关于verilog仿真使用#和@的仿真结果不同的研究
0赞最近仿真一段很奇怪的代码,testbench中分别使用#和@,但是输出波形不一致。
代码如下;
module jdshfks(
input clk,
input en ,
input rst_n,
input [3:0] a,
output reg [3:0] b
);
always@( posedge clk ) begin
if( !rst_n )
begin
b <= 4'b0;
end
else
begin
if( en )
b <= a;
else
b <= b;
end
end
endmodule
其功能:当en信号有效,输出等于输入。否则输出保持。
其测试代码如下:使用的是ise自带的isim仿真器仿真。
`timescale 1ns / 1ps
module fdfsdf;
// Inputs
reg clk;
reg en;
reg rst_n;
reg [3:0] a;
// Outputs
wire [3:0] b;
parameter period = 2'd2;
// Instantiate the Unit Under Test (UUT)
jdshfks uut (
.clk(clk),
.en(en),
.rst_n(rst_n),
.a(a),
.b(b)
);
always #(period/2) clk = ~clk;
initial begin
clk = 1;
en = 0;
rst_n = 0;
a = 5;
#10 rst_n = 1;
#period en = 1;
repeat(10)
begin
#period a = ($random)%16;
end
end
endmodule
代码中,使用#period延时一个时钟。
从波形图中,可看出,en在时钟上升沿变化为1,但是此时输出为输入,表示此时输入的en信号有效。但是实际上,此时判定的en信号是无效的,因为是在时钟上升沿时刻刚好变为1,则此刻认为的en信号值应该为时钟上升沿之前一点的en值。也就是为0,那么输出就不应该马上变化,而是要延迟一个时钟周期后再变化。
这个问题真是百思不得其解,采用modelsim仿真,结果也是这样。采用单步调试功能,发现en变化是有效的。即在时钟上升沿时刻的en值改变,此刻仿真认为的en的值为变化后的en值,为1,所以输出马上变化了。
改写testbench,采用@(posedge clk)替换延时一个时钟周期。
仿真代码如下:采用的还是ISE的isim仿真。
`timescale 1ns / 1ps
module fdfsdf;
// Inputs
reg clk;
reg en;
reg rst_n;
reg [3:0] a;
// Outputs
wire [3:0] b;
parameter period = 2'd2;
// Instantiate the Unit Under Test (UUT)
jdshfks uut (
.clk(clk),
.en(en),
.rst_n(rst_n),
.a(a),
.b(b)
);
always #(period/2) clk = ~clk;
initial begin
// Initialize Inputs
clk = 1;
en = 0;
rst_n = 0;
a = 5;
#10 rst_n = 1;
#10
@(posedge clk) en = 1;
repeat(10)
begin
@(posedge clk) a = ($random)%16;
end
end
endmodule
其实就是将第一个的testbench的#period换成了@(posedge clk)
仿真结果如下所示:
可看出,此刻在时钟上升沿变化的en信号是无效的,输出不变,要等一个时钟周期后,输出才会等于输入,这与我们想的结果是一致的。。。
看来,仿真中,对于#和@这两个延时的仿真结果是有区别的,特别是对于在时钟上升沿时刻变化的信号,这应该是仿真器有关系的。采用@延时比较准确,因为这样仿真的结果才和预想的一样。因为在实际中,寄存器的输入判断,是判断在时钟边沿之前一刻的输入值。