赞
踩
(1)概念:
静态时序分析(static timing analysis,STA)是遍历电路存在的所有时序路径,根据给定工作条件(PVT)下的时序库.lib文件计算信号在这些路径上的传播延时,检查信号的建立和保持时间是否满足约束要求,根据最大路径延时和最小路径延时找出违背时序约束的错误。
(2)特点:
优点:不需要给输入激励;几乎能找到所有的关键路径(critical path);运行速度快;
缺点:只适用同步电路;无法验证电路的功能;需要比较贵的工具支持;对于新工艺可能还需要建立一套特征库,建库的代价可能要几百万。
(3)工具:
Synopsys的prime time;
Cadence的Encounter Timing System等
(1)概念:
动态时序分析(dynamic timing analysis,DTA)对所有输入信号给出激励,在testbech(.sp或者.v)中设置一段仿真时间,最后对仿真结果进行时序和功能分析。 仿真可以是门级或者晶体管级,包括spice格式和RTL格式的网表。
(2)特点:
优点:晶体管级的仿真比较精确,直接基于工厂提供的spice 工艺库计算得到;适用于任何电路,包括同步、异步、latch等等;不需要额外搞一套特征库;不需要很贵的时序分析工具。
缺点:需要给不同的测试激励;关键路径无法检查全 (致命性的);规模大的电路spice仿真特别慢 (致命性的)。
(3)工具:
spice仿真器: hspice, finesim, hsim, spectre等;
verilog仿真器: ModelSim,VCS,NC-Verilog,Verilog-XL等。
(1)偏移SKEW
因时钟线长度不同或负载不同,导致时钟到达相邻单元的时间不同,这个时间上的偏差就叫时钟偏移SKEW。
上图中的Tskew=Tc1-Tc2
(1)偏移会一直存在,因此FPGA在设计时,会进行优化,采用全铜工艺和树状结构,设计专门的始终缓冲和驱动网络,使得时钟到达不同单元时的路径一样长,尽量减小偏移。
(2)Skew 问题的解决方法就是:设计中的主要信号应该走全局时钟网络。
(3)此外FPGA中延迟锁定环(Delay locked ring,DLL)也可以去SKEW,延迟锁相环由控制逻辑和延时线组成,控制逻辑将输入时钟与输出时钟进行比较,并插入延时从而使得时钟同步。
(2)抖动Jitter
在理想情况下,一个频率固定的完美的脉冲信号(以1MHz为例)的持续时间应该恰好是1us,每500ns有一个跳变沿。但这种信号并不存在。如图所示,信号周期的长度总会有一定变化,从而导致下一个沿的到来时间不确定。这种不确定就是抖动(jitter)。时钟抖动也永远存在。
(3)占空比失真Duty Cycle Distortion
占空比失真即时钟不对称,高电平和低电平时间发生变化。DCD会占用时间裕量(Slack)造成数字信号的失真,使过零区间偏离理想的位置。DCD通常是由信号的上升沿和下降沿之间时序不同而造成的。
(1)在数字电路中,逻辑门相互连接,组成更加复杂的电路,所以大多数逻辑门的输出端都连接着多个别的单元的输入。所以需要一个术语来描述逻辑门的驱动能力的大小,也就是扇出 Fan-out。最大扇出数 maximum fan-out 定义为一个逻辑门可以驱动的同类逻辑门的最大数。
(2)与扇出相对的概念是 扇入 Fan-in,它描述的是一个逻辑门能够处理的外部输入的能力。扇入大的逻辑门的速度要比扇入小的慢,原因是增加扇入相当于增加逻辑门的输入电容。我们可以用使用多级逻辑门来代替高扇入的设计。
建立时间:触发器时钟上升沿到来前数据保持稳定的时间。
保持时间:触发器时钟上升沿到来前数据保持稳定的时间。
时钟到来之前,数据需要提前准备好;时钟到来之后,数据还要稳定一段时间。建立时间和保持时间组成了数据稳定的窗口,如下图所示:
约束条件:
设电路与相应的时序图如下所示:
则有:
(1)建立时间满足条件:Tsu <= Tclk + Tskew - Tcq - Tcomb
Tsu:建立时间
Tclk:一个时钟周期的时间
Tskew:时钟偏移时间
Tcq: 寄存器 clock 端到 Q 端的延迟
Tcomb:组合逻辑延时
则最小时钟周期 Tclk = Tcq + Tcomb + Tsu - Tskew,最快频率为1/Tclk
(2)保持时间满足条件:Thd <= Tcq + Tcomb - Tskew
为了方便理解,可借鉴如下示意图:
建立/保持时间部分例题可参考 https://www.runoob.com/w3cnote/verilog2-setup-hold-time.html
(1)亚稳态 (Metastability):
其本质为没有满足建立时间或保持时间的时序要求,此时触发器输出端Q在有效时钟沿之后比较长的一段时间处于不确定的状态,在这段时间里Q端在0和1之间处于振荡状态,而不是等于数据输入端D的值。这段时间称为决断时间Tmet(resolution time)。经过resolution time之后Q端将稳定到0或1上,但是稳定到0或者1,是随机的,与输入没有必然的关系。
亚稳态振荡时间 Tmet 关系到后级寄存器的采集稳定问题,Tmet 影响因素包括:器件的生产工艺、温度、环境以及寄存器采集到亚稳态里稳定态的时刻等。甚至某些特定条 件,如干扰、辐射等都会造成 Tmet 增长。
只要系统中有异步元件,亚稳态就是无法避免的,亚稳态主要发生在异步信号检测、跨时钟域信号传输以及复位电路等常用设计中。由于产生亚稳态后,寄存器Q端输出在稳定下来之前可能是毛刺、振荡、固定的某一电压值。在信号传输中产生亚稳态就会导致与其相连其他数字部件将其作出不同的判断,有的判断到“1”有的判断到“0”,有的也进入了亚稳态,数字部件就会逻辑混乱。
(2)如何防止亚稳态
首先,在同步系统中,输入信号总是系统时钟同步,能够达到寄存器的时序要求,所以亚稳态肯定不会发生。在异步系统的信号输出过程中,如果无法满足建立时间和保持时间的要求则会发生亚稳态。
预防亚稳态的方法就是将输入信号(单bit信号)打拍,也就是在要使用的时钟域下,将信号寄存。
单比特信号从慢速时钟域同步到快速时钟域需要使用打两拍的方式消除亚稳态。第一级寄存器产生亚稳态并经过自身后可以稳定输出的概率为 70%~80%左右,第二级寄存器可以稳定输出的概率为 99%左右,后面再多加寄存器的级数改善效果就不明显了,所以数据进来后一般选择打两拍即可。
**原理:**当第二个采样时钟对reg1进行采样时,在第二个clk上升沿的建立时间和保持时间的范围内 reg1保持在稳定的概率要比第一个时刻大得多,相应的发生亚稳态的概率也会减小
这里注意,该方法仅仅适用单比特信号从慢速时钟域同步到快速时钟域,单比特信号从快速时钟域同步到慢速时钟域还仅仅使用打两拍的方式则会漏采数据。
参考 https://blog.csdn.net/wuzhikaidetb/article/details/119619162
(1)电平信号
电平信号是指长时间保持不变的信号。采用双级触发器缓存法(延迟打拍法)
(2)脉冲信号
起点时钟域将脉冲转电平变化;终点时钟域使用双触发器同步,并随后检测电平变化,转换成脉冲。
(1)电平信号
由于电平信号是缓变信号(相对于慢时钟),因此仍然可以采用延迟打拍法。
(2)脉冲信号
与慢到快时钟的方法一致,但快时钟需要确认慢时钟接收到了信号之后再给下一个信号,即添加握手机制。
相关题目:牛客网 VL69 脉冲同步器
格雷码计数器;异步FIFO
(1)阻塞赋值:可以认为是只有一个步骤的操作:计算等号右手方向(RHS)的值,并更新等号左手方向(LHS)部分,且不允许有来自任何其他Verilog语句的干扰。两个阻塞赋值采用同一个时钟沿出发,其顺序不确定,可能会引发竞争冒险。
(2)阻塞赋值:可以看作是两个步骤,赋值时刻开始时,计算RHS;赋值时候结束时,更新LHS。
为避免总和后仿真中出现的大多数竞争冒险问题:
(1)时序电路建模时,用非阻塞赋值。
(2)锁存器电路建模时,用非阻塞赋值。
(3)用always块建立组合逻辑模型时,用阻塞赋值。
(4)在同一个always块中建立时序和组合逻辑电路时,用非阻塞赋值。
(5)在同一个always块中不要既用非阻塞赋值又用阻塞赋值。
(6)不要在一个以上的always块中为同一个变量赋值。
(7)用$strobe系统任务来显示用非阻塞赋值的变量值。
(8)在赋值时不要使用#0延迟。
(1)动态事件队列(Active):阻塞赋值、计算非阻塞赋值语句右边(RHS)的表达式、连续赋值、执行$display、计算原语的输入和输出的变化。
(2)停止运行的事件队列(Inactive):#0延时阻塞赋值、assignments by delayed(#1)
(3)非阻塞事件队列(NBA):更新非阻塞赋值语句左边变量(LHS)的值
(4)监控事件队列(Observe):执行$monitor、执行$strobe
(5)其他指定的PLI事件队列(Reactive)
(1)$display和$write都可以打印信息,但前后自动换行
(2)$strobe命令会在当前事件结束时完成;而$display在一开始便完成(见层次化事件队列)
(3)$monitor用于持续监测指定变量,只要这些变量发生了变化,就会立即显示对应的输出语句。
(1)总体上:给verilog添加不必要的0延迟会使得定时事件的分析变得很复杂,不建议使用。可以用其他方式代替。
(2)#0 零延迟无法被综合
(3)例子:
reg [2:0] data;
initial begin
data = 2;
end
initial begin
#0 data = 3;
end
如层次化事件队列所述,先执行的是active event(阻塞赋值data = 2;),然后才执行inactive event(zero delay assignments, #0 data = 3;)但不建议这样使用,有其他的替代方案。
(4)用法:零延迟控制被用来控制在多个过程块尝试更新同一变量值时的执行顺序。由于始终和初始化块在相同的仿真时间开始评估,它们的执行顺序是不确定的。具有零控制延迟的语句最后执行,因此可以避免竞争条件。
参考:https://blog.csdn.net/qq_43858116/article/details/128509000
1、同步复位的优缺点
2、异步复位的优缺点
3、同步复位异步释放的结构与优点
总的来说,将非复位的高电平打两拍传入来防止释放时的亚稳态,同时对这两个寄存器传入异步复位信号,来保证系统的复位是异步的。
4、复位网络:有缺陷的复位分发与正确的复位分发
由于存在亚稳态问题,若各个子区域采用独立的复位电路,则可能造成之间复位信号不在同一拍,因此采用如下方式:
参考链接:知乎 硬件加速设计方法笔记
采用经典的三段式状态机:
需要注意的是,输出的状态可以回到IDLE。为了更高的效率,也可以直接执行IDLE状态的内容。
`timescale 1ns/1ns module sale( input clk , input rst_n , input sel , input [1:0] din , output reg [1:0] out ); reg [2:0] state, next_state; parameter A = 0, B = 1,C = 2, D = 3, E = 4, F = 5; always @(posedge clk, negedge rst_n) begin if(!rst_n) begin state <= A; end else begin state <= next_state; end end always @(*) begin case(state) A: begin case({sel,din}) 3'b000: next_state <= A; 3'b001: next_state <= B; 3'b010: next_state <= C; 3'b100: next_state <= A; 3'b101: next_state <= E; 3'b110: next_state <= D; default: next_state <= A; endcase end B: begin case({sel,din}) 3'b000: next_state <= A; 3'b001: next_state <= B; 3'b010: next_state <= C; 3'b100: next_state <= A; 3'b101: next_state <= E; 3'b110: next_state <= D; default: next_state <= A; endcase end // 此处省略其他状态 default: begin next_state <= A; end endcase end always @(*) begin case(state) A: drinks_out <= 2'd0; B: drinks_out <= 2'd1; C: drinks_out <= 2'd1; D: drinks_out <= 2'd2; E: drinks_out <= 2'd0; F: drinks_out <= 2'd2; default: out <= 2'd0; endcase end endmodule
采用状态机或者移位寄存器
分为以下3种:
1、有毛刺的时钟切换(采用纯组合逻辑)
2、同源时钟切换
module Glitch_free_clock_switching_syn(clk0,clk1,rst_n,select,out_clk); input clk0,clk1; input rst_n,select; output outclk; reg out0,out1; always@(negedge clk1 or negedge rst_n) begin if(!rst_n) begin out1 <= 0; end else begin out1 <= ~out0 & select; end end always@(negedge clk0 or negedge rst_n) begin if(!rst_n) begin out0 <= 0; end else begin out0 <= ~out1 & ~select; end end assign outclk = (out1 & clk1) | (out0 & clk0)
3、异步时钟切换:消除亚稳态
这是由于~out0 & select信号是从另一个时钟域传来的。
因此:先用一个升沿触发器获取~out0 & select信号,再在降边沿改变输出的out信号。
module Glitch_free_clock_switching_asyn(clk0,clk1,rst_n,select,outclk); input clk0,clk1; //asynchronous:异步 input rst_n,select; output outclk; reg out_r1,out1; reg out_r0,out0; always@(posedge clk1 or negedge rst_n) begin if(!rst_n) out_r1 <= 0; else out_r1 <= select & ~out0; end always@(negedge clk1 or negedge rst_n) begin if(!rst_n) out1 <= 0; else out1 <= out_r1; end always@(posedge clk0 or negedge rst_n) begin if(!rst_n) out_r0 <= 0; else out_r0 <= ~select & ~out1; end always@(posedge clk0 or negedge rst_n) begin if(!rst_n) out0 <= 0; else out0 <= out_r0; end assign outclk = (out0 & clk0) | (out1 & clk1); endmodule
参考解决方案:CSND 时钟切换处理
参考资料:菜鸟教程:时钟分频
在计数器跨时钟域传输的过程中,常常将二进制码转换为格雷码,再采用打拍的方式传输,最后再解码为二进制码。
因为格雷码的反转比特数较少,更难出错 / 引起亚稳态 / 时序违例。
(1)二进制转格雷码
Gn = Bn; Gi-1=Bi ^ Bi-1; ( i=1,2,n-1; )
assign Gray[n-1] = Binary[n-1];
assign Gray[n-2:0] = Binary[n-1:1] ^ Binary[n-2:0];
(2)格雷码转二进制:
Bn =Gn; Bi-1 = Bi ^ Gi-1;( i=1,2,n-1; )
assign Binary[n-1] = Gray[n-1];
assign Binaty[n-2:0] = Binary[n-1:1] ^ Gray[n-2:0];
参考链接:CSDN Verilog实现1位全加器
两种实现方式:
(1)通过真值表直接实现
(2)通过两个半加器实现
相关题目:牛客网 VL72 全加器
注意要点:
(1)采用异或操作可以得到sum
(2)采用与操作可以得到进位
参考链接:超前进位加法器
参考链接:微信 仲裁器设计(一)
参考链接:微信 仲裁器设计(二)
简言之,考虑读写最坏的情况所需要的FIFO深度。
此外,考虑异步FIFO读写指针跨时钟传输有延迟,导致full,empty信号的延时,FIFO的深度应在原基础上增加若干。
参考链接:微信 FIFO深度计算
(1)CMOS:器件是电压控制器件,输入阻抗很大,对干扰信号的捕捉能力很强,所以,不用的管脚不能悬空,要接上拉或下拉电阻,给它一个恒定的电平。悬空时输入阻抗高,易受外界噪声干扰,使电路产生误动作,而且也极易造成栅极感应静电而击穿。
(2)TTL:输入引脚悬空时可以看作是输入端接一个无穷大的电阻,可以看作高电平。
因为悬空时相当于为高阻抗,电压不为零,此时故为1;接地时相当于没有阻抗,此端电压与地电位相同、为零,此时故为0。
以射极输入为例,如果悬空,输入端的那个三极管是截止的,这和输入高电平(即1)的情况是一样的,也就相当于输入1。
在数字逻辑电路中,低电平表示0,高电平表示1。一般规定低电平为0-0.25V,高电平为3.5-5V。
1、CMOS门电路结构:链接
2、TTL门电路结构:链接
3、TTL与非门结构详解:链接
b站全面讲解的视频:linux内核源码分析教程,六大模块全面分析(内存管理、进程管理、设备驱动、…)
参考链接:知乎:深入理解linux虚拟内存机制
参考链接:CSDN:线程、进程、多线程、多进程 和 多任务 小结
1、IIC:
2、SPI:
3、UART:
4、SDIO:SDIO协议浅析
5、CAN:CAN通讯协议指南
(1)定义:使用signed定义为有符号数,默认为无符号数:
reg signed [7:0] a;
wire signed [7:0] b;
(2)表示:有符号数以补码的形式表示,$signed()和$unsigned()函数的作用是告诉编译器所修饰的变量的二进制数据被当作有符号数($signed())或无符号数($unsigned())来处理。并不对变量数据做任何转换操作。
(3)使用:加、减、乘,任何运算的表达式中不能将有符号变量和无符号变量进行混用。必须保证全都为无符号变量或有符号变量,如果至少存在1个无符号变量,那么整个表达式的运算过程会被当作无符号数运算。
(4)重要案例:
reg signed [7:0] a; reg [7:0] b; reg signed [8:0] d; initial begin a = -7; b = 138; $display("a = %b", a); $display("b = %b", b); d = a + $signed(b); $display("d = %b", d); $display("d = %0d", d); d = a + $signed({1'b0, b}); $display("d = %b", d); $display("d = %0d", d); end
仿真结果:
a = 11111001
b = 10001010
d = 110000011
d = -125
d = 010000011
d = 131
第1种用法的结果是错的,第2种用法的结果是正确的。因为138的8位二进制为10001010,其最高位为1,如果直接使用$signed(b),那么编译器会把10001010当作负数(-118)的二进制补码,所以b就被当作-118使用了。正确的方法应该是在最高位之前补上1个正数的符号位0,确保补码为正数。
参考:https://blog.csdn.net/MmikerR/article/details/106444181
(1)CMOS,LVCMOS
(2)TTL,LVTTL
(3)LVDS
(4)RS232、RS485/RS422
(5)SSTL
等等
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。