搜档网
当前位置:搜档网 › 数字电路设计中需要考虑的问题1

数字电路设计中需要考虑的问题1

a.FPGA内部资源要比较清楚
b.FPGA型号

1)竞争与冒险
在组合逻辑电路中,某个输入变量通过两条或两条以上的途径传到输出端,由于每条途径延迟时间不同,
到达输出门的时间就有先有后,这种现象称为竞争。
同一信号经过不同路径所需时间不同正是竞争产生的原因,

如果没有传输及门延时,就没有逻辑冒险了,那么(~A)A = 0就没有毛刺了
但是 F = AB 完全按照真值表,A与B几乎同时变化的话,还是会有毛刺的


表达式出现L = (~A)A (偏0冒险) 或者 L = (~A) + A , (偏1冒险)则称出现A冒险,其他信号取特定稳定值时(比如B=1,C=0)
解决办法:a.消除互补项,(通过增加冗余)或者根据卡诺图,出现相切的圈,增加圈使其相交即可
b.输出端加滤波电容
c.加选通控制,使得输出在输入稳定后才有效

F = AB + (~A)C,当B = C = 1时,可改写为 F = (~A) + A,为1冒险,可以加上1电平,故可以加BC项,且不会影响逻辑
F = AB + (~A)C + BC

F = (A + B)((~A) + C),当B = C = 0时, F = (~A)A ,为0冒险,可以乘上(B + C),不会改变其逻辑
F = (A + B)((~A) + C)(B + C)


L = A(~C) + (~A)B + (~A)C
上述L,不会出现B冒险和C冒险

功能冒险的判断: 功能冒险是当多个输入信号同时变化的瞬间,由于变化快慢不同而引起的冒险。
F=AC+(~B)C中, 当ABC:000 -> 001 -> 011 则F:0 -> 1 -> 0 (偏0冒险)

F = A + B 当AB 01 ->00 ->10

竞争冒险的危害:使对脉冲敏感的系统出现误动作,如时钟端口、清零和置位端口对毛刺信号十分敏感,
任何一点毛刺都可能会使系统出错
但是D触发器对毛刺不敏感,除非毛刺出现在时钟上升沿,且满足建立时间和保持时间才会影响系统
通常毛刺都比较短几ns,一般不满足建立时间和保持时间才会影响系统
故用D触发器读取组合逻辑的输出信号,可以大大减少毛刺,类似于将异步电路转化为同步电路


2)TTL(Transistor-Transistor Logic)
TTL电路是电流控制器件,TTL电路的速度快,传输延迟时间短(5-10ns),但是功耗大;
TTL 电路额定高电平和低电平分别是2.4v和0.4v,最小可识别电平(即临界可识别电平)是2v和0.8v。
即系统本身高电平识别是2.4v,但若一个信号受噪声叠加后呈现是2v的电压,此时也可识别为高电平;
低电平额定识别是0.4v,若一个信号受噪声叠加后呈现0.8v的电压时,也可以识别出是低电平。
噪声容限是 0.4v,就是说可以容许信号电平上有叠加上小于0.4v裕度的噪声
CMOS芯片的噪声容限比TTL通常大,因为VOH是离电源电压较近,并且最小值是

离零较近。(VOH可以认为是额定高电平,类似于TTL的2.4V)

数字电路中,由TTL电子元器件组成电路使用的电平。电平是个电压范围,规定输出高电平>2.4V,输出低电平<0.4V。在室温下,
一般输出高电平是3.5V,输出低电平是0.2V。最小输入高电平和低电平:输入高电平>=2.0V,输入低电平<=0.8V,噪声容限是0.4V。


CMOS电路:1逻辑电平电压接近于电源电压,0 逻辑电平接近于 0V。而且具有很宽的噪声容限。
通常TTL与CMOS都是指Vcc = 5V时的情况,
对于Vcc = 3.3V时的情况,是LVTTL 和LVCMOS ,其实还有Vcc = 2.5V时的LVCMOS
CMOS : Vcc:5V;VOH>=4.45V;VOL<=0.5V;VIH>=3.5V;VIL<=1.5V。噪声容限接近1V
LVCMOS : Vcc:3.3V;VOH>=3.2V;VOL<=0.1V;VIH>=2.0V;VIL<=0.7V。
LVCMOS : Vcc:2.5V;VOH>=2V;VOL<=0.1V;VIH>=1.7V;VIL<=0.7V。

