Veloris.
返回索引
FPGA 2025-10-21

阻塞赋值和非阻塞赋值

3 分钟
737 words

阻塞赋值和非阻塞赋值

1 阻塞赋值(Blocking Assignment)

阻塞赋值是Verilog HDL中一种赋值方式,使用等号“=”作为运算符。使用阻塞赋值时,赋值语句会立即执行,并且会阻塞后续语句的执行,直到当前赋值完成。它模拟的是串行执行的硬件行为。

1.1 主要特点:

  • 立即更新:赋值立即生效,后续语句可以立即看到更新后的值

  • 顺序执行:在一个 begin…end 块中,语句是按顺序执行的。下一条语句必须等待上一条阻塞赋值语句执行完毕后才能开始执行。这和C语言或Python等软件编程语言中的赋值行为非常相似。

1.2 主要用途:

  • 组合逻辑always @(*)always @(a or b ...)块中)。

  • 因为组合逻辑的输出在理想情况下就是输入信号变化的即时反映,这种立即更新的特性正好可以模拟组合逻辑的行为

1.3 代码示例:

always @(*) begin
    a = 1;      // 步骤1:a立即变为1
    b = a;      // 步骤2:b获得a的新值(1)
    c = b + 1;  // 步骤3:c = 1 + 1 = 2
end
//执行顺序

// 时刻0: a = 1    → a变为1
// 时刻1: b = a    → b变为1(使用更新后的a)
// 时刻2: c = b+1  → c变为2(使用更新后的b)

2 非阻塞赋值(Non-Blocking Assignment)

非阻塞赋值使用小于等于号“<=”作为运算符。它模拟硬件的并发行为,即所有赋值语句在always块开始时同时评估(Evaluate),但实际更新(Update)发生在块结束时或特定事件后。这不会阻塞后续语句的执行。

2.1 主要特点:

  • 延迟更新:当仿真器遇到一个非阻塞赋值语句时,它会立即计算右侧表达式(RHS)的值,但不会立刻更新左侧的变量(LHS)。相反,它会将这个“更新计划”放到一个事件队列里。

  • 并行执行:在当前仿真时间步(time step)结束时,仿真器才会执行所有被计划的更新。这意味着在一个 begin…end 块中,所有非阻塞赋值语句的RHS都是在“同一时刻”计算的,LHS也是在“同一时刻”更新的。可以理解为它们是并行发生的。

2.2 主要用途:

  • 时序逻辑 (always @(posedge clk) 块中)。

  • 它完美地模拟了由同一个时钟边沿触发的所有触发器(Flip-Flops)同时采样输入数据,并同时更新自己输出的状态。

2.3 代码示例:

always @(posedge clk) begin
    a <= 1;      // 记录:a将要变为1
    b <= a;      // 记录:b将要变为a的旧值
    c <= b + 1;  // 记录:c将要变为b的旧值+1
end

//执行分为两个阶段:
//阶段1:评估(Evaluate)- 同时进行
// 计算右侧表达式:
// - a的新值 = 1
// - b的新值 = a的当前值(假设为3)
// - c的新值 = b的当前值 + 1(假设b当前为5,则为6)
//阶段2:赋值(Update)- 同时更新
// 在当前时间步结束时,执行所有更新:
//在当前时间片结束时,所有左侧变量同时更新:
//- a = 1
//- b = 3(旧的a值)
//- c = 6(旧的b值+1)

二者的区别比较

方面阻塞赋值 (=)非阻塞赋值 (<=)
符号=<=
执行机制立即执行,阻塞后续语句调度执行,非阻塞后续语句
模拟行为顺序逻辑,类似软件并发逻辑,类似硬件翻转器
适用逻辑组合逻辑、测试台时序逻辑、寄存器
潜在风险可能引入竞争条件如果混合使用,可能不一致
示例应用临时变量计算移位寄存器或流水线

总之,在Verilog设计中,推荐在描述组合逻辑时使用阻塞赋值,在描述时序逻辑时使用非阻塞赋值,以匹配硬件的实际工作原理。

End of file.