weiqi7777

关于verilog仿真使用#和@的仿真结果不同的研究

0
阅读(5562)

最近仿真一段很奇怪的代码,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

clip_image002

代码中,使用#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)

仿真结果如下所示:

clip_image004

可看出,此刻在时钟上升沿变化的en信号是无效的,输出不变,要等一个时钟周期后,输出才会等于输入,这与我们想的结果是一致的。。。

看来,仿真中,对于#和@这两个延时的仿真结果是有区别的,特别是对于在时钟上升沿时刻变化的信号,这应该是仿真器有关系的。采用@延时比较准确,因为这样仿真的结果才和预想的一样。因为在实际中,寄存器的输入判断,是判断在时钟边沿之前一刻的输入值。

Baidu
map