TTL : Vcc:5V;VOH>=2.4V;VOL<=0.5V;VIH>=2V;VIL<=0.8V。
LVTTL: Vcc:3.3V;VOH>=2.4V;VOL<=0.4V;VIH>=2V;VIL<=0.8V。
LVTTL: Vcc:2.5V;VOH>=2.0V;VOL<=0.2V;VIH>=1.7V;VIL<=0.7V。

从以上数据可以看出LVTTL与LVCMOS是可以相互驱动的,是兼容的,但是: TTL不能驱动CMOS,虽然CMOS可以驱动TTL
Vcc= 5V时,TTL电路驱动COMS电路时加上拉电阻1.5K - 4.7K,这样就没有问题了(只要拉高原先的2.4V到3.5V就可以啦!)
另外3.3V LVCMOS 可以直接驱动5V的TTL电路
1)TTL电路是电流控制器件,而CMOS电路是电压控制器件。
2)TTL电路的速度快,传输延迟时间短(5-10ns),但是功耗大。
CMOS电路的速度慢,传输延迟时间长(25-50ns),但功耗低。
CMOS电路本身的功耗与输入信号的脉冲频率有关,频率越高,芯片集越热,这是正常现
象。


3)单片机I/O电路结构:
51单片机P1.0 -- P1.7为准双向端口(内置了上拉电阻)
作为输出口时,如果内部没有上拉,且外部悬空,则该管脚悬空,电平未定,如果内部未上拉,外部下拉,则改端口始终输出低电平
作为输入时,应先在P1口写入1,使得端口内部与地间的开关管断开(因为写0时,P1输出就为0,就是输入为高也会被拉低的)
OC门电路
集电极开路,输出(通常)接电源Vcc'及上拉电阻,这样可以实现线与逻辑,而且可以实现电平转换,输出的电平由Vcc'决定,输入端电源VCC
线与逻辑是两个输出信号相连可以实现与的功能。在硬件上,要用oc门来实现,由于不用 oc门可能使灌电流过大,而烧坏逻辑门
对与IC的驱动管脚,从该脚流出的是source current(拉电流),流入的是sink current (灌电流)



4)同步电路与异步电路:
同步电路是由时序电路(寄存器和各种触发器

)和组合逻辑电路构成的电路,所有操作都是在严格的时钟控制下完成的,
这些时序电路共享同一个时钟clk,所有状态的变化都是在时钟的上升沿完成的;
异步电路主要是组合逻辑电路,其逻辑输出与任何时钟信号都没有关系;
异步电路也用在时序电路中,此时它没有统一的时钟,状态变化的时刻是不稳定的,一个时刻允许一个输入发生变化,以避免
输入信号之间造成竞争冒险(似乎异步逻辑更合适),电路的稳定需要可靠的建立时间和保持时间;
同步逻辑是时钟之间有固定的因果关系。异步逻辑是各时钟之间没有固定的因果关系。

5)建立时间、保持时间和亚稳态
建立时间:触发器在时钟沿来到前,其数据输入端的数据必须保持不变的时间;保持时间:触发器在时钟沿来到后,
其数据输入端的数据必须保持不变的时间
因为触发器内部数据的形成是需要一定的时间的,如果不满足建立和保持时间,触发器将进入亚稳态,进入亚稳态后触发器的
输出将不稳定,在0和1之间变化,这时需要经过一个恢复时间,其输出才能稳定,但稳定后的值并不一定是你的输入值。这就
是为什么要用两级触发器来同步异步输入信号。这样做可以防止由于异步输入信号对于本级时钟可能不满足建立保持时间而使
本级触发器产生的亚稳态传播到后面逻辑中,导致亚稳态的传播。两级触发器可防止亚稳态传播的原理:假设第一级触发器的
输入不满足其建立保持时间,它在第一个脉冲沿到来后输出的数据就为亚稳态,那么在下一个脉冲沿到来之前,其输出的亚稳
态数据在一段恢复时间后必须稳定下来,而且稳定的数据必须满足第二级触发器的建立时间,如果都满足了,在下一个脉冲沿
到来时,第二级触发器将不会出现亚稳态,因为其输入端的数据满足其建立保持时间。同步器有效的条件:第一级触发器进入
亚稳态后的恢复时间 + 第二级触发器的建立时间 < = 时钟周期。

