组合与时序 RTL 写法
赋值规则
跳转到“赋值规则”| 场景 | 写法 | 含义 |
|---|---|---|
| 组合过程 | 阻塞赋值 = | 后续语句立即看到新值 |
| 时钟过程 | 非阻塞赋值 <= | 先计算右值,在当前时间步末统一更新 |
| 简单连线 | assign | 连续驱动网络 |
这是一条可靠的工程约定,不是语言允许范围的完整描述。
组合逻辑模板
跳转到“组合逻辑模板”always_comb begin result = '0; valid = 1'b0;
if (enable) begin result = a + b; valid = 1'b1; endend默认值覆盖所有输出,后续分支只改变化量,可避免锁存器并减少重复代码。
寄存器与使能
跳转到“寄存器与使能”always_ff @(posedge clk) begin if (rst) begin q <= '0; end else if (enable) begin q <= d; endend时序块中不写最后的 else 表示寄存器保持原值,这与组合块遗漏分支不同。
非阻塞赋值的周期语义
跳转到“非阻塞赋值的周期语义”always_ff @(posedge clk) begin a <= in; b <= a; c <= b;end在同一个上升沿,三个右值都读取旧状态,因此这是一条三级移位流水线:in 经过 1、2、3 个周期分别到达 a、b、c。书写顺序不会把它变成单周期级联。
flowchart LR IN["in"] --> A["a 寄存器"] --> B["b 寄存器"] --> C["c 寄存器"]常用结构
跳转到“常用结构”计数器
跳转到“计数器”always_ff @(posedge clk) begin if (rst) begin count <= '0; end else if (tick) begin count <= count + 1'b1; endend上升沿检测
跳转到“上升沿检测”logic signal_d;
always_ff @(posedge clk) begin signal_d <= signal_sync;end
assign rise = signal_sync & ~signal_d;signal_sync 必须已同步到 clk 域;该写法不能替代异步输入同步器。
流水线
跳转到“流水线”将长组合逻辑拆到多个寄存器阶段,可以提高最高频率,但会增加延迟。设计接口时同时记录吞吐量和周期延迟。
不要这样写
跳转到“不要这样写”- 在同一时序块混用
=和<=来制造隐含顺序。 - 一个寄存器在多个
always_ff中赋值。 - 把数据本身放入
always @(posedge data)作为“时钟”。 - 用逻辑分频信号驱动大量寄存器;优先使用时钟使能或专用时钟资源。
- 在组合块中读取并写回同一变量形成组合反馈。