5.1 D 触发器与时钟进程


5.1 D 触发器与时钟进程

本节摘要:D 触发器是时序逻辑的最小记忆单元,时钟进程是它的标准书写形式。本节讲清触发器的采样行为、同步与异步复位的两种句式与时序差异、时钟使能的两种写法,并给出逐段对照的波形验证方法。

记忆是怎么发生的

组合电路的输出跟着输入即时变化,D 触发器(数据触发器)做的事件截然不同:平时输出纹丝不动,只在时钟上升沿那一瞬,把 D 输入的值抄进输出 Q,然后继续纹丝不动。抄进来的值一直保持到下一个上升沿。这一"抄"就是数字系统的记忆机制:一个位的信息被存住了。

行为写成 VHDL 就三行核心:

library ieee; use ieee.std_logic_1164.all; entity dff is port ( clk : in std_logic; d : in std_logic; q : out std_logic ); end entity dff; architecture rtl of dff is begin process (clk) -- 敏感表只有时钟 begin if rising_edge(clk) then -- 只在上升沿动手 q <= d; -- 把 d 抄进 q end if; end process; end architecture rtl;

敏感表只有 clk——上一章的配平法则在这里有个重要例外说明:进程里读了 d,但 d 只在时钟沿被采样,d 自己变化不该唤醒进程,所以只挂 clk 恰好正确。时序进程的标准形态就是"敏感表只有时钟 + rising_edge 判断",记住这个形态,百分之九十的时序代码都是它的变形。

复位:给记忆一个确定的起点

上电瞬间触发器的值是未知的,复位负责把它拉到已知状态。两种风格,句式与时序都不同:

-- 同步复位:复位要等时钟沿才生效 process (clk) begin if rising_edge(clk) then if rst = '1' then q <= '0'; else q <= d; end if; end if; end process; -- 异步复位:复位一来立刻生效,不等时钟 process (clk, rst) begin if rst = '1' then q <= '0'; elsif rising_edge(clk) then q <= d; end if; end process;

对比两段代码的三个差异点。其一,敏感表:同步版只有 clk(rst 只在时钟沿被采样);异步版必须挂上 rst(rst 变化本身要唤醒进程)。其二,判断顺序:异步版 rst 判断在 rising_edge 外面,这是"电平优先于时钟沿"的语法表达。其三,波形表现:同步复位在 rst 拉高后的下一个时钟沿才清零;异步复位 rst 一拉高输出立刻归零。FPGA 的触发器硬件自带异步复位端,两种风格都能直接映射;工程惯例偏向异步复位、同步释放的折中方案,细节在第 8 章上板排障时结合真实案例再谈。

图:三种情形下的触发器输出波形

图:三种情形下的触发器输出波形

时钟使能:让触发器"隔拍工作"

很多场合需要"这个时钟沿要不要采样由条件决定"——这就是时钟使能。标准写法是在 rising_edge 判断里再套一层条件:

process (clk) begin if rising_edge(clk) then if en = '1' then -- 使能有效才采样 q <= d; end if; -- 使能无效:保持原值(这是想要的保持,不是锁存器) end if; end process;

注意这里的"不赋值就保持"与第 3 章的锁存器雷区并不冲突:锁存器发生在组合进程的不完整赋值;时钟进程里"跳过赋值"意味着触发器保持原值,映射的正是触发器的保持行为,完全正确。区分二者只需一句话:时钟沿下的不完整赋值是保持,无时钟的组合路径不完整赋值才是锁存

验证环节沿用第 1 章的测试台骨架:时钟进程加激励进程,d 与 rst 按时间表翻转。逐段核对波形:找到每个上升沿,标出此刻 d 的值,确认 q 在沿后等于该值;再人为制造一次"复位与时钟沿同时到达",对比同步与异步两个版本的输出差异。这个实验做一遍,复位时序的争论你就有了亲手测过的答案。

⚠️ 常见坑:在同一进程里对同一信号既写时钟沿赋值又写组合赋值,或者用 d 的下降沿、双沿混合驱动——综合器要么报多时钟域错误要么综合出不可预期的电路。一条铁律:一个进程一个时钟,永远只用一个沿。

💡 关键直觉:触发器 = "抄写员"。平时不动作,时钟沿一到,把眼前(D 端)的内容抄到本子(Q 端)上。复位是"把本子擦干净",同步擦要等抄写节拍,异步擦随时动手。

本节要点回顾

  • 标准形态:时序进程 = 敏感表只有时钟 + rising_edge 判断;
  • 同步复位嵌在沿内、慢一拍但抗毛刺;异步复位在沿外、立即生效但释放要小心;
  • 时钟使能是在沿判断内加条件,跳过即保持;
  • 保持不等于锁存:时钟进程的"没赋值"是触发器本色,组合进程的"没赋值"才是雷;
  • 一个进程一个时钟一个沿:多时钟域要靠跨域同步手段,别在一个进程里硬来。

实战延伸:复位策略的选择

复位分同步复位和异步复位:

-- 异步复位 process(clock, reset) begin if reset = '1' then q <= '0'; elsif rising_edge(clock) then q <= d; end if; end process; -- 同步复位 process(clock) begin if rising_edge(clock) then if reset = '1' then q <= '0'; else q <= d; end if; end if; end process;

异步复位的优点:复位立即生效,不依赖时钟;缺点:复位释放是异步的,可能导致时序违例(recovery/removal)。

同步复位的优点:复位释放与时钟同步,避免 recovery/removal 问题;缺点:复位必须等下一个时钟沿生效。

工程实践

现代 FPGA 设计推荐异步复位 + 同步释放(async assert, sync deassert):

process(clock, reset_async) begin if reset_async = '1' then sync_reg <= '0'; elsif rising_edge(clock) then sync_reg <= '0'; -- 同步释放 end if; end process; -- 用 sync_reg 作为下游逻辑的复位信号

这种写法既保留了异步复位的快速响应,又避免了异步释放的时序风险。Xilinx 和 Intel 的官方应用笔记都推荐这种模式。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U