FPGA基础 -- Verilog 行为级建模之过程性赋值

发布于:2025-06-19 ⋅ 阅读:(17) ⋅ 点赞:(0)

行为级建模中的过程性赋值(Procedural Assignment),这是理解 Verilog 和构建复杂逻辑(如 FSM、时序电路、流水线等)不可或缺的一部分。


🌟 一、引入:Verilog 中的赋值类型分类

Verilog 中的赋值分为两大类:

类别 说明 示例关键字
连续赋值(continuous assignment) assign 关键字,适用于组合逻辑 assign y = a & b;
过程性赋值(procedural assignment) alwaysinitial 块中使用 always @(*) begin x = a + b; end

我们重点讲 过程性赋值,因为它是行为级建模的核心。


🧠 二、过程性赋值的基本形式

在 Verilog 的 alwaysinitial 代码块中,可以使用过程性赋值。这些赋值 不直接生成硬件连线,而是描述某种行为,通常与寄存器、时序有关。

1. 两种赋值运算符

运算符 含义 通常使用场景
= 阻塞赋值(blocking assignment) 组合逻辑建模
<= 非阻塞赋值(non-blocking assignment) 时序逻辑建模

🚦 三、阻塞与非阻塞赋值的区别与适用

🔹阻塞赋值(=)

阻塞赋值的执行顺序是逐行执行、立即赋值,就像 C 语言一样。

always @(*) begin
  a = b;
  c = a; // c = b
end

这会在仿真中生成“顺序逻辑”行为。注意:用于建模组合逻辑是安全的,但不适合寄存器更新。

✅ 用于:组合逻辑,例如:

always @(*) begin
  if (sel)
    out = in1;
  else
    out = in2;
end

🔹非阻塞赋值(<=)

非阻塞赋值是并行调度的,所有赋值在时钟边沿“同时生效”。

always @(posedge clk) begin
  a <= b;
  c <= a; // c <= a, 但在当前周期仍是旧值
end

这才是 建模寄存器行为 的正确方式,可防止组合回环

✅ 用于:时序逻辑(触发器、状态机寄存器等):

always @(posedge clk or negedge rstn) begin
  if (!rstn)
    state <= IDLE;
  else
    state <= next_state;
end

🔍 四、过程性赋值在行为级建模中的结构模式

1. 组合逻辑(同步赋值)

always @(*) begin
  case (state)
    IDLE: next_state = START;
    START: next_state = RUN;
    default: next_state = IDLE;
  endcase
end
  • 使用 =,防止锁存器推断(latch)
  • @(*) 表示自动根据使用变量决定敏感列表

2. 时序逻辑(寄存器赋值)

always @(posedge clk or negedge rstn) begin
  if (!rstn)
    state <= IDLE;
  else
    state <= next_state;
end
  • 使用 <=,防止竞态
  • 建模 flip-flop 的最佳方式

🧩 五、行为级建模进阶建议

✅ 建议风格规范

模块 建议赋值类型 原因
状态转移逻辑 = in always @(*) 表示组合逻辑,清晰、无锁存
状态寄存器更新 <= in always @(posedge clk) 映射寄存器逻辑,防止竞态
多位信号更新 使用非阻塞组合赋值序列 保持设计一致性

❗ 六、常见错误与调试建议

❌ 错误用法示例:

always @(posedge clk) begin
  a = b; // ❌阻塞赋值用于时序逻辑,可能产生竞态
end

✅ 正确改法:

always @(posedge clk) begin
  a <= b; // ✅非阻塞赋值
end

🛠 七、综合器处理方式

✅ 可综合的过程性赋值:

  • always @(*) + =,建模组合逻辑
  • always @(posedge clk) + <=,建模寄存器

🚫 不可综合用法:

  • initial
  • #10 延迟语句
  • 文件读写语句(如 $readmemh

📘 八、实例总结:状态机建模结构

// 状态定义
parameter IDLE=2'b00, START=2'b01, RUN=2'b10;

// 状态寄存器
reg [1:0] state, next_state;

// 状态更新:时序逻辑
always @(posedge clk or negedge rstn)
  if (!rstn)
    state <= IDLE;
  else
    state <= next_state;

// 状态转移:组合逻辑
always @(*) begin
  case (state)
    IDLE: next_state = START;
    START: next_state = RUN;
    RUN: next_state = IDLE;
    default: next_state = IDLE;
  endcase
end
  • state 是寄存器,用 <= 更新
  • next_state 是组合逻辑结果,用 = 推导

✅ 九、小结

关键词 含义
= 阻塞赋值,顺序执行,组合逻辑
<= 非阻塞赋值,并行调度,时序逻辑
always @(*) 自动组合逻辑
always @(posedge clk) 寄存器触发器逻辑