行为级建模中的过程性赋值(Procedural Assignment),这是理解 Verilog 和构建复杂逻辑(如 FSM、时序电路、流水线等)不可或缺的一部分。
🌟 一、引入:Verilog 中的赋值类型分类
Verilog 中的赋值分为两大类:
类别 | 说明 | 示例关键字 |
---|---|---|
连续赋值(continuous assignment) | 用 assign 关键字,适用于组合逻辑 |
assign y = a & b; |
过程性赋值(procedural assignment) | 在 always 或 initial 块中使用 |
always @(*) begin x = a + b; end |
我们重点讲 过程性赋值,因为它是行为级建模的核心。
🧠 二、过程性赋值的基本形式
在 Verilog 的 always
或 initial
代码块中,可以使用过程性赋值。这些赋值 不直接生成硬件连线,而是描述某种行为,通常与寄存器、时序有关。
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) |
寄存器触发器逻辑 |