宋桓公

inout仿真终极方案

0
阅读(3474)

仿真inout确实是个麻烦事,同一个端口,既要写TestBeach输入激励信号,又要观察输出的响应信号。但是往往,就看到了自己 的输入激励,而看不到响应信号,今天就通过一个例子,提出一个简单的仿真方案。
首先,建模部分如下:

1:moduleinout_test
2:(
3:inputCLK,
4:inputRSTn,
5:
6:inout[31:0] pci_ad
7:);
8:
9:parameterread_ad = 1'b0;
10:parameter write_ad = 1'b1;
11:
12:reg pci_ad_oe;
13:reg [31:0]pci_dat_out;
14:assign pci_ad = pci_ad_oe ? pci_dat_out : 32'bZ;
15:
16:reg [3:0]i;
17:always @(posedge CLK or negedge RSTn)
18:if(!RSTn)
19:begin
20:i <= 4'd0;
21:pci_ad_oe <= read_ad;
22:pci_dat_out <= 32'd0;
23:end
24:else
25:case(i)
26:0:
27:begin
28:pci_ad_oe <= read_ad;
29:i <= i + 1'b1;
30:end
31:1:
32:begin
33:i <= i + 1'b1;
34:end
35:2:
36:begin
37:i <= i + 1'b1;
38:end
39://------
40:3:
41:begin
42:pci_ad_oe <= write_ad;
43:pci_dat_out <= 32'd33;
44:i <= i + 1'b1;
45:end
46:4:
47:begin
48:pci_dat_out <= 32'd44;
49:i <= i + 1'b1;
50:end
51:5:
52:begin
53:pci_dat_out <= 32'd55;
54:i <= i + 1'b1;
55:end
56:6:
57:begin
58:pci_dat_out <= 32'd66;
59:end
60:
61:endcase
62:
63:endmodule


观察程序:inout [31:0] pci_ad; pci_ad声明为inout变量。
而是关键实现输入输出的语句是:
assign pci_ad = pci_ad_oe ? pci_dat_out : 32'bZ;

当变量 pci_ad_oe == 1 时,pci_ad作为输出端口,将pci_dat_out的值输出,
此时控制pci_dat_out就能控制pci_ad的输出。

当 pci_ad_oe == 0 时,pci_ad作为输入端口,此时pci_dat_out对端口不再
产生影响,能影响pci_ad的只能是外部的激励(输入信号)。

接着看程序,步骤0,1,2,(即当i为0,1,2)时pci_ad作为输入端口,
接收外部的激励信号;步骤3,4,5,6时,pci_ad作为输出端口,输出
响应信号。

建模部分完毕,接着编写TestBeach:

1:`timescale 1 ps/ 1 ps
2:moduleinout_test_vlg_tst();
3:
4:reg CLK;
5:reg RSTn;
6:reg [31:0] treg_pci_ad;
7:
8:wire [31:0] pci_ad;
9:
10:assign pci_ad = treg_pci_ad;
11:
12:inout_test i1 (
13:.CLK(CLK),
14:.RSTn(RSTn),
15:.pci_ad(pci_ad)
16:);
17:
18:initial
19:begin
20:RSTn = 0; #10 RSTn = 1;
21:CLK = 1; forever #5 CLK = ~CLK;
22:end
23:
24:reg [3:0]Ti;
25:always @(posedge CLKornegedge RSTn)
26:if(!RSTn)
27:begin
28:Ti <= 4'd0;
29:end
30:else
31:case(Ti)
32:0:
33:begin
34:treg_pci_ad <= 32'd1;
35:Ti <= Ti + 1'b1;
36:end
37:1:
38:begin
39:treg_pci_ad <= 32'd2;
40:Ti <= Ti + 1'b1;
41:end
42:2:
43:begin
44:treg_pci_ad <= 32'd3;
45:Ti <= Ti + 1'b1;
46:end
47:3:
48:begin
49:treg_pci_ad <= 32'd4;
50:Ti <= Ti + 1'b1;
51:end
52:4:
53:begin
54:treg_pci_ad <= 32'd5;
55:Ti <= Ti + 1'b1;
56:end
57:5:
58:begin
59:treg_pci_ad <= 32'd6;
60:Ti <= Ti + 1'b1;
61:end
62:6:
63:begin
64:treg_pci_ad <= 32'd7;
65:end
66:
67:endcase
68:
69:endmodule

首先,说明在建模完成之后,我喜欢自动生成TestBeach,这样的好处是他会根据你的建模程序,
自动生成变量声明,正好和你的建模一一对应,而不用自己一个个声明。当然主体测试程序还是
得自己编写。具体步骤方法如下图所示:

image_thumb[33]

接着看,TestBeach的具体内容:

assign pci_ad = treg_pci_ad;这句也自动生成的,每当你声明了一个inout端口,他就会自动生成
一个变量,这个变量的命名方法就是在你的inout变量名字前加一个“treg_”前缀。这个变量的作用
就是让你模拟激励信号的。也就是说,inout的输入信号就靠他了。

回头看看建模部分,有步骤i(0~6),共7个,同样在TestBeach有步骤Ti(0~6)共7个,且

他们是 一一对应的,不理解这个对应关系不要紧,我想把仿真图调出来给您瞧瞧:

image_thumb[17]

没错他们在时钟上是一一对应的。我们记得在建模时,步骤0,1,2,总线是作为输入状态的,此时
可观察激励信号,步骤3,4,5,6是输出时刻,观察响应信号。

而在,TestBeach中Ti的7个步骤全部是输入激励信号。于是我们猜测,在步骤0,1,2时,我们看到是
激励信号,也就是treg_pci_ad的值——分别是0,1,2。而步骤3,4,5,6时treg_pci_ad的值不再起
作用,我们看到的应该是响应信号pci_dat_out的值33,44,55,66。是不是这样呢,我们继续看仿真
图:

image_thumb[35]

我们发现,激励值是看到了,没错是1,2,3,但是pci_ad_oe拉高之后,我们只能看到一堆XX,而看不
到响应信号的值,这就是我们之前说所说的:“看到了自己的输入激励,而看不到响应信号”,了解到这个
问题之后,要解决这个问题其实不难,只要在建模里加上两句话即可:

output [31:0] Tout_pci_ad,//用于观察总线的输出信号

assign Tout_pci_ad = pci_ad_oe ? pci_dat_out : 32'bZ;

也就是新增一个输出,信号Tout_pci_ad专门用于观察pci_ad的输出响应值,由于新增了引脚输出,编译后,
别忘了从新生成TestBeach(温馨提示:在此之前,请另存TestBeach的主体控制代码,免得被从新写,呵呵!)
这样的话输入输出就能看啦:

image_thumb[37]

总结:原本的是inout端口,仅仅能作为输入端口,观察激励信号,想观察输出的响应的,需另外加上Tout_输出
信号专门用于观察输出信号。

需要修改后完整程序的话,留下邮箱,我发给您。

技术讨论欢迎加群~~电子技术协会 362584474

Baidu
map