💡 特别鸣谢野火 FPGA 的教学与帮助!
本节相关的教程 link 📌
- 第 15 章 时序逻辑的开始 --- 寄存器:
- 15.0 章节导读:
- 15.1 理论学习:
- 15.2 实战演练:
- 15.2.1 实验目标:
- 15.2.2 硬件资源:
- 15.2.3 程序设计:
- 1. 模块框图:
- 2. 波形图绘制:
- 同步复位的 D 触发器:
- 异步复位的 D 触发器:
- 不同点:
- 相同点:
- “延一拍”的效果:
- 3. 代码编写:
- 同步复位的 D 触发器:
- 异步复位的 D 触发器:
- RTL 视图对比:
- 4. 仿真验证:
- 仿真文件编写:
- 仿真波形分析:
- 同步复位的 D 触发器:
- 观察“Transcript”界面:
- 异步复位的 D 触发器:
- 15.2.4 上板验证:
- 1. 引脚约束:
- 2. 结果验证:
- 15.3 章末总结:
- 15.4 拓展训练:
15.0 章节导读
从本章开始我们开始进入到时序逻辑的设计,要进行时序逻辑的设计,那寄存器就是必不可少的元素,让我们一起来认识一下什么是寄存器,它能做什么、有什么特性、如何用 Verilog 语言来描述。
15.1 理论学习
组合逻辑最大的缺点就是会存在竞争冒险(详细可参考前面推荐的数字电路相关的书,这里不再在进行详细解释)问题,这种竞争冒险问题是非常危险的,常常会引起电路的不稳定性和工作时的不确定性,而我们使用时序逻辑就可以极大的避免这种问题,从而使系统更加稳定。而时序逻辑最基本的单元就是寄存器, 寄存器具有存储功能,一般是由 D 触发器构成,由时钟脉冲控制,每个 D 触发器(D Flip Flop ,DFF)能够存储一位二进制码。
D 触发器的功能为:在一个脉冲信号(一般为晶振产生的时钟脉冲)上升沿或下降沿的作用下,将信号从输入端 D 送到输出端 Q,如果时钟脉冲的边沿信号不来则输入信号保持原值,且寄存器拥有复位清零功能,其复位又分为同步复位和异步复位。 区分一个设计是组合逻辑电路还是时序逻辑电路主要是看数据工作是不是在时钟沿下进行的,在 FPGA 的设计中,复杂的电路设计都要用到时序逻辑电路,往往都是以时序逻辑电路为主,组合逻辑为辅的混合逻辑电路。
15.2 实战演练
15.2.1 实验目标
前面章节中,我们设计并编写了使用按键控制 LED 灯的工程,在本章节我们同样使用这个例子,虽然实验效果相同,但本章是使用 D 触发器来进行控制的,和使用组合逻辑的控制方法有所不同。 当按键未按下时 led 灯处于熄灭状态;当按键被按下时 led 灯被点亮。
15.2.2 硬件资源
我们要使用按键 KEY1 点亮 LED 灯 D6
由原理图可知,征途 Mini 开发板的按键未按下时为高电平、按下后为低电平;LED 灯则为低电平点亮。
15.2.3 程序设计
1. 模块框图
我们先给模块取一个名字叫 flip_flop,接下来是分析端口信号:D 触发器能够正常工作一定有时钟,每当时钟的“沿(上升沿或下降沿)”来到时我们采集到稳定有效的数据;其次还需要的就是复位信号,用于让触发器的回到初始状态把数据清零;因为是用按键控制 led 灯的亮灭,所以输入端我们还需要一个按键控制信号;输出就只有一个控制 led 灯的信号,这里我们的输入输出信号都是 1bit 的。根据上面的分析设计出的 Visio 框图如图 15-4 所示。
2. 波形图绘制
D 触发器根据复位的不同分为两种,一种是同步复位的 D 触发器,另一种时异步复位的 D 触发器,下面就是详细介绍这两种 D 触发器的异同,以及波形的设计。从本章开始, 我们后面设计的工程项目都主要以时序逻辑为主,其中波形的设计尤为关键,希望大家能够认真体会其中的精妙之处。
同步复位的 D 触发器
同步复位的 D 触发器中的“同步”是和工作时钟同步的意思,也就是说,当时钟的上升沿(也可以是下降沿,一般习惯上为上升沿触发)来到时检测到按键的复位操作才有效,否则无效。如图 15-5 所示最右边的三根红色的竖线表达的就是这种效果,sys_rst_n 被拉低后 led_out 没有立刻变为 0,而是当 syc_clk 的上升沿到来的时候 led_out 才复位成功, 在复位释放的时候也是相同原因。
异步复位的 D 触发器
异步复位的 D 触发器中的“异步”是和工作时钟不同步的意思,也就是说,寄存器的复位不关心时钟的上升沿来不来,只要有检测到按键被按下,就立刻执行复位操作。如图 15-6 所示最右边的两根红色的竖线表达了这种效果,sys_rst_n 被拉低后 led_out 立刻变为 0,而不是等待 syc_clk 的上升沿到来的时候 led_out 才复位,而在复位释放的时候 led_out 不会立刻变为 key_in 的值,因为还要等待时钟上升沿到来到时才能检测到 key_in 的值,此时才将 key_in 的值赋值给 led_out。
相同点
相比于组合逻辑电路来讲,对于电路中产生的毛刺有着极好的屏蔽作用, 如上图中间位置的一组红色竖线所示,是我们模拟在干扰情况下产生的毛刺现象,因为时序电路只有在沿到来时才检测信号是否有效,所以在两个上升沿之间的毛刺都会被自然的过滤掉,可以大大减少毛刺现象产生的干扰,提高了电路中数据的可靠性。
“延一拍”的效果
上面两个图最左边的一组红色竖线所表达的就是这个现象。key_in 在复位后的第一个时钟的上升沿来到时拉高,我们可以发现此时 led_out 并没有在同一时刻也跟着拉高,而在之前的组合逻辑中输出是在输入变化的同一时刻立刻变化的,这是什么原因呢?
因为我们所画的波形图都是基于前仿真的,没有加入门延时的信息,所以很多时候数据的变化都是和时钟直接对齐的。当表达时序逻辑时如果时钟和数据是对齐的,则默认当前时钟沿采集到的数据为在该时钟上升沿前一时刻的值;当表达组合逻辑时如果时钟和数据是对齐的,则默认当前时钟沿采集到的数据为在该时钟上升沿同一时刻的值。而仿真工具在进行 RTL 代码的仿真时也遵循这个规则,我们也可以理解为仿真寄存器是按照建立时间 Tsu(指触发器的时钟信号上升沿到来以前,数据稳定不变的最小时间)最大(一个时钟周期),保持时间 Th(指触发器的时钟信号上升沿到来以后,数据稳定不变的最小时间)最小(为 0)的理想环境下进行的;而在仿真组合逻辑时因为没有时钟也就没有建立时间和保持时间的概念,所以数据只要有变化就立刻有效。这里我们在画波形图的时候一定要记住这个“延一拍”的效果,否则我们绘制的波形图就会和最后的仿真结果不符,也可能会导致最后的逻辑混乱。
不同点
主要就是复位有效的条件是“立刻”执行还是等待“沿”再执行的区别
3. 代码编写
同步复位的 D 触发器
根据上面 RTL 代码综合出的 RTL 视图如图 15-7 所示,由一个选择器和一个寄存器构成。
异步复位的 D 触发器
根据上面 RTL 代码综合出的 RTL 视图如图 15-8 所示,只有一个寄存器构成。
如果复位时的值不是 0 而改为 1,相当于复位时将 D 触发器置为 1,则使用 D 触发器上的置位端口,其综合的 RTL 视图如图 15-9 所示。
RTL 视图对比
采用同步复位会多出来一个选择器的结构,这里我们可能不禁会有疑问,为什么多了一个选择器?我们设计的 RTL 逻辑中并没有想表达这个选择器的意思,这显然对我们最初想要表达的的设计是多余的,所以我们在使用 Intel(Altera)芯片时最好使用异步复位(如果是 Xilinx 的芯片则推荐使用同步复位,Xilinx 最新的 UltraFast 推荐不使用复位,后面会在内部结构和时序分析中解释原因),这样子就可以节约更多的逻辑资源,之所以会有这样的差异是由于 FPGA 内部结构决定的,后面我们会从 FPGA 的内部结构中详细解释。
4. 仿真验证
仿真文件编写
begin…end 是一个串行块在 Testbench 中被使用时其内部的语句是顺序执行的,在本例中的 13-28 行代码中,我们多次进行延时,其时间是在之前基础上叠加的,而不是从 0 时刻开始计算时间。
仿真波形分析
我们在观察时序逻辑时不能再像观察组合逻辑那样子,因为输入和输出会有延一拍的效果,如果输入数据在前一个时钟的上升沿变化,则输出数据不会立刻变化,而是在下一个时钟的上升沿才变化,这样的现象我们简单化运用——当时钟和信号在同一时刻变化时,我们以时钟的上升沿前一时刻采集的输入信号为依据来产生输出信号,这样我们就可以很好的观察时序逻辑产生的波形了。
同步复位的 D 触发器
仿真出来的波形如图 15-10 所示,我们让仿真运行了 500ns 即可得到较好的观察效果。首先复位为高电平的那一刻是和时钟的上升沿对齐的,根据上面的原则,其实此处的上升沿采集到的复位信号为该上升沿前一时刻的值,也就是低电平,所以寄存器处于复位状态,使 led_out 依然保持为低电平,而在下一个时钟的上升沿前一时刻时复位信号已经为高电平,复位被释放,且 key_in 为高电平,所以此时 led_out 也为高电平,这种分析最后的现象完全契合了延一拍的效果(直观上看到的波形是对齐的,其实我们要取的值是时钟上升沿前一时刻得值),中间我们又加入了一段时间的复位,可以看到同步复位的效果。 和最初设计的波形图对比发现是完全一致的。
观察“Transcript”界面
发现 key_in 和 led_out 的值是延一拍的对应关系,有些时候会因这种延时一拍的关系导致对打印数据的观测不是很直观,特别是我们中间还加了复位的控制,不知道的还以为是出现了错误,使之更难于观察,这也是我们为什么在本节中没有列出真值表的原因。在时序逻辑电路中真值表并不能很清晰的表达时序的对应关系,反而是用波形图表达的更加清晰,而在以后的设计中,我们并不是不再用“Transcript”界面打印信息,而是不再这样完全把信号进行简单的列举显示,我们会打印一些关键时刻点的打印信息或者是设计一些特殊的打印信息以方便对特殊时刻点信号的观察。
异步复位的 D 触发器
我们使用和同步复位的 D 触发器一样的时序电路分析波形的方法,如图 15-12 所示, 经过仔细的验证发现符合异步复位 D 触发器的逻辑设计。而我们就不再打印异步复位的 D 触发器的信息了。
15.2.4 上板验证
1. 引脚约束
上板验证之前先要进行引脚约束。工程中各输入输出信号与开发板引脚对应关系如表格 15-2 所示。引脚配置如图 15-13 所示。
2. 结果验证
下载完成后按下按键 KEY1,会发现同时被绑定的 led 随着按键的按下会被点亮,而按键松开时又熄灭,实现了我们最初预想的设计,如图 15-16 所示。
15.3 章末总结
本章首次讲解了 FPGA 中的时序逻辑,这也是我们正式学习、认识 FPGA 的一个新开始,因为用 FPGA 设计的大型电路几乎都是以时序逻辑为主的,我们也会在今后更加看到 FPGA 大显身手的时刻。 本章中我们还对比了同步复位的 D 触发器和异步复位的 D 触发器在波形、代码编写、逻辑资源上的不同,并给出了推荐的用法,希望大家能够在以后的设计中加以规范,熟练使用。在代码的设计上要深刻体会组合逻辑和时序逻辑的差别,特别是在用 always 块描述时,要理解电平触发和沿触发的区别,注意敏感列表的不同。 always 块实现时序逻辑时无论是单比特信号还是多比特信号都具有这种延一拍的效果。我们在后面设计时要养成一些“条件反射”,即做到根据波形写代码的时候看到波形中有延一拍的现象时就要想到用 always 块的时序逻辑来实现;看到 always 块表达时序逻辑时就要想要波形中会延一拍的效果,我们经常会听到有人说把数据“打一拍”其实就是这个意思。
15.4 拓展训练
细心的朋友可能会发现发两个仿真的波形在最开始的一段时间内有所不同,同步复位的 D 触发器在开始一段时间内是红色的信号,而异步复位的 D 触发器就没有这种现象,产生这种现象的原因是什么,仿真波形中的红色信号又代表什么意思呢?