美文网首页
FPGA学习笔记---Verilog延迟语句分析比较(转)

FPGA学习笔记---Verilog延迟语句分析比较(转)

作者: 浙南旧事 | 来源:发表于2021-05-30 20:21 被阅读0次

版权声明:本文为CSDN博主「单片机学习经验交流」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_20222919/article/details/107576195

在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的和,延时语句加在左侧。

仿真波形如下:


20200725113704354.jpg

通过波形可以看到初始化之后,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

测试代码保持不变,仿真波形如下:


20200725134011501.jpg

通过仿真波形可以看出,在第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

测试代码不变,仿真波形如下:


20200725135035930.jpg

通过波形可以看到,系统初始化之后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

测试代码不变,仿真波形如下:


20200725135950940.jpg

通过波形可以看出,初始化之后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

测试不变,仿真波形如下:


20200725144520441.jpg

由波形图可以看出,当a、b停止变化后12ns,sum才会输出最后一次a+b的值。

通过上面几种延时方法比较,可以看出,延时在不同语句中不同位置,输出结果也不相同。

相关文章

网友评论

      本文标题:FPGA学习笔记---Verilog延迟语句分析比较(转)

      本文链接:https://www.haomeiwen.com/subject/poemsltx.html