考虑D1、D2及其之间的组合逻辑 详细分析参考百度文库《建立时间与保持时间》
第一种情况:忽略时钟clk延时情况下,可以不考虑保持时间
通常不用考虑D1、D2共用时钟clk的延时,FPGA全局时钟网络可以保证延时可以忽略,
通常也不用考虑D2的保持时间,这个是因为通常数据都保持一个时钟,同时又有线路的延时,故到达D2的信号相对于时钟会后移
一点,这样自动就满足保持时间的要求了
T - Tco - Tdelay > T3 T:时钟周期,Tco:寄存器输出延迟时间:时钟沿后多长时间输出有效(稳定),
Tdelay:组合逻辑延时或D1 输出端到 D1输入端间信号传输延时 T3: D2的建立时间

D2的建立

时间与保持时间与D1的建立时间与保持时间是没有任何关系的,而只与D2前面的组合逻辑延时和D1的输出延时有关系

skew是指时钟偏移,同样的时钟产生的多个子时钟信号之间的延时差异。它表现的形式是多种多样的,既包含了时钟驱动器的
多个输出之间的偏移,也包含了由于PCB走线误差造成的接收端和驱动端时钟信号之间的偏移


6) IC设计中同步复位与 异步复位的区别。(南山之桥)
解答:
1)同步复位和异步复位在FPGA的实现与所选的器件有关。有些器件里的触发器本身就具有同步/ 异步复位端,在这样的器件
中,异步复位和同步复位在走线上是没有区别的。区别只在于是否与时钟有关。在这样的器件中,只要不是在复位一结束信
号(例如多位的计数器)的值就发生跳变,应该是没有影响的。
2)如果器件只能完成异步复位,那同步复位实际上是由逻辑完成的。在这种情况下,有可能增加你的逻辑资源。
3)如果想采用异步复位,又想避免复位结束时,有些触发器处于复位状态,有些触发器处于工作状态的情况(由于skew造成),
可以在复位输入的起始路径上加入一级D触发器。并限制同步后复位信号的max_delay。
总之,需要根据你的应用情况选用不同的复位形式。
7)异步复位,同步释放
module Reset_Synchronizer(
input clk,
input asyncrst_n,
output reg rst_n
);

always @(posedge clk or negedge asyncrst_n)
if(!asyncrst_n)
{rst_n,rff1} <= 2'b0;
else
{rst_n,rff1} <= {rff1,1'b1};

endmodule

//分析:异步复位信号变为低电平,则rst_n 也会变低以复位后继系统,当异步复位信号变高后,当clk上升沿到来时,rst_n不是立刻变为高,
//rst_n还要持续有效一个时钟,这样rst_n就与时钟clk同步了,这就是所谓的异步复位,同步释

放!

或者直接将asyncrst_n 通过D触发器寄存一次,该输出作为后继系统的复位信号,效果一样吗?
效果不一样吧!由于asyncrst_n释放时可能不满足D1的建立时间,这样一级寄存输出是会出现亚稳态的,需要二级寄存输出的。

Trecovery ( recovery time) 指的是原本有效的异步复位信号释放(对低电平有效的复位来说就是上跳沿) 与紧跟其后的第一个时钟有效沿之间
所必须间隔的最小时间。
Tremoval ( removal time) 指的是时钟有效沿与紧跟其后的原本有效的异步复位信号变得无效之间所必须间隔的最小时间。
关于removal time的精辟解释
在带有复位端的D触发器中,当reset信号复位有效,它可以直接驱动最后一集的输出与非门,令输出端口置位1或者0,这就是异步复位。
当这个复位信号release时,q的输出由前一级的内部输出决定。但是由于reset不仅作用于最后一级门电路,而且还要作为前一级电路的
输入信号,如此前一级的内部输出也受到了复位信号的影响,前一级的内部电路实际上实现了一个保持功能,即在时钟跳变附近锁住当时的输入值。
这个维持电路,在时钟附近如果reset有效的话,它会锁住reset的值,如reset 释放那么这个维持电路就会锁住d输入值,如此当reset
释放发生的地方靠时钟沿很近,那么这个维持电路就可能既没有时间维持reset值,也没有足够的时间维持d输入了。造成亚稳态问题,
并通过最后一级与非门传到了输出。
如果reset信号释放的时间能够晚一点的话,也就是说维持电路有足够的时间来锁住reset,这段小的时间要求就是所谓的removal time了。


7)moore与mealy状态机
Moore型与Mealy型两种状态机的不同点

