inout仿真终极方案
0赞
仿真inout确实是个麻烦事,同一个端口,既要写TestBeach输入激励信号,又要观察输出的响应信号。但是往往,就看到了自己 的输入激励,而看不到响应信号,今天就通过一个例子,提出一个简单的仿真方案。
首先,建模部分如下:
1: module inout_test
2: (
3: input CLK,
4: input RSTn,
5:
6: inout [31:0] pci_ad
7: );
8:
9: parameter read_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: module inout_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 CLK or negedge 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,这样的好处是他会根据你的建模程序,
自动生成变量声明,正好和你的建模一一对应,而不用自己一个个声明。当然主体测试程序还是
得自己编写。具体步骤方法如下图所示:
接着看,TestBeach的具体内容:
assign pci_ad = treg_pci_ad;这句也自动生成的,每当你声明了一个inout端口,他就会自动生成
一个变量,这个变量的命名方法就是在你的inout变量名字前加一个“treg_”前缀。这个变量的作用
就是让你模拟激励信号的。也就是说,inout的输入信号就靠他了。
回头看看建模部分,有步骤i(0~6),共7个,同样在TestBeach有步骤Ti(0~6)共7个,且
他们是 一一对应的,不理解这个对应关系不要紧,我想把仿真图调出来给您瞧瞧:
没错他们在时钟上是一一对应的。我们记得在建模时,步骤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。是不是这样呢,我们继续看仿真
图:
我们发现,激励值是看到了,没错是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的主体控制代码,免得被从新写,呵呵!)
这样的话输入输出就能看啦:
总结:原本的是inout端口,仅仅能作为输入端口,观察激励信号,想观察输出的响应的,需另外加上Tout_输出
信号专门用于观察输出信号。
需要修改后完整程序的话,留下邮箱,我发给您。
技术讨论欢迎加群~~电子技术协会 362584474