组合逻辑与时序逻辑
核心区别
跳转到“核心区别”| 类型 | 输出由什么决定 | 典型电路 | RTL 要点 |
|---|---|---|---|
| 组合逻辑 | 当前输入 | 译码器、加法器、多路选择器 | 所有路径完整赋值,不能依赖旧值 |
| 时序逻辑 | 当前输入 + 已保存状态 | 寄存器、计数器、状态机 | 在时钟边沿更新,周期之间保持状态 |
flowchart TD IN["输入"] --> COMB["组合逻辑"] --> OUT["输出"] COMB --> D["寄存器 D"] CLK["时钟"] --> REG["寄存器"] D --> REG --> Q["状态 Q"] --> COMB组合逻辑
跳转到“组合逻辑”一个完整组合逻辑块必须让每个输出在每条控制路径上都有确定值:
always_comb begin y = '0; // 默认值覆盖未命中路径 if (enable) begin y = sel ? a : b; endend若 enable == 0 时没有给 y 赋值,硬件必须“记住旧值”,综合器通常会推断锁存器。除非明确需要电平敏感锁存器,否则这是设计缺陷。
时序逻辑
跳转到“时序逻辑”always_ff @(posedge clk) begin if (rst) begin count <= '0; end else if (enable) begin count <= count + 1'b1; endend寄存器只在上升沿采样右侧表达式;没有使能时保持原值。多个非阻塞赋值读取的都是该边沿到来前的状态,然后同时提交新状态。
设计判断
跳转到“设计判断”写代码前先回答:
- 哪些值必须跨周期保存?只有这些值需要寄存器。
- 哪些计算可在一个周期内完成?它们属于组合数据通路。
- 组合路径是否太长?必要时增加流水级,而不是降低约束要求。
- 是否意外生成锁存器、异步反馈或组合环路?
常见误区
跳转到“常见误区”begin-end只表示语句分组,不表示电路串行执行。if和case通常综合为选择逻辑,不是软件分支跳转。for在可综合 RTL 中通常展开为并行硬件,不是逐次运行的循环。- 寄存器保持旧值是时序逻辑的正常行为;组合逻辑“保持旧值”通常意味着锁存器。