在于,Moore型状态机的输出信号是直接由状态寄存器译码得到,而Mealy型状态机则是以现时的输入
信号结合即将变成次态的现态,编码成输出信号。
Mealy的输出是组合逻辑,Moore输出则是同步逻辑

8)多时域设计中,如何处理信号跨时域
不同的时钟域之间信号通信时需要进行同步处理,这样可以防止新时钟域中第一级触发器的亚稳态信号对下级逻辑造成影响,其中对于单个
控制信号可以用两级同步器,如电平、边沿检测和脉冲,对多位信号可以用FIFO,双口RAM,握手信号等。
当同步的是地址时,一般该地址应采用格雷码,因为格雷码每次只变一位,相当于每次只有一个同步器在起作用,这样可以降低出错概率,
象异步FIFO的设计中,比较读写地址的大小时,就是用这种方法。
(乒乓操作、握手、FIFO)
2 异步FIFO设计中的问题与解决办法
2.1 亚稳态问题
在含有触发器的电路中往往会出现亚稳态问题。亚稳态会使异步FIFO的读写地址发生错误,产生误读或者误写。为此异步FIFO设计中亚稳态问题
也是一个比较重要的问题。亚稳态不可能完全消除,只能使其出现的概率降到最低。主要有2种方法来降低亚稳态出现的概率: 锁存器电平触发
会把输入端的毛刺带入输出;而触发器由于边沿作用可以有效抑制输入端干扰;
①采用触发器冗余方式。即采用多个触发器级联的方式,使本来出现概率为P的亚稳态,其出现概率降低到P2,但这种方式会导致延时增

加。
②使用格雷码。格雷码的相临码元之间只有一位发生变化,这就大大地降低了亚稳态出现的概率。本文采用格雷码方式。
11)与或型逻辑表达式转化成与非逻辑
L=L''所以AD+BD+CD+ABC=(AD+BD+CD+ABC+)''
=[(AD)'(BD)'(CD)'(ABC)']'


9)锁存器与触发器的区别:
锁存器输出会有毛刺,触发器输出

10)给了reg的setup,hold时间,求中间组合逻辑的delay范围。(飞利浦-大唐笔试)
Delay < period - setup – hold 这个有问题吧!不考虑clk skew时 Delay < period - setup – Tco Tco为触发器输出延时


11)画状态机,接受1,2,5分钱的卖报机,每份报纸5分钱。
分析:可以定义 0 1 2 3 4这5个状态,另外要加一个结算状态5(按下确定按钮后,即输入money过程结束)
0状态接收1 2 5分钱可以跳到1 2 0状态,0状态可以不响应结算按钮,
1 2 3 4状态都可以接收1 2 5分钱跳到相应状态,也可以响应结算按钮,调到结算状态5
状态5只持续一个时钟,然后自动回到状态0,开始下一轮交易
其间需要一个计数器count,在合适的状态转化下,count会增加,其值即输出的报纸份数,找零由状态决定
(例如如果状态3跳到状态5,则找零3分钱)
需要一个复位信号,

12)
用VERILOG或VHDL写一段代码,实现消除一个glitch ???????如何消除毛刺


13)one bit full adder :
Logic sum = (a xor b) xor cin //异或逻辑 assign out = ((~a) & b) | ((~b) & a); //异或操作no glitch
cout = (a & b) | (b & cin) | (a & cin);
4位全加器可以通过4个一位全加器级联得到
14)3分频电路会吗?(用到上升沿与下降沿)奇数分频可以参考该思路
module fen_pin(
clk,
rst_n,
clk_div3 //can't be reg,because 3 fen pin

//out
);
input clk;
input rst_n;
output clk_div3;

/////////////////////////////////////////
//posedge cnt
reg [1:0] cnt = 0;
always @(posedge clk)
if(!rst_n)
cnt <= 0;
else
begin
if(cnt == 2)
cnt <= 0;
else
cnt <= cnt + 1;
end

