FPGA仿真中阻塞赋值(=)和非阻塞赋值(<=)区别

FPGA仿真中阻塞赋值和非阻塞赋值的区别

单独仿真小模块对但将小模块加入整个工程仿真不对就有可能是没有注意到仿真中阻塞赋值和非阻塞赋值的区别

目录

前言

一、简介

二、设计实例

三、仿真实例

1、仿真用非阻塞赋值

2、仿真用阻塞赋值

总结


前言

网上很多人介绍verilog语法中的阻塞赋值和非阻塞赋值几乎都是基于设计module介绍的,很少从testbench仿真module介绍。笔者在仿真的时候,尤记得老师说过仿真时用=和<=没区别,但其实区别很大,如果仿真时不加以区分,单独仿真小模块对但将小模块加入整个工程仿真不对的BUG就可能是仿真用错了赋值。本文将以一个具体的实例介绍testbench中的阻塞赋值和非阻塞赋值。


++提示:以下是本篇文章正文内容。++

一、简介

在FPGA设计中,Verilog HDL中的阻塞赋值(Blocking Assignment) 和**非阻塞赋值(Non-blocking Assignment)**是两种不同的赋值方式,它们的行为和用途有显著区别,直接影响电路的时序逻辑和组合逻辑的实现。

1. 阻塞赋值(=)

语法:变量 = 表达式;

执行方式:

立即执行,赋值语句在当前仿真时间步中按顺序执行,后面的语句必须等待该赋值完成才能继续。

类似于软件编程中的"顺序执行"。

用途:

主要用于组合逻辑设计(如always @(*)块)。

不适用于时序逻辑(可能导致仿真与硬件行为不一致)。

示例:

复制代码
always @(*) begin
    a = b;  // 阻塞赋值
    c = a;  // c的值会立即更新为b的值
end

执行后,c直接等于b(因为a = b先完成)。

2. 非阻塞赋值(<=)

语法:变量 <= 表达式;

执行方式:

延迟执行,所有非阻塞赋值在当前仿真时间步结束时同时更新。

赋值操作不会阻塞后续语句的执行。

用途:

主要用于时序逻辑设计(如always @(posedge clk)块)。

避免竞争条件,确保寄存器行为正确。

示例:

复制代码
always @(posedge clk) begin
    a <= b;  // 非阻塞赋值
    c <= a;  // c获取的是a的旧值(更新前)
end

在时钟上升沿,a和c的更新是并行的:c得到的是a的旧值(非阻塞赋值的典型特征)。

二、设计实例

设计模块代码如下,完成的是a+b*c的一个功能,假设操作延时都只有一个CLK,所以输入a进来打拍了一次。

复制代码
module a_add_bmulc(
    input clk,
    input [7:0] a,
    input [3:0] b,
    input [3:0] c,
    output reg [8:0] result
    );

reg [7:0] a_delay;
always @(posedge clk)
begin
    a_delay<=a;
end

reg [7:0] mul_result;
always @(posedge clk)
begin
    mul_result<=b*c;
end

always @(posedge clk)
begin
    result<=a_delay+mul_result;
end

endmodule

三、仿真实例

1、仿真用非阻塞赋值

仿真时笔者首先使用非阻塞赋值。

复制代码
initial
begin
    #(PERIOD*6) a<=1;b<=2;c<=3;
    #(PERIOD)   a<=4;b<=5;c<=6;
    #(PERIOD)   a<=0;b<=0;c<=0;
    #(PERIOD*10)
    $finish;
end

仿真结果如下:

和预期相符合,a,b,c同时输入,先计算b*c,a进来先延迟了1个时钟周期,b*c的结果相对于输入b和c也有一个时钟周期的延时,result相对于输入a,b,c有2个时钟周期的延时。

2、仿真用阻塞赋值

接下来仿真时笔者再改为阻塞赋值。

复制代码
initial
begin
    #(PERIOD*6) a=1;b=2;c=3;
    #(PERIOD)   a=4;b=5;c=6;
    #(PERIOD)   a=0;b=0;c=0;
    #(PERIOD*10)
    $finish;
end

仿真结果如下:

和预期不符,a_delay直接和a相等了,并没有延迟一个时钟周期,同样的,b*c的结果也没有延迟一个时钟周期,这和电路根本对应不上,但结果result却是对的。

本文举的例子只是作为一个小模块来说明,实际工程远大于这个模块,如果仿真时不注意区分阻塞赋值和非阻塞赋值,就很有可能产生意想不到的错误噢。结论就是仿真时也尽量使用非阻塞赋值。


总结

以上就是今天要记录的全部内容,本文介绍了FPGA仿真中阻塞赋值和非阻塞赋值的区别。

相关推荐
风已经起了1 天前
FPGA学习笔记——图像处理之亮度调节(乘法型)
图像处理·笔记·学习·fpga开发·fpga
helesheng5 天前
一个MCU与FPGA混合电路上电启动的问题及其解决办法探索[原创www.cnblogs.com/helesheng]
mcu·fsmc·fpga·启动·复位·线与·安路小精灵系列
XINVRY-FPGA12 天前
XCKU15P-2FFVA1760I AMD 赛灵思 Xilinx Kintex UltraScale+ FPGA
arm开发·嵌入式硬件·阿里云·fpga开发·云计算·硬件工程·fpga
XINVRY-FPGA15 天前
XCVP1902-2MSEVSVA6865 AMD 赛灵思 XilinxVersal Premium FPGA
人工智能·嵌入式硬件·神经网络·fpga开发·云计算·腾讯云·fpga
芒果树技术15 天前
MT-PXle RIO模块【高性能FPGA+ LVDS】采用FPGA实现高效LVDS通讯
fpga开发·模块测试·fpga
m0_5750463418 天前
FPGA数据流分析
数据分析·fpga·数据流分析
forgeda18 天前
半年报中的FPGA江湖:你打你的,我打我的
fpga·行业现状·竞争格局
璞致电子21 天前
【PZ-AU15P】璞致fpga开发板 Aritx UltraScalePlus PZ-AU15P 核心板与开发板用户手册
嵌入式硬件·fpga开发·fpga·fpga开发板·xilinx开发板
电子凉冰23 天前
FPGA入门-分频器
fpga开发·fpga
闻道且行之23 天前
FPGA|Quartus II 中使用TCL文件进行引脚一键分配
fpga开发·verilog·tcl