电子说
提前给出一些观点:
本文最后会给出推荐的仿真观点。
事实上,上面三点说的是针对一种情况,我们举一个简单的例子说明。我们的设计文件,很简单,就是一个检测上升沿的程序:
`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_Lee
module 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
推荐的仿真方式
从上面的分析可以看出,为了适应不同的仿真平台(并不是说哪个仿真平台错了) ,且本着仿真意义的实际情况,我们不应该在极端的情况下进行仿真,不仅没有意义,而且让人疑惑。推荐的做法是在下降沿或者距离时钟的上升沿有一定的延迟给数据,这才能避开不同平台的差异且有实际意义。
全部0条评论
快来发表一下你的评论吧 !