//negedge count
reg [1:0] count = 0;
always @(negedge clk)
begin
if(!rst_n)
count <= 0;
else
count <= cnt;
end


assign clk_div3 = (cnt == 2) | (count == 1); //no glitch
endmodule

13) 请画出用D触发器实现2分频的逻辑电路?
就是把D触发器的输出端加非门接到D端。

module reg_initial(clk,led);
input clk;
output led;

reg [7:0] tmp = 8'd111; //综合器可以综合的,验证过了

assign led = (tmp == 8'd111);//此时RTL视图里 led输出1, led = (tmp = 8'd111);此时输出0

endmodule

14)二倍频
`timescale 1 ns/ 1 ns //仅用于仿真
module twice(
clk,
clk_ou

t
);
input clk;
output clk_out;

wire clk_delay;
assign #5 clk_delay = clk; //仅用于仿真,似乎不可综合 pi/4相位延时

assign clk_out = clk_delay ^ clk;


endmodule

///////////////////////////////////////////
module div2(
input clk,
input rst_n,
output led
);

reg cnt;//reg cnt = 0; //赋初值,仿真波形正确,不赋初值,状态不定x,但是RTL视图是一样的,没有用到
//D触发器的清零端和预置位端(可以异步操作),实际应用就算不赋初值应该也能用
always @(posedge clk)
cnt <= ~cnt;

//always @(posedge clk)
////if(!rst_n)
//// cnt <= 0;
//cnt <= cnt + 1;
////else
//// cnt <= ~led;
//// cnt <= ~cnt;

assign led = cnt;
endmodule

//FPGA内部资源LE: 4输入查找表 + 1位寄存器 + 相关逻辑
//故以下代码就消耗了64个LE,组合逻辑通常消耗的LE是不会太多的,例如8个输入的任何逻辑,才消耗2个LE
//如果输出的信号没有用到内部定义的寄存器(reg),则综合后就没有那些寄存器了。
reg [31:0]cnt;//no use
reg [31:0] tmp;
reg [31:0] tmp1;

always @(posedge clk)
cnt <= cnt + 1;

always @(posedge clk)
tmp <= cnt;

always @(posedge clk)
tmp1 <= tmp;

assign led = tmp;


9bit*9bit乘法器
input [18:0] a;
input [7:0] b;
assign led = a * b;//综合用掉3个乘法器,另外还消耗了9个LE,消耗逻辑资源LE是因为是几个乘法器协调逻辑信号

用LE实现乘法器是很耗资源的,
例如EP1C没有内嵌乘法器,实现16bit*16bit无符号乘法,消耗346个LE,有符号乘法322个LE
如果是32bit*32bit,消耗1210个LE
16bit的除法信号288LE


EP1C6Q240C8 //命名可知,含大约6K 个LE,240个管脚
FPGA内部资源
1.可编程输入输出单元IO
2.可编程逻辑单元LE
3.嵌入式块RAM
4.丰富的布线资源
5.底层嵌入功能单元PLL DLL DSP(指乘法器)
6.内嵌专用硬核

LE: 4输入查找表 + 1个可编程寄存器(one bit) + 一条进位链 + 一条寄存器级联链

LE有两种工作模式:一普通模式,二算术模式
普通模式主要是指进行一般的逻辑运算,
算术模式指加法

、计数器、累加器、比较器等

时钟资源:全局时钟网络、锁相环


以MOS(Metal-Oxide Semiconductor)管作为开关元件的门电路称为MOS门电路
其制造工艺简单、集成度高、功耗小以及抗干扰能力强
MOS门电路有三种类型:使用P沟道管的PMOS电路、使用N沟道管的NMOS电路和同时使用PMOS和NMOS管的CMOS电路。
其中CMOS性能更优,因此CMOS门电路是应用较为普遍的逻辑电路之一。

基本门电路

由于CMOS非门电路工作时总有一个管子导通,所以当带电容负载时,给电容充电和放电都比较快。CMOS非门的
平均传输延迟时间约为10ns

扇出系数 :一个逻辑门电路能驱动与之同类逻辑门的个数
扇入系数 :门电路允许的输入端的数目,典型门电路的扇入系数对NOR为4,对NAND为6
好的系统的平均扇入,扇出系统通常是3或4

CMOS门电路多余引脚不能悬空

CMOS传输门可以
1.实现2选1数据选择器
2.模拟开关,数字信号控制的开关


(4)传输延迟与功耗。CMOS电路的功耗很小,一般小于1 mW/门,但传输延迟较大,一般为几十ns/门,且与电源电压有关,
电源电压越高,CMOS电路的传输延迟越小,功耗越大。前面提到74HC高速CMOS系列的工作速度己与TTL系列相当。
(5)扇出系数。因CMOS电路有极高的输入阻抗,故其扇出系数很大,一般额定扇出系数可达50。但必须指出的是,扇出系
数是指驱动CMOS电路的个数,若就灌电流负载能力和拉电流负载能力而言,CMOS电路远远低于TTL电路。


卡诺图化简
F(A,B,C,D) = sigma m(0,1,3,6,13,15)
wire [3:0] num;
assign num = {A,B,C,D}; num = 0,1,3,6,13,15时,F(num) = 1;
卡诺图的构造特点使卡诺图具有一个重要性质:可以从图形上直观地找出相邻最小项。两个相邻最小项可以合并为一个与项
并消去一个变量。
缺点:当变量的数目超过6时.画图就变得复杂了,也不容易计算.........
逻辑函数未用最小项表示照样可以化简 (那就自己根据真值表填呗)
在填入卡诺图过程中就能把函数展开成最小项
AB/CD 00 01 11 10
AB/CD为什么这么排列,是有原因的,这样相邻的两个元素都有一个相同的值如 (00 与 01,此时A = 0)
(01 与 11,此时B = 1) (11 与10,此时A = 1), (00 与 10,此时B = 0,虽在边缘,但是仍认为相邻)

查找表(LUT)结构本质上是一个RAM,它类似于一块有4个输入、16个输出的16bit的存取器(当然也有5输入的结构), 这个
存取器里面储存了所有可能的结果,当用户通过原理图或者HDL语言来描述一个逻辑电路

时,PLD/FPGA的综合软件和布局布线
软件会自动计算逻辑电路中所有可能的结果,并且把结果事先写入RAM。这样对输入信号进行逻辑运算就相当于输入一个地址
进行查表,找出并输出地址对应的内容。如果把输出的D触发器旁路而直接输出,则便实现了组合逻辑,反之,如果有D触发器
则实现了时序逻辑。
由于FPGA基于SRAM的查找表,故需要配置芯片(如EPCS),CPLD通常就不需要了(基于EEPROM or flash)

****不完全的if 和 case赋值可能综合出latch,不是一定综合出latch

/////////////////////////////
从下面的代码可知知道资源利用情况 用掉2个LE
module div2(
input clk,
input a,
input b,
input c,
output d,
output reg [1:0] led
);


//reg [7:0] tmp11;
always @(posedge clk)
led <= {a,d}; //如果 led <= {a,~d}; 则消耗3个LE


assign d = (a & b) | (a & (~b) & (~c));

endmodule
1个LE只能有一个逻辑输出(可对应4输入),


以下计数器综合结果:
Reg [1:0] led;
always @(posedge clk)
led <= led + 1;

LED[0]非门加D触发器,LED[1]是异或加D触发器
所以N位的计数器(递增1)消耗N个LE,同时也消耗了LE里面的查找表,也就是这N个LE再也不能用在其他地方了
Reg [7:0] led;
always @(posedge clk)
begin
if(led == 3) //这样会额外消耗8个LE来进行比较逻辑
led <= 0;
else
led <= led + 5;//{~a,d};
end


/////////////////////////////////////
always @(posedge clk)
begin
if(led == 99) //这样会额外消耗8个LE来进行比较逻辑
led <= 0;
else
led <= led + 1;//{~a,d};
end



assign d = (a & b) | (a & (~b) & (~c));
assign e = (led > 25) & (led < 50); //只增加1个LE,说明用到这个逻辑比较与上面的比较逻辑 if(led == 99)共用了一些资源,
//如果完全无关,增加一个显然不行的,少说也3个吧!可以这样验证,去掉if()测试增加3个
assign f = (led > 11) & (led < 33); //同样只增加1个LE


无论a还是x的fpga,IO脚的基本结构都差不多,输出都是推拉mos管,能够实现三态、可编程的上下拉电阻等等

卡马克快速平方根


一、能不用复位的就别用了。
reset,作为一个实际存在的物理信号,需要占用FPGA内部的route资源,往往reset的fanout又多得吓人。这就很容易造成route难度上升,
性能下降,编译时间增加。因此,在FPGA设计中能省略的复位应尽量省略。
举几个我经常省略复位的地方,但不是绝对适用:
1.分频用的计数器
除非需要控制初始相位,否则分频用的计数器往往都是自由运行的,只要每个时钟加1就好。
2.移位寄存器
为了使pipeline配合正确,设计中经常会存在移位寄存器。这种情况下,你只要复位第一级寄存器,然后保持若干个周期,移位寄存器就
被彻底复位了,而不用为每个bit都添加复位。移位寄存器不使用复位的又一个好处是可以利用SRL。
3.moore型状态机输出
对于那些moore型状态机的输出,你只要复位了状态机,下一个周期就会被复位。
不用复位可能会引起的一个问题是仿真时出现一堆的X。这个问题可以通过在HDL文件中为寄存器赋初值

解决。

单精度浮点float存储方式
unsigned int a = 0x49E48E68; //1872333.000 的float存储值, 32 bit
printf("a = %f\n",*(float *)&a);//打印1872333.000

float f = 3.141592654;
printf("f = %x\n",*(unsigned int *)&f);//0x40490FDB

[31:0]
31 -> S
30:23 -> e
22: 0 -> x
(-1)^S * (1 + x) * 2^(e - 127)

3.14
二进制大约11.001001
左移一位1.1001001(左右移的位数这样确定,最终保持小数点前一位是1即可)
e = 左移的位数 + 127;
x = 小数点后的23位二进制,很大的额
故x = 0x490000
0x40490000 //2'b0100 0000 0100 1001 .....


//以下是可综合的,综合8位全加器,消耗16个LE,比自己写的消耗资源多(用xor,onebit_full_adder搭的,仅6个LE)
integer i;
reg c;

always @(*)
begin
c = cin;
for(i = 0; i < 8; i = i + 1)
{c,sum[i]} = a[i] + b[i] + c; //相互之间未共用资源

end
assign cout = c;

//可综合的函数,不过函数要定义在module里面
function [4:0] full_add;
input [3:0] a;
input [3:0] b;
input cin;

begin
full_add = a + b + cin;
end


endfunction

//函数调用,其中wire [4:0] res;
assign res = full_add(a[3:0],b[3:0],cin); //综合消耗6个LE



两年半载积累之提高电路时钟频率的几种方法_QuartusII
对于提高电路时钟频率的方法,最有效的无非是自己设计电路的时候尽量不要在关键路径上的一个时钟周期内做太多组合逻辑
的运算,很费时的,能够几个时钟周期平摊的就平摊下;另外,写代码的时候,风格也很重要,尽量不要在关键路径上写三重门
运算的,时钟速度很受影响的。
另外还可以:在TimeQuest中对时钟信号添加约束;
通过将一些非全局高扇出信号拉到全局时钟线或局部时钟线上,即挂到全局时钟树或局部时钟树上


关键路径:电路中频繁调用,而且延迟比较大,或者产生意外的几率比较大的线路


output reg clk_div2;
wire clk_temp;
always @(posedge clk)
begin
clk_div2 <= clk_temp;
end
assign clk_temp = ~clk_div2;

reg q = 0;
always@(posedge clk )
begin


q <= ~q;
end
assign led[1] = q;


Clock-to-Output Delay(tco) 这个时间指的是当时钟有效沿变化后(就沿对应时刻吧),将数据推倒同步时序路径的输出端的最小时间间隔。

分频时钟和源时钟的skew不容易控制,难以保证分频时钟和源时钟同相。故此推荐采用使用时钟使能的方法,通过使用时钟使能可以避免时钟
“满天飞”的情况,进而避免了不必要的亚稳态发生

如果其中至少一个时钟是在FPGA内部通过PLL(锁相环)或者DLL(延迟锁相环)可控制的,另一个时钟与在PLL或者DLL解决方案中那个时钟
周期有倍数关系,那么相位匹配可以用来消除时序冲突
双跳技术可以用于在两个异步时钟区域间对单比特信号进行再同步
当利用双跳的方法时,最重要的是规定时序约束,使得第一和第二种时钟区域之间的信号通过在时序分析时不考虑,因为双触发结构重新同步
化信号,在两个区域之间没有有效的同步通道。此外,在触发器之间的时序应该最小化,以减少准稳定状态通过第二个触发器传播的概率

在FPGA中的FIFO一般用围绕双口RAM的包装来实现的

格雷码可以利用在异步时钟区域之间传递多位计数器的数据,常常利用在FIFO内部

module div2
#(
parameter A = 10;
parameter B = 11
)
(
clk,
led
);

约翰逊(Johnson)计数器又称扭环计数器,是一种用n位触发器来表示2n个状态的计数器
parameter N = 4;
reg [N:0] q;
q = 4'b0000,1000,1100,1110,1111,0111,0011,0001,0000,...
4个寄存器组成移位寄存器,另外加一个非门即可实现

//握手通信
module handshack
(
input clk,
input rst_n,
input req,
input [7:0] datain,
output ack,
output [7:0] dataout
);

reg reqr1,reqr2,reqr3;
reg [7:0] dataoutr;
reg ackr;

always @ (posedge clk,negedge rst_n)
if(!rst_n)
{reqr3,reqr2,reqr1} <= 3'b111;
else
{reqr3,reqr2,reqr1} <= {reqr2,reqr1,req};

wire pos_req1 =reqr1 & ~reqr2;
wire pos_req2 =reqr2 & ~reqr3;
assign dataout = dataoutr;


assign ack =ackr;

always @ (posedge clk,negedge rst_n)
if(!rst_n)
dataoutr <= 8'h00;
else if(pos_req1)
dataoutr<= datain;

always @ (posedge clk,negedge rst_n)
if(!rst_n)
ackr <= 1'b0;
else if(pos_req2)
ackr <= 1'b1;
else if(!req)
ackr <= 1'b0;
endmodule


输入信号:i_pulse,输出信号:o_found,输入信号是一个比时钟还要窄的脉冲,请问如何在该脉冲发生后及时检测到,并输出
o_found = 1进行指示。注意:o_found的输出可以比输入脉冲晚几个时钟周期,但是不能延迟太长。
补充约束:两个脉冲间隔大于一个时钟周期
解答:
可以用i_pulse作二分频电路的时钟,这样来一个脉冲(上升沿),输出翻转(跳变)一次,
这个跳变(上升沿或下降沿)是很好检测的,寄存一下,然后异或

具体代码:
reg q = 0;
always @(posedge i_pulse) //输入脉冲作为时钟
begin
q <= ~q;
end

reg q_tmp1 = 0;
reg q_tmp2 = 0;
always @(posedge clk)
begin
q_tmp1 <= q;
q_tmp2 <= q_tmp1;
end

assign o_found = q_tmp1 ^ q_tmp2;//((~q_tmp2) & q_tmp1) | ((~q_tmp1) & q_tmp2);//即q xor q_tmp;

至此完成脉冲上升沿检测,若需检测其下降沿,可以将其取反再检测上升沿;


与非门搭建异或门
F = a ^ b = (!a)b + (!b)a
= ---------------
---------------
(!a)b + (!b)a
=
-------------------
------ --------
-- ---
a * b * a * b

= -------------------
------ --------
-- ---
a * b * a * b 注意 -- = -- = --- 即重复或增加1
a aa 1*a

记住化简为与非只需记住两条:
1)a = (!(!a));
2)!(a + b) = (!a)(!b)
3)(!a) = !(a*a)


比较器:a[7:0],b[7:0]
assign led = (a == b);//消耗5个LE ,4位比较消耗3个LE
assign led = (a > b); //assign led = (a < b); //都消耗8个LE
assign led = (a < 255); //消耗3个LE
a与固定数值比较消耗资源要小一些
assign led = (a == 111);//消耗3个LE


//二进制转格雷码,格雷码只能定义2^n深度
assign wgr

aynext = (wbinnext>>1) ^ wbinnext;

二进制 格雷码
000 000
001 001
010 011
011 010
100 110
101 111
110 101
111 100


gray b0b1b2b3
b0 b0^b1

for(i = 3; i > 4; i = i + 1)



相关主题