问题:为什么得到结果滞后了几个时钟周期
Verilog语言是硬件描述语言,电流通过电路会产生延时。我们通过clk时钟将延时控制在可控的范围内。那么,Verilog延时有什么规律呢?
在此我先给出结论:在always模块中,如果某步操作需要用到之前操作的结果,那么在这一步会产生一个时钟周期的延时。
规避方法是,将某些步骤改成assign,或者用阻塞赋值
下面以两位有符号数乘法举例,说明延时产生的机理以及规避措施
这是无延时乘法器
`timescale 1ns / 1ps
module MULT2(
input clk,
input reset,
input [1:0]a,
input [1:0]b,
output [3:0]z
);
wire [3:0]aa,bb;
reg [7:0]temp0,temp1,temp2,temp3;
wire[7:0]rul;
reg f;
//位扩展
assign aa = {{2{a[1]}},a};
assign bb = {{2{b[1]}},b};
always@(posedge clk or posedge reset)
if(reset)
f <= 0;
else
begin
temp0 <= bb[0] ? {{4{aa[3]}},aa} :8'b0;
temp1 <= bb[1] ? {{3{aa[3]}},aa,1'b0} :8'b0;
temp2 <= bb[2] ? {{2{aa[3]}},aa,2'b0} :8'b0;
temp3 <= bb[3] ? {{1{aa[3]}},aa,3'b0} :8'b0;
f<=1;
end
assign rul=temp0+temp1+temp2+temp3;
assign z = f ? temp0+temp1+temp2+temp3: 4'b0;
endmodule
下面是延时两个时钟周期
延时三个时钟周期
这是因为非阻塞赋值每步操作都是同时进行的,等第一步算出结果后,第二步已经无意义地执行过了,第一步的结果只有一个时钟周期后才能用到。
那么如何避免延时呢?
解决方法正如无延时的代码,用assign代替非阻塞赋值。因为assign对wire线网型进行操作,在真正的硬件电路中,线网型相当于导线,会在always模块前完成。
或者用阻塞赋值 =