数电:CMOS、锁存器、触发器和时序
本文为查看CMOS到触发器 - superego_zhang - 博客园灵感记录按数电发展逻辑介绍基础的元器件并引用总结原博客部分内容感谢原作者创作。一、CMOS晶体管CMOS管是作为各种逻辑实现的第一步。1.PMOS和NMOS金属-氧化物-半导体(Metal-Oxide-Semiconductor)结构的晶体管简称MOS晶体管有P型MOS管和N型MOS管之分。PMOS管和NMOS管共同构成的互补型MOS集成电路即为 CMOS Complementary MOS。MOS管就相当于一个开关如图所示。可以在栅极通过控制电压实现源、漏极导通从而控制输出0/1电平。2.CMOS反相器如果单独只用PMOS/NMOS每次导通会有大量电流功耗较大。而CMOS将二者结合每次只会导通其中一个功耗很小使得CMOS成为芯片构建主流。CMOS 反相器电路如图。3.CMOS门电路基于CMOS的反相器可以组成其他基础门电路①CMOS与非门NAND②CMOS或非门NOR二、存储器件有了上述基础的门电路之后可以实现与或非和加、减、乘、除、等逻辑操作。接下来一步就是实现数据存储。1.双稳态器件双稳态器件是指稳定状态有两种一种是0一种是1的器件。双稳态器件是存储器件的基本模块双稳器件的的一种电路结构是交叉耦合反相器结构如下图所示。为什么介绍双稳态器件呢那是因为锁存器、寄存器都是双稳态器件它们都有两个稳定状态1和0。正是因为它们有两个稳定的状态因此才可以拿它们来存储数据也就是说双稳态电路比如交叉耦合反相器、锁存器和寄存器可以存储数据。2.锁存器Latch很显然上述的交叉耦合反相器没有输入是存储不了输入的数据因此就需要有输入的类似“交叉耦合反相器”结构的双稳态电路这就是锁存器。锁存器不需要触发信号由输入信号直接完成置0或置1操作。① RSReset-Set锁存器补充一点早期会把RS锁存器又称作RS触发器这是不严格的RS锁存器不需要触发D锁存器电平触发触发器跳变沿触发。RS锁存器结构如图。这里用的或非门搭建的SR锁存器同样也可以用与非门搭建SR锁存器。工作原理1S端是置位端S1的时候把输出Q置为12R端是复位端R1的时候把输出Q复位成03当S0, R0的时候输出Q的值就保持前一个状态的值也就是把原理的状态锁存了4当S1, R1的时候根据与非门的特性Q0, Q0, 这样QQ不符合输出Q~Q的逻辑。所以S1, R1是不允许的状态这也是SR锁存器的一个限制为了解除这个限制一般是把一个信号接到S端同时通过一个反相器输入到R端这样SR就不可能同时为1。优点1锁存数据保持数据状态2防毛刺功能。假设门级的传输延迟时间为tpd假设S置0低电平有效为保证触发器可靠地翻转必须等到Q0的状态反馈到G1的输入端以后S0的信号才可以取消。因此S输入的低电平信号宽度tw应满足tw≥2tpd。R端同理。可见如果SR端输入的信号宽度很小比如毛刺那么输出是不会改变的。RS锁存器的结构在门控时钟切换防毛刺中很有用缺点1R/S端不能同时为12锁存的时间点不清楚任何时刻输入都能直接改变输出的状态没有一个参考的时刻来确切的知道电路的状态。当存在多个RS锁存器时不能保证所有输入、输出同一时刻。② D锁存器为了解决SR锁存器的缺点改进的结构就是D锁存器。最大的特点是引入了一个特殊信号时钟信号它可以通过高低电平循环变化实现RS锁存器的使能。引入时钟信号后D锁存器就只能在时钟有效的时候S和R才能起作用也就是给RS锁存器加了一个前提条件这样对照周期性的时钟信号就能明确知道锁存的时间点了。常见结构图如下所示。D锁存器可以分为前级门电路两个与门和一个非门和后级RS锁存器组成。工作原理输入是Clk和D输入有四种可能1当clk0时红S红R都为0也就是SR锁存器的输入为00根据SR锁存器的功能输出Q和Q’将保持原来的状态因此clk0时不管D是什么输出Q和Q’都不随D变化只与原来的状态有关也就是保持。2当clk1时R(1·D’)D’S(1·D)D。也就是说当clk1的时候SR锁存的输入是互补的不会出现S和R同时有效的情况。当D1时S1置位有效输出Q1当D0时R1复位有效输出Q0因此就可以知道在clk1时输出QD也就是输出等于输入。通过上面的分析上面的D锁存器结构功能为在clk1时数据通过D锁存器流到了Q在Clk0时Q保持原来的值不变。这样的锁存器也称为透明锁存器或者电平敏感锁存器。优点解决了RS锁存器没有参考的时刻的问题。缺点在时钟为高的时候输入信号的任何改变都会随时引起输出的改变一个时钟高电平期间可能会有多次改变。而且受布线延迟影响较大很难保证输出没有毛刺产生。3.触发器Flip-Flop为了改进D锁存器电平敏感的缺点发明了边沿D触发器。D触发器最大的特点是边沿敏感的也就是仅取决于CLK的上升沿或下降沿到来时的输入信号状态与在此前、后输入的状态没有关系。这样就提高可靠性增强抗干扰能力。结构如图所示。D触发器由两个D锁存器构成驱动时钟的相位相反前面的D锁存器称为主锁存器后面的D锁存器称为从锁存器因此D触发器也可以称为主从触发器。工作原理在时钟clk0的时候主锁存打开进行传输数据把输入传送到从到从锁存器的输入端即Qm D1。然后clk从0→1的时候主锁存器准备关闭保持原来的值D1与此同时从锁存器准备打开把Qm的值传输到输出Qs也就是QsQmD1。4.寄存器Register寄存器如下图由多个D触发器构成一个D触发器可以看做1位的寄存器寄存器可以看成是多位的DFF。三、时序时序包含亚稳态和时序违例。1.亚稳态上述触发器器件的核心一般是交叉耦合反相器是双稳态器件但实际电路中可能还出现第三种状态即亚稳态。发生原因①最基础的CMOS反相器作为一个开环放大电路输出电压完全由输入电压唯一决定给定一个中间值电压Vi/2此时NMOS 和 PMOS 同时导通且工作在饱和区反相器工作在高增益放大状态那么输出也会是Vo/2。②虽然数字电路中一般只用0/1不会使用Vi/2但是在时钟沿的时刻数据发生变化就有可能采到Vi/2的电平。③但是触发器中的核心器件是CMOS反相器组成的交叉耦合反相器它是一个闭环正反馈电路即使输入不平衡的中间电平由于外部干扰几毫伏的热噪声等原因让某一侧电压稍微偏高正反馈回路会把这个偏差持续放大偏高的一侧会让另一侧输出更低反过来又让这一侧更高形成滚雪球效应④最终电路会快速滑向两个稳定状态之一全 0 或全 1这个滑向稳定的时间就是亚稳态的恢复时间亚稳态最大的影响是在亚稳态还没恢复的时间内触发器的输出值是一个高低不定的状态如果直接将这个输出接到后续的组合逻辑将导致逻辑出现不可预测的错误。2.时序违例即在下图中的采集时刻数据的建立、保持时间不满足来得太迟或走得太早。若在时钟上升沿来的那一刻数据D突然发生变化即主锁存器正准备关闭①时刻从锁存器刚刚打开②时刻数据发生变化都会使得电路进入亚稳态。表现形式为主锁存器的SR锁存器交叉正反馈正在进行恢复处于0/1不定状态。等恢复时间到达时交叉正反馈会因为环境中的干扰反馈恢复到0或1的值。这就是打两拍两个同clk的D触发器解决亚稳态问题的关键后面会细说从锁存器直接输出主锁存器的值导致输出端看到0/1不定状态3.亚稳态和时序违例的关系①亚稳态→→→时序违例严重的②时序违例→→→不一定导致亚稳态。当时序违例没有很严重如下图所示。D1不满足建立是TsuD2不满足保持时间Thd但是二者的违例的时间较小相当于二者都在①时刻主锁存器还没完全关断前此时D还没完成变换根据交叉反馈电路的特性主锁存器的Q端还保持上一次的值从锁存器的输出Q端不会出现亚稳态。4.时序违例产生场景①异步时钟域老生常谈的问题不同时钟域的clk1和clk2clk2有概率采集到clk1产生的正在变化的数据从而产生时序违例。危害异步时钟的危害在于它的时序违例结果不确定导致后续输出逻辑的不确定关键是无法通过工具的静态时序分析解决。解决办法单bit打两拍多bit使用异步FIFO底层原因是格雷码。关于打两拍规避亚稳态的原理多说两句。首先看平均故障时间MTBFMean Time Between Failures公式tr亚稳态恢复时间对应交叉反馈器件的恢复时间T/T0电气特性fin/fclock异步输入信号频率/同步触发器时钟频率由公式看出亚稳态恢复时间和时钟频率有很大关系其中tr就是D触发器中的交叉反馈器件恢复时间一般tr Tclk打第一拍是为了给一个Tclk的时间让交叉反馈器件恢复到0或1只有当Tclk tr时才需要多打几拍每打一拍给第一个触发器的交叉反馈器件多加Tclk的时间。更细节内容可以查看https://blog.csdn.net/weixin_39015789/article/details/105013592如下图所示除非Tclk很小小到一个Tclk无法覆盖tr恢复时间才需要多打几拍。总结打两拍每打一拍是给触发器一个时钟周期Tclk的时间恢复若Tclk tr则需要多打几拍恢复打两拍只保证采集到稳定的逻辑电平但是不保证数据正确。但是即便当前拍采集错误延迟1-2拍后一定能采到正确的数据除非数据变化过快每一拍都卡在时序违例的时间上。②相位不固定的同源时钟同一个PLL或者时钟IP产生例如同一个PLL产生100M时钟和300M时钟相位周期可通过最小公倍数计算得出按照下述相位固定的同源时钟处理。③相位固定的同源时钟同一个PLL产生的同频率时钟也有可能时序违例导致亚稳态例如PLL产生同频率时钟clk1和clk2相位固定相差2.5ns若此时clk1触发器产生的数据延迟2.5ns到达clk2的触发器那么clk2采集数据时将出现时序违例。但是这种时序违例与异步时钟域的区别在于它每次违例都是固定且必然发生的可以通过工具的静态时序分析解决时序约束或相移时钟而异步的危害就在于它的不确定性。5.时序约束和亚稳态措施的关系不管是异步时钟域还是同步时钟域只要涉及不同时钟域就需要做跨时钟域处理单bit打拍多bit异步fifo。时序约束只是尽量保证布线时尽量不让数据采集不落入亚稳态不能百分百保证一旦落入就需要有跨时钟域处理消除亚稳态的影响二者是相互保障的关系。6.常规的时序约束①时钟周期约束create_clock -name 时钟名称 -period 周期值单位ns [-waveform {上升沿时刻 下降沿时刻}] [-add] [get_ports 输入端口名] -name自定义时钟名省略则默认使用端口名。 -period时钟周期单位纳秒必填参数。 -waveform指定占空比默认 {0 period/2}50% 占空比0ns 上升沿。 -add在同一端口叠加多个时钟用于多模式场景。 # 定义100MHz系统时钟50%占空比输入端口sys_clk create_clock -name sys_clk -period 10 -waveform {0 5} [get_ports sys_clk]create_generated_clock -name 时钟名称 -source 源时钟节点 [-divide_by 分频系数] [-multiply_by 倍频系数] [-edge {沿位置列表}] [get_pins 输出引脚/端口] -source源时钟的输入节点通常是上级时钟的端口 / 引脚。 -divide_by / -multiply_by整数分频、倍频系数二选一使用。 -edge自定义沿位置用于非整数分频、复杂相位的场景。 -FPGA 中 MMCM/PLL 的输出时钟Vivado 会自动识别并生成衍生时钟无需手动编写。 # 逻辑二分频时钟源为寄存器时钟端输出为寄存器Q端 create_generated_clock -name clk_div2 -source [get_pins reg0/C] -divide_by 2 [get_pins reg0/Q]②输入延时约束set_input_delay -clock 参考时钟名 [-clock_fall] -max 最大延迟值 -min 最小延迟值 [-add_delay] [get_ports 输入端口名] -clock参考时钟默认使用时钟上升沿。 -clock_fall参考时钟下降沿有效用于双沿采样场景。 -max最大输入延迟对应 setup 检查数值越大FPGA 内部可用时间越少。 -min最小输入延迟对应 hold 检查数值越小hold 检查越严苛。 -add_delay叠加已有延迟用于多时钟、多模式场景。 # 数据端口data_in相对于sys_clk最大延迟2ns最小延迟0.5ns set_input_delay -clock sys_clk -max 2 -min 0.5 [get_ports {data_in[*]}]③输出延时约束set_output_delay -clock 参考时钟名 [-clock_fall] -max 最大延迟值 -min 最小延迟值 [-add_delay] [get_ports 输出端口名] -max最大输出延迟对应 setup 检查代表下游要求数据在时钟沿前提前稳定的时间。 -min最小输出延迟对应 hold 检查允许为负数代表下游允许数据在时钟沿后小幅变化。 # 输出端口data_out相对于sys_clk最大延迟1.5ns最小延迟-0.5ns set_output_delay -clock sys_clk -max 1.5 -min -0.5 [get_ports {data_out[*]}]④时序例外约束set_false_path -from 起点集合 -to 终点集合 [-through 经过节点集合] # clk1到clk2的所有跨域路径均设为伪路径 set_false_path -from [get_clocks clk1] -to [get_clocks clk2]set_clock_groups -asynchronous | -exclusive -group 时钟集合1 -group 时钟集合2 -asynchronous异步时钟域间所有路径均不做时序检查。 -exclusive互斥时钟两个时钟永远不会同时工作如时钟切换电路的输出。 # clk1和clk2为异步时钟域互相不检查时序 set_clock_groups -asynchronous -group [get_clocks clk1] -group [get_clocks clk2] # 三个异步时钟域两两之间均不检查时序 set_clock_groups -asynchronous -group [get_clocks clk_sys] -group [get_clocks clk_ddr] -group [get_clocks clk_adc]当二者为异步时钟可直接用set_clock_groups约束。非异步时钟可能同源非同周期时钟可用set_false_path来特别约束不需要分析的路径例如set_false_path -from [get_clocks clk_out2_clk_wiz_0] -to [get_clocks clk_out1_clk_wiz_0] -through [get_nets -hierarchical *reset_sync*]上述约束解决跨时钟域的reset信号复位报红问题。set_multicycle_path N [-setup | -hold] [-start | -end] -from 起点集合 -to 终点集合 具体看第四章介绍set_max_delay 最大延迟值 -from 起点 -to 终点 set_min_delay 最小延迟值 -from 起点 -to 终点 set_max_delay仅作用于 setup 检查强制路径最大延迟上限可用于强制放宽捕获沿。 set_min_delay仅作用于 hold 检查强制路径最小延迟下限可用于修复 hold 违例。 # 强制clk1到clk2路径最大延迟不超过10ns set_max_delay 10 -from [get_clocks clk1] -to [get_clocks clk2]7.多周期时序约束1.语法set_multicycle_path path_multiplier [-setup | -hold] [-start | -end] [-from startpoints] [-to endpoints] [-through pins | cells | nets]# path_multiplier 设置修改约束路径分析的时钟周期数必须大于0# -setup / -hold 指定约束命令针对的路径建立时间分析还是保持时间分析# -start / -end 指定path_multiplier参数是源时钟还是目标时钟作为参考时钟# -from 指定约束路径的起始结点startpoints# -to 指定约束路径的终止节点endpoints# -through 可选项指定约束路径所经过的节点pins|cells|nets-from -to可以同时设置如果只设置一个例如-from那么约束会覆盖所有从起始节点startpoints开始的路径setup/recovery分析时path_multiplier参数默认为1hold/removal分析时path_multiplier参数默认为0。约束格式移动对象移动方向偏移量N -setup -startlaunch 发射沿向前时间变小N-1 个发射周期M -hold -startlaunch 发射沿向后时间变大M 个发射周期N -setup -endcapture 捕获沿向后时间变大N-1 个捕获周期M -hold -endcapture 捕获沿向前时间变小M 个捕获周期2.示例clk_out1_clk_wiz_0周期为2nsclk_out2_clk_wiz_0周期为5ns。①vivado默认分析如下图。setup默认找launch沿之后最近的capture沿所以是4ns-5ns。hold默认找launch沿之前最近的capture沿所以是0ns-0ns。建立/保持launch沿nscapture沿nssetup分析45hold分析00②分析hold如果先分析setuphold也会默认跟着一起动-start向后移动launch沿。set_multicycle_path -hold -start 1 -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks clk_out2_clk_wiz_0]建立/保持launch沿nscapture沿nssetup分析45hold分析20③分析hold-end向前移动capture沿。set_multicycle_path -hold -end 1 -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks clk_out2_clk_wiz_0]建立/保持launch沿nscapture沿nssetup分析45hold分析05④分析setup-start向前移动launch沿同时带动hold分析中launch沿向前移动。无论是-start或者-end分析当N设置为1时默认setup和hold都保持不动因为setup沿移动分析需要设置成N-1此时N-11-10所以默认不动。set_multicycle_path -setup -start 1 -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks clk_out2_clk_wiz_0]建立/保持launch沿nscapture沿nssetup分析45hold分析00⑤分析setup。set_multicycle_path -setup -start 2 -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks clk_out2_clk_wiz_0]建立/保持launch沿nscapture沿nssetup分析25hold分析-20此时若要保持hold分析不变需要额外加一句hold约束。由于hold -start/-hold分析时时钟沿移动方向和setup分析时相反正好抵消setup移动时给hold带来的影响注意hold比setup分析移动少1所以M值设置成1。set_multicycle_path -setup -start 2 -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks clk_out2_clk_wiz_0] set_multicycle_path -hold -start 1 -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks clk_out2_clk_wiz_0]建立/保持launch沿nscapture沿nssetup分析25hold分析00⑥分析setup-end向后移动capture沿同时影响hold分析capture沿跟随移动。如果-end分析设置成1如上述说明会保持一致所以直接设置成2。set_multicycle_path -setup -end 2 -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks clk_out2_clk_wiz_0]建立/保持launch沿nscapture沿nssetup分析410hold分析05若要保持hold分析不变需要额外加一句hold约束。set_multicycle_path -setup -end 2 -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks clk_out2_clk_wiz_0] set_multicycle_path -hold -end 1 -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks clk_out2_clk_wiz_0]建立/保持launch沿nscapture沿nssetup分析410hold分析008.建立时间、保持时间slack建立时间的slackslack_su和保持时间的slackslack_hd计算如下图。Tco表示从D触发器的clock的launch沿到Q端出数据的时间Tdata表示数据在两个D触发器之间的逻辑走线延时Tclk_delay表capture时钟到D触发器相对launch时钟到D触发器的延时上述公式可用来分析计算Tsu/Thd/Tclk建立时间slack和时钟周期Tclk有关当前launch沿发送只能在下一个capture沿采集中间间隔一个时钟周期保持时间只和器件有关可理解为下一个launch沿发送的数据不能太早来所以不需要间隔一个时钟周期所以当需要计算整个电路的最小时钟周期可用建立时间公式推导。