前言提前给出一些观点:
仿真是为了仿真,所以不要设置极限情况,例如在时钟上升沿通过阻塞赋值给数据,应该避免这种情况;各种不同的仿真软件对时钟上升沿通过阻塞赋值给数据的理解不一致,例如modelsim和isim;可以使用非阻塞赋值设置数据值,避免在时钟上升沿时刻使用阻塞赋值给数据。本文最后会给出推荐的仿真观点。
实践分析事实上,上面三点说的是针对一种情况,我们举一个简单的例子说明。我们的设计文件,很简单,就是一个检测上升沿的程序:
`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////// engineer: reborn lee// website : https://blog.csdn.net/reborn_lee//////////////////////////////////////////////////////////////////////////////////module delay( input wire in, input wire clk, input wire rst, output reg out_r3 ); reg in_reg; always@(posedge clk) begin if(rst) begin in_reg <= 0; end else begin in_reg <= in; end end wire mid_pos; assign mid_pos = ~in_reg & in; reg reg_pos; reg reg1_pos; reg reg2_pos; always@(posedge clk) begin if(rst) begin reg_pos <= 0; reg1_pos <= 0; reg2_pos <= 0; out_r3 <= 0; end else begin reg_pos <= mid_pos; reg1_pos <= reg_pos; reg2_pos <= reg1_pos; out_r3 <= reg2_pos; end end endmodule如下,我们的testbench为:
`timescale 1ns / 1ps// engineer: reborn lee// website : https://blog.csdn.net/reborn_leemodule sim_delay; reg clk; reg rst; reg in; wire out_r3; initial begin clk = 0; forever begin #5 clk = ~clk; end end initial begin rst = 1; in = 0; #20 rst = 0; #100 @(posedge clk) begin in = 1; end #300 in = 0; end delay delay_inst( .in(in), .clk(clk), .rst(rst), .out_r3(out_r3) ); endmodule我们对输入进行赋值:
@(posedge clk) begin in = 1; end可见,使用的是阻塞赋值,且在时钟上升沿赋值;
在这种情况下,我们使用vivado自带的仿真工具仿真,得到结果如下:
isim仿真工具
可见,得不到上升沿,这我们其实也能理解;由于是行为仿真,所以,一切都是理想的,不考虑延迟;我们使用阻塞赋值在时钟上升沿时刻给输入赋值,立即生效;固然,我们的时钟在上升沿采样的时候,得到in_reg和in是同边沿的,这样自然就得不到边沿了,后面延迟多拍也自然无用。
这是vivado的仿真工具isim对这种情况的理解。
现在问题来了,当我们使用modelsim进行仿真的时候,情况是这样的:
modelsim仿真工具
它会对in延迟一整拍,也就是要给时钟,最终也就能得到上升沿了。同样的设计,同样的仿真文件,为何会出现这样的差异呢?这里给出的解释是仿真工具对这种情况的理解问题:在实际情况中(考虑真实环境,存在延迟),这种输入的边沿出现在时钟的有效沿,本身就是不合法的,因为这会导致时序通过不了,例如建立时间。对于这种情况,modelsim或者questasim的处理就比较直接,我不准出现这种情况,如果你出现了,我们认为此刻无效。其效果类似于非阻塞赋值:
@(posedge clk) begin in <= 1; end这里使用了非阻塞赋值,那么在时钟上升沿时刻,in的值就没那么快生效,如此,无论在那个平台仿真,仿真情况都一致了。
下面是这种情况下在任意平台的仿真图:
任意平台
推荐的仿真设计开门见山,在时钟有效沿时刻给数据是不符合实际的,是极端的做法,这在实际情况中不会出现,即使出现,综合布线工具也会重新布线避免这种情况,否则就是时许违规。因此为了有意义的仿真且统一仿真平台,我们应该在距离有效沿一定延迟给数据,例如:
#100 @(posedge clk) begin #1 in = 1; end或者:
#100 @(negedge clk) begin in = 1; end总之,别在有效沿给数据,以这种情况为例,给出仿真图:
#100 @(posedge clk) begin #1 in = 1; end
推荐的仿真方式
总结从上面的分析可以看出,为了适应不同的仿真平台(并不是说哪个仿真平台错了) ,且本着仿真意义的实际情况,我们不应该在极端的情况下进行仿真,不仅没有意义,而且让人疑惑。推荐的做法是在下降沿或者距离时钟的上升沿有一定的延迟给数据,这才能避开不同平台的差异且有实际意义。
接收机与频谱分析仪在EMC测试应用的差异
浅谈空间光学系统内部的杂散辐射分析
学编程经历哪些阶段 如何度过编程迷茫期
生活好帮手:手机上的AR尺子
吉利汽车在发动机热效率方面的前瞻技术取得新突破
关于行为仿真的一点观点
东芝出售资产填补亏损已成习惯 这次是NAND闪存电脑芯片
雷布斯的红米Note对飚诺基亚6,“情怀”相近,只是岁岁年年“机”不同
OPPO Reno系列手机已经成功入网支持10倍变焦并有望采用三摄像头
基于“响应性液体门控技术”在水界面上高效过滤与吸收的核心机制
Golang实现一个简单的http代理
三星Galaxy S8/S8 Plus齐曝光 这么大的屏占比心动吗?
氧化镓产业化更进一步,本土初创企业成果涌现
黑鲨游戏手机2Pro开启预约 7月30日正式发布
华为鸿蒙一向死而生!
关于自动虫情测报灯配置的详细讲解
企业使用刷脸识别有什么好处?
气密性检测仪在汽车行业的应用
镀锌翅片管散热器的详细介绍
索尼成立Sony AI部门 推动人工智能的基础研究和开发