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仿真中阻塞赋值和非阻塞赋值的区别。

相关推荐
XINVRY-FPGA11 天前
XCVU47P-2FSVH2892E Xilinx Virtex UltraScale+ FPGA AMD
c语言·c++·人工智能·嵌入式硬件·阿里云·fpga开发·fpga
迎风打盹儿15 天前
FPGA点亮ILI9488驱动的SPI+RGB接口LCD显示屏(二)
fpga·verilog hdl·ili9488·rgb接口·lcd显示屏
tiantianuser18 天前
RDMA简介7之RoCE v2可靠传输
服务器·fpga开发·verilog·xilinx·rdma·可编程逻辑
9527华安24 天前
国产安路FPGA纯verilog图像缩放,工程项目解决方案,提供5套TD工程源码和技术支持
fpga开发·verilog·图像缩放·双线性插值·安路fpga
贝塔实验室24 天前
FPGA 的硬件结构
arm开发·fpga开发·职场和发展·硬件架构·硬件工程·fpga·安全架构
贝塔实验室1 个月前
FPGA 动态重构配置流程
驱动开发·fpga开发·硬件架构·硬件工程·射频工程·fpga·基带工程
tiantianuser1 个月前
RDMA简介5之RoCE v2队列
fpga开发·verilog·fpga·rdma·高速传输·rocev2
ALINX技术博客1 个月前
【新品解读】一板多能,AXRF49 定义新一代 RFSoC FPGA 开发平台
射频工程·fpga·amd·rfsoc·alinx
tiantianuser1 个月前
RDMA简介3之四种子协议对比
verilog·fpga·vivado·rdma·高速传输