赋值和非阻塞赋值的区别。"/>
Verilog实现信号对齐,并且打一拍。以及测试文件中阻塞赋值和非阻塞赋值的区别。
实现功能:
标题首先我遇到的问题是,所有信号变化与时钟上升沿对齐,所以时钟上升沿时候,这些信号该如何取值?
以第三个时钟上升沿为例,a信号在这一时刻该取1还是取2?
a信号在第三个时钟上升沿前一点时间取值,所以a信号取值为1;同理,b信号取值为3,c信号取值为5,d信号取值为2.
也就是说在时钟上升沿时刻,一般信号采样会采该信号前面一点点时刻所对应的值。
如何打一拍
“打一拍”是指信号延迟一个时钟周期。
我们可以看到,vld_out是vld_in打一拍输出后的结果,那么如何进行打拍呢?
使用D触发器即可实现打一拍。
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)vld_out<=1'b0;
else vld_out<=vld_in;
end
设计文件代码
该代码上述功能要求:
module four_data_multiply(
clk ,
rst_n ,
vld_in ,
a ,
b ,
c ,
d ,
vld_out,
dout
);//参数定义
parameter DATA_W = 4;
parameter DATA_O_W = 16;//输入信号定义
input clk ;
input rst_n ;
input vld_in ;
input[DATA_W-1:0] a ;
input[DATA_W-1:0] b ;
input[DATA_W-1:0] c ;
input[DATA_W-1:0] d ;
//输出信号定义
output[DATA_O_W-1:0] dout ;
output vld_out;
//输出信号reg定义
reg [DATA_O_W-1:0] dout ;
reg vld_out;
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begindout<=1'b0;
end
else begin dout<=a*b*c*d;
end
endalways@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)vld_out<=1'b0;
else vld_out<=vld_in;
end
endmodule
测试文件中阻塞赋值和非阻塞赋值区别
在Verilog眼中无论testbench、dut还是assertion都是code。
所以先把code吃进来,然后有一个时间轴参数,仅仅处理set t = 0时刻的code.这个code有阻塞语句、$display、assignment…0时刻还有#0语句、在处理非阻塞的LHS、最后monitor语句。
当我的测试文件是使用非阻塞赋值
`timescale 1ns / 1ps
module testBench();reg clk ;reg rst_n ;reg vld_in;reg[3:0] a ;reg[3:0] b ;reg[3:0] c ;reg[3:0] d ;wire[15:0] dout ;parameter CYCLE=10 ; parameter RST_TIME=2 ;four_data_multiply test(.clk(clk) ,.rst_n(rst_n) ,.vld_in(vld_in) ,.a(a) ,.b(b) ,.c(c) ,.d(d) ,.vld_out(vld_out),.dout(dout));initial beginclk=1;#1;forever #(CYCLE/2)clk=~clk;endinitial beginrst_n=1;#(1) rst_n=0;#(RST_TIME) rst_n=1;endinteger i;initial begin #(1);for(i=0;i<6;i=i+1)begin #(CYCLE);a<=i;b<=i+1;c<=i+2;d<=i+3;end endinitial beginvld_in<=0;#(CYCLE*2+1);vld_in<=1; #(CYCLE*2);vld_in<=0;#(CYCLE*1);vld_in<=1;#(CYCLE*1);vld_in<=0;end
endmodule
然后我的仿真结果如下所示:
可以完成该要求。
当我的测试文件使用阻塞赋值:
`timescale 1ns / 1ps
module testBench();reg clk ;reg rst_n ;reg vld_in;reg[3:0] a ;reg[3:0] b ;reg[3:0] c ;reg[3:0] d ;wire[15:0] dout ;parameter CYCLE=10 ; parameter RST_TIME=2 ;four_data_multiply test(.clk(clk) ,.rst_n(rst_n) ,.vld_in(vld_in) ,.a(a) ,.b(b) ,.c(c) ,.d(d) ,.vld_out(vld_out),.dout(dout));initial beginclk=1;#1;forever #(CYCLE/2)clk=~clk;endinitial beginrst_n=1;#(1) rst_n=0;#(RST_TIME) rst_n=1;endinteger i;initial begin #(1);for(i=0;i<6;i=i+1)begin #(CYCLE);a=i;b=i+1;c=i+2;d=i+3;end endinitial beginvld_in=0;#(CYCLE*2+1);vld_in=1;#(CYCLE*2);vld_in=0;#(CYCLE*1);vld_in=1;#(CYCLE*1);vld_in=0;end
endmodule
仿真结果如下:
可以看出,虽然我在设计文件里写了打拍节奏,然而依然没有实现打拍。
原因如下:
在Verilog眼中无论testbench、dut还是assertion都是code。所以先把code吃进来,然后有一个时间轴参数,仅仅处理set t = 0时刻的code.这个code有阻塞语句、$display、assignment…0时刻还有#0语句、在处理非阻塞的LHS、最后monitor语句。
所以当使用阻塞赋值时,在时钟上升沿时,首先执行阻塞赋值,然后信号采样阻塞赋值的结果。
所以当使用非阻塞赋值时,在时钟上升沿时,信号采样非阻塞赋值的前一时刻的结果,等到采样结束,才执行非阻塞赋值的LHS。
更多推荐
Verilog实现信号对齐,并且打一拍。以及测试文件中阻塞赋值和非阻塞赋值的区别。
发布评论