Menu
CoddyTech

非阻塞赋值

本课属于 Coddy Verilog 学习旅程的“基础知识”单元。第 50 课,共 90 课。

在上一课中,我们介绍了阻塞赋值(=),它会逐步执行。现在我们来介绍非阻塞赋值(<=),它会同时并行执行。

非阻塞赋值使用 <= 运算符。它被称为“非阻塞”,因为它不会阻塞下一条语句的执行。一个代码块中的所有非阻塞赋值都会同时执行。

语法:

variable <= expression;

何时使用非阻塞赋值

非阻塞赋值(<=)用于时序逻辑:这类电路使用时钟并具有存储功能。输出只会在时钟边沿(通常是上升沿)变化。

时序逻辑示例:

  • 触发器
  • 寄存器
  • 计数器
  • 状态机
  • 移位寄存器

Verilog 示例:

initial begin
  a <= 5;      // 已安排执行,但尚未执行
  b <= a + 2;  // 已安排执行,使用 a 的旧值
  c <= b * 3;  // 已安排执行,使用 b 的旧值
end

所有三个赋值都使用旧值同时进行。时间步结束时,所有更新会一起发生。

始终块中的非阻塞赋值(时序逻辑)

非阻塞赋值用于时序逻辑:使用时钟并具有存储功能的电路(触发器、寄存器、计数器)。

always @(posedge clk) begin
  q <= d;           // 在时钟边沿,q 获取 d 的值
  count <= count + 1; // 在时钟边沿,count 加 1
end

这两个赋值会同时发生,并使用时钟沿到来之前的值。

总结

规则说明
顺序逻辑使用 <=always @(posedge clk)
组合逻辑使用 =always @(*)
非阻塞赋值会并行执行所有赋值会同时发生
值会在时间步结束时更新不会立即更新
challenge icon

挑战

完成非阻塞赋值

添加缺失的非阻塞赋值,让这个 2 位移位寄存器正常工作。

工作原理:

  • 每个时钟沿到来时,q1 获取 d
  • q2 获取 q1 的旧值

要做什么:

  1. 将 d 赋给 q1(非阻塞)
  2. 将 q1 赋给 q2(非阻塞)

亲手试试

module shift_register (
  input clk,
  input reset,
  input d,
  output reg q1,
  output reg q2
);
  
  always @(posedge clk or posedge reset) begin
    if (reset) begin
      q1 <= 0;
      q2 <= 0;
    end else begin
      // TODO:添加移位逻辑
      // 第 1 步:用非阻塞赋值将 d 赋给 q1
      // 第 2 步:用非阻塞赋值将 q1 赋给 q2
    end
  end
endmodule
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

基础知识中的所有课

自己练习: Verilog 在线编译器