实现功能:


标题首先我遇到的问题是,所有信号变化与时钟上升沿对齐,所以时钟上升沿时候,这些信号该如何取值?
以第三个时钟上升沿为例,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)begin
dout<=1'b0;
end
else begin
dout<=a*b*c*d;
end
end
always@(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 begin
clk=1;
#1;
forever #(CYCLE/2)clk=~clk;
end
initial begin
rst_n=1;
#(1) rst_n=0;
#(RST_TIME) rst_n=1;
end
integer 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
end
initial begin
vld_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 begin
clk=1;
#1;
forever #(CYCLE/2)clk=~clk;
end
initial begin
rst_n=1;
#(1) rst_n=0;
#(RST_TIME) rst_n=1;
end
integer 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
end
initial begin
vld_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。
版权声明:本文为kongbeiruhai原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。