使用Modelsim对触发器进行仿真,到底应该怎样写testbench?
dff_test.v
- module dff_test
- (
- CLK,
- D,
- Q
- );
- input CLK;
- input D;
- output Q;
- reg Q;
- always@(posedge CLK)
- begin
- Q <= D;
- end
- endmodule
dff_test_tb.v
- module dff_test_tb ;
-
- reg D ;
- wire Q ;
- reg CLK ;
-
- dff_test
- DUT (
- .D (D ) ,
- .Q (Q ) ,
- .CLK (CLK ) );
- initial
- begin
- CLK = 1'b0;
- #500;
- forever #50 CLK = ~CLK;
- end
- initial
- begin
- D = 1'b0;
- #3000;
- @(posedge CLK);
- D = 1'b1;
- #10000;
- @(posedge CLK);
- D = 1'b0;
- #110;
- @(posedge CLK);
- D = 1'b0;
- end
- endmodule
我认为仿真的结果Q应该比D迟一个时钟节拍,但是仿真的结果却如下图所示
Q并没有比D迟一个时钟节拍。难道是@(posedge CLK)这种等待时钟沿的方法没有使D信号的产生发生在CLK的上升沿之后?
请大家赐教,谢谢!
你对触发器的验证激励,就不用写等待时钟了,只要提供电平和时间即可。触发的东西交给你的设计去采集边沿了。把@的都去掉,没必要加入同步机制。
2# gaurson
gaurson,谢谢你的回复!
你的意思是说去掉@语句,只用延迟吗?那么如果我的时钟初始值是0,从时间0就开始产生,并且周期是100,那么在比如150,250,1050等等这样和时钟上升沿同步的时刻改变信号D的值,这个被改变的值是立刻会被触发器采到的,从仿真结果上来看也是没有延迟一拍的,除非我把这个信号的改变推迟一点,稍晚于时钟的上升沿。
如果是功能仿真的话,一般都是这样的。只要输入的数据都是同一时刻产生的,基本能采样到。
4# gaurson
gaurson,十分感谢!我还有问题继续请教。
如果真如之前所说,这样的激励写法会让和时钟上升沿同时改变的信号在刚刚改变时就被时钟采到,那么如果有一个信号是D和Q运算产生的,那么这个信号的仿真结果是和预期的结果不符的啊
请看如下
dff_tb.v
- module dff_test
- (
- CLK,
- D,
- Q
- );
- input CLK;
- input D;
- output Q;
- reg Q;
- wire A;
- assign A = Q & (~D);
- always@(posedge CLK)
- begin
- Q <= D;
- end
- endmodule
dff_test_tb.v
- module dff_test_tb ;
-
- reg D ;
- wire Q ;
- reg CLK ;
- dff_test
- DUT (
- .D (D ) ,
- .Q (Q ) ,
- .CLK (CLK ) );
- initial
- begin
- CLK = 1'b0;
- forever #50 CLK = ~CLK;
- end
- initial
- begin
- D = 1'b0;
- #150;
- D = 1'b1;
- #300;
- D = 1'b0;
- end
- endmodule
仿真结果
本意是想在D信号的下降沿后产生一个一时钟周期宽度的脉冲,现在的仿真结果只是一个刺,这样的话对后级使用A信号的电路是不是就产生了影响?
请赐教!
如果D的产生一定要跟CLK的上升沿相关的话,用第一种testbench,并改为非阻塞赋值:D <= 1'b1 和 D<= 1'b0.
6# yongfenr
感谢yongfenr!
我使用了非阻塞赋值,的确解决了问题,就是对其中的原因还不是很明白。
问个简单的问题:
我写的test程序仿真时,波形图为什吗只能防出输入波形(TEST里写的),但相应的输出波形没有?
你调用要仿真的模块了么?
謝謝分享
阻塞语句是立即赋值,也就是说,在同一时刻,其他语句会在执行完该语句后再执行。
而非阻塞语句是下个时钟沿赋值,在同一时刻其他语句和该语句是同时执行吧。
我也不太清楚,但感觉应该是这个原因
阻塞语句对应于组合逻辑,既然你是时钟出发的,就要用非阻塞语句
最近也看到这块,时序电路一定要用非阻塞赋值
那我什么时候用在testbench用非阻塞赋值?