天天看點

FPGA學習筆記---Verilog延遲語句分析比較

       在Verilog語言中經常要用到延時語句,延時語句添加的位置不同,輸出的結果就會不同。今天就來分析比較一下延時語句在不同位置時,對指派語句的影響。

一、阻塞式左延時指派

檔案代碼:

`timescale 1ns/1ns
module delay(
    a,
    b,
    sum
);
    input [3:0] a;
    input [3:0] b;
    output reg [4:0] sum;   
//阻塞式左延時指派語句
always @(*) begin
    #12 sum = a + b;
end
endmodule
           

測試代碼

`timescale 1ns/1ns
module delay_tb;
    reg [3:0] a;
    reg [3:0] b;
    wire [4:0] sum; 

delay delay(
    .a(a),
    .b(b),
    .sum(sum)
);
    initial begin
    a = 0; b = 0;
    #5;
    a = 1; b = 1;
    #5;
    a = 2; b = 2;
    #5;
    a = 3; b = 3;
    #5;
    a = 4; b = 4;
    #5;
    a = 5; b = 5;
    #5;
    a = 6; b = 6;
    #5;
    a = 7; b = 7;
    #5;
    a = 8; b = 8;
    #5;
    a = 9; b = 9;
    #5;
    a = 10; b = 10;
    #5;
    
    #30;    
    $stop;
    end
endmodule
           

a、b的值5ns改變一次,通過阻塞式語句讀取a、b的和,延時語句加在左側。

仿真波形如下:

FPGA學習筆記---Verilog延遲語句分析比較

       通過波形可以看到初始化之後,a、b的值每5ns變化一次,在第12ns時,sum輸出a+b的和為4,說明在延時時間到了之後,才取a和b的值計算,然後更新給sum。執行完阻塞指派語句後,程式退出always塊,等待下一次資料變化。在第15ns時,a、b的值又發生了變化,延時等待12ns後,在第27ns取出a和b的值并計算,然後更新給sum。也就是說延時語句在阻塞指派左側時,在延時時候到了之後,系統更新右值同時指派給左值。sum總是為a和b最新值的和。

二、阻塞式右延時指派

代碼修改如下:

`timescale 1ns/1ns
module delay(
    a,
    b,
    sum
);
    input [3:0] a;
    input [3:0] b;
    output reg [4:0] sum;   
//阻塞式右延時指派語句
always @(*) begin
    sum = #12 a + b;
end
endmodule
           

測試代碼保持不變,仿真波形如下:

FPGA學習筆記---Verilog延遲語句分析比較

       通過仿真波形可以看出,在第12ns的時候,sum輸出值為0,說明初始化之後,程式進入always塊中計算a+b值,延時等待12ns之後,再将值更新給sum。雖然此時a和b的值都變為了2。但是計算的依然是12ns之前的值。計算完成之後推出always塊,當第15ns時,a、b的值發生了變化,又進入always塊中計算此時a+b的值,等待12ns之後,也就是在第27ns時将結果6指派給sum。由此可以看出,當延時語句在阻塞指派右邊時,更新的是延時之前的值。在延時等待過程中資料發生變化時将會被忽略。

三、非阻塞式左延時指派

修改代碼如下:

`timescale 1ns/1ns
module delay(
    a,
    b,
    sum
);
    input [3:0] a;
    input [3:0] b;
    output reg [4:0] sum;
//非阻塞式左延時指派語句
always @(*) begin
    #12 sum <= a + b;
end
endmodule
           

測試代碼不變,仿真波形如下:

FPGA學習筆記---Verilog延遲語句分析比較

         通過波形可以看到,系統初始化之後a、b的值5ns變化一次,在第12ns時sum結果為4。說明計算的是a、b的最新值。在第15ns時,a、b的值發生了更新,延時12ns後,也就是第27ns,讀取a、b目前最新值,計算累加和指派給sum輸出。由此可看到延時加在非阻塞指派左側時,在延時時間到了之後,讀取a、b最新值并計算累加和。

四、非阻塞式右延時指派

修改代碼如下:

`timescale 1ns/1ns
module delay(
    a,
    b,
    sum
);
    input [3:0] a;
    input [3:0] b;
    output reg [4:0] sum;   
//非阻塞式右延時指派語句
always @(*) begin
    sum <= #12 a + b;
end
endmodule
           

測試代碼不變,仿真波形如下:

FPGA學習筆記---Verilog延遲語句分析比較

通過波形可以看出,初始化之後a、b的值每5ns更新一次,在第12ns時sum值為0,說明計算的是0ns時a、b的值。在第17ns時,sum值為2,說明計算的是第5ns時,a、b的值。後面的值以此類推,說明sum的值統一延遲的12ns。但是每次a、b的變化都被捕捉到了。說明延時加在非阻塞指派的右側時,輸出結果會統一延遲。但是不會漏掉任何一次資料變化。

五、連續指派

修改代碼如下:

`timescale 1ns/1ns
module delay(
    a,
    b,
    sum
);
    input [3:0] a;
    input [3:0] b;
    output [4:0] sum;
assign #12 sum =  a + b;
endmodule
           

測試不變,仿真波形如下:

FPGA學習筆記---Verilog延遲語句分析比較

由波形圖可以看出,當a、b停止變化後12ns,sum才會輸出最後一次a+b的值。

通過上面幾種延時方法比較,可以看出,延時在不同語句中不同位置,輸出結果也不相同。