功能要求如下:复位后,din_vld 不定时等于1,当din_vld出现3个或超过3个周期的高电平脉冲时,将第三个周期时对应的din值赋给dout,其他时候dout保持不变。
根据功能要求,写出代码后用modelsim进行仿真,效果如下图:
然后发现仿真的波形和我们预期的波形并不一致!!
计数器cnt在din_vld == 0 的时候就已经开始计数了。
查看代码,计数器cnt的加一条件是:add_cnt = din_vld == 1 && flag == 0 。
也就是说,信号din_vld在时钟上升沿处由0变1的时候,仿真软件把信号din_vld的值取为1了。
那么会出现这种情况的原因是什么呢?
这里是软件仿真,是软件模拟真实的电路情况。但是,软件模拟是有缺陷的,无论软件如何模拟,本质上它都是串行执行的代码,是一条一条指令执行的。
在仿真文件里,有两个initial语句,一个是产生时钟的,一个是产生din_vld的,如下图。
按照verilog的语法,这两个initial是并行执行的。但事实上软件执行是有先后的。很有可能先执行了din_vld变1的代码,再执行了clk由0变1的代码,这种情况下,在时钟的上升沿就会采到din_vld为1,因此就会出现案例中的错误。
这是与FPGA实际的电路是不符合的,也就是说这个其实是仿真缺陷的问题,而不是设计问题。
虽然不是设计问题,但仿真仍然要继续,我们需要避免这种情况。如何避免呢?
解决上述问题的方法:我们可以在测试文件中给信号加上一个1ns 的延时,这样两个initial语句就绝对不会同时执行。
代码如下图:
用modelsim重新编译一下再仿真,此时的波形就是功能要求的正确结果。如下图:
问题解决,更多FPGA相关问题欢迎加Q:1479512800肖肖肖 互相讨论!