1、同步电路和异步电路的区别是什么?(仕兰微电子)
同步电路:存储电路中所有触发器的时钟输入端都接同一个时钟脉冲源,因而所有触发器的状态的变化都与所加的时钟脉冲信号同步。
异步电路:电路没有统一的时钟,有些触发器的时钟输入端与时钟脉冲源相连,这有这些触发器的状态变化与时钟脉冲同步,而其他的触发器的状态变化不与时钟脉冲同步
异步电路主要是组合逻辑电路,用于产生地址译码器、FIFO或RAM的读写控制信号脉冲,其逻辑输出与任何时钟信号都没有关系,译码输出产生的毛刺通常是可以监控的。
同步电路是由时序电路(寄存器和各种触发器)和组合逻辑电路构成的电路,其所有操作都是在严格的时钟控制下完成的。这些时序电路共享同一个时钟CLK,而所有的状态变化都是在时钟的上升沿(或下降沿)完成的。
2、什么是同步逻辑和异步逻辑?
同步逻辑是时钟之间有固定的因果关系。异步逻辑是各时钟之间没有固定的因果关系。
3、什么是"线与"逻辑,要实现它,在硬件特性上有什么具体要求?
线与逻辑是两个或多个输出信号相连可以实现与的功能。在硬件上,要用OC门来实现(漏极或者集电极开路),为了防止因灌电流过大而烧坏OC门,应在OC门输出端接一上拉电阻(线或则是下拉电阻)。
漏极开路(OD),集电极开路(OC)
4、什么是Setup 和Holdup时间,区别是什么?
解释setup time和hold time的定义和在时钟信号延迟时的变化
在理想情况下,只要在时钟沿来临时,有效数据也来临(时钟沿之前或同时),则能够正确采集到数据;而在时钟沿之后(或同时),即使数据发生变化,也不会影响DFF的输出了。然而在实际中,上升沿打开开关需要时间,逻辑门的状态改变(电容充放电等)都需要时间,因此数据的采集是需要一定时间的,在这个时间内数据不能发生变化。上升沿时候开关关闭也需要时间,如果在这个时间段内数据有变化的话,那么新数据就有可能被传递到下一级,进而发生错误,所以数据必须保持一定时间不变。
在clk上升沿来之前,数据必须提前一个最小时间量“预先准备好”,这个最小时间量就是建立时间;
在clk上升沿来之后,数据必须保持一个最小时间量“不能变化”,这个最小时间量就是保持时间。
建立时间(setup time)是指在触发器的时钟信号上升沿到来以前,数据稳定不变的时间,如果建立时间不够,数据将不能在这个时钟上升沿被打入触发器;
保持时间(hold time)是指在触发器的时钟信号上升沿到来以后,数据稳定不变的时间, 如果保持时间不够,数据同样不能被打入触发器。
5、解释setup和hold time violation,画图说明,并说明解决办法
Setup/hold time 是测试芯片对输入信号和时钟信号之间的时间要求.
建立时间是指触发器的时钟信号上升沿到来以前,数据稳定不变的时间.输入信号应提前时钟上升沿(如上升沿有效)T时间到达芯片,这个T就是建立时间-Setup time.如不满足setup time,这个数据就不能被这一时钟打入触发器,只有在下一个时钟上升沿,数据才能被打入触发器.
保持时间是指触发器的时钟信号上升沿到来以后,数据稳定不变的时间.如果hold time 不够,数据同样不能被打入触发器.
建立时间(Setup Time)和保持时间(Hold time).建立时间是指在时钟边沿前,数据信 号需要保持不变的时间.保持时间是指时钟跳变边沿后数据信号需要保持不变的时间.如果不满足建立和保持时间的话,那么DFF将不能正确地采样到数据,将会出现 metastability的情况.如果数据信号在时钟沿触发前后持续的时间均超过建立和保持时 间,那么超过量就分别被称为建立时间裕量和保持时间裕量.
满足建立和保持时间要求,电路状态改变就是正确的,电路功能就不会发生错误;如果不满足,电容就没有足够的时间充放电,造输出点的电平可能既非0也非1,造成“亚稳态“输出。如果前级驱动够强劲,电路就能按照趋势变化下去,一定时间后该点的值就会变化为“正确值”,如果驱动不够强劲,电路就会恢复之前的值,最终得到何值是不可控的,所以我们要避免亚稳态。在使用DFF时,必须满足其建立时间和保持时间的要求。
消除方法
竞争冒险修改设计法:
a、代数法,在产生冒险现象的逻辑表达式上,加上冗余项或乘上冗余因子;
b、卡诺图法,将卡诺图中相切的圈用一个多余的圈连接起来。
竞争冒险选通法:
在电路中加入选通信号,在输出信号稳定后,选通允许输出,从而产生正确输出。
滤出法: 由于冒险脉冲是一个非常窄的脉冲,可以在输出端接一个几百微法的电容将其滤出掉。
竞争冒险常用消除方法:
1、接入滤波电容;
2、引入选通脉冲;
3、修改逻辑设计;
4、.利用可靠性编码;
5、引入封锁脉冲。
https://blog.csdn.net/huigeyu/article/details/89813676
6.锁存器
7、你知道那些常用逻辑电平?TTL与COMS电平可以直接互连吗?
常用逻辑电平:12V,5V,3.3V;
TTL和CMOS不可以直接互连,由于TTL是在0.3-3.6V之间,而CMOS则是有在12V的有在5V的.
CMOS输出接到TTL是可以直接互连.
TTL接到CMOS需要在输出端口加一上拉电阻接到5V或者12V.
8、如何解决亚稳态.
1.1 亚稳态发生原因
在FPGA系统中,如果数据传输中不满足触发器的Tsu和Th不满足,或者复位过程中复位信号的释放相对于有效时钟沿的恢复时间(recovery time)不满足,就可能产生亚稳态,此时触发器输出端Q在有效时钟沿之后比较长的一段时间处于不确定的状态,在这段时间里Q端在0和1之间处于振荡状态,而不是等于数据输入端D的值。这段时间称为决断时间(resolution time)。经过resolution time之后Q端将稳定到0或1上,但是稳定到0或者1,是随机的,与输入没有必然的关系。
1.2 亚稳态发生场合
只要系统中有异步元件,亚稳态就是无法避免的,亚稳态主要发生在异步信号检测、跨时钟域信号传输以及复位电路等常用设计中。
1.3 亚稳态危害
由于产生亚稳态后,寄存器Q端输出在稳定下来之前可能是毛刺、振荡、固定的某一电压值。在信号传输中产生亚稳态就会导致与其相连其他数字部件将其作出不同的判断,有的判断到“1”有的判断到“0”,有的也进入了亚稳态,数字部件就会逻辑混乱。在复位电路中产生亚稳态可能会导致复位失败。怎么降低亚稳态发生的概率成了FPGA设计需要重视的一个注意事项。
2. 理论分析
2.1 信号传输中的亚稳态
在同步系统中,输入信号总是系统时钟同步,能够达到寄存器的时序要求,所以亚稳态不会发生。亚稳态问题通常发生在一些跨时钟域信号传输以及异步信号采集上。
它们发生的原因如下:
(1)在跨时钟域信号传输时,由于源寄存器时钟和目的寄存器时钟相移未知,所以源寄存器数据发出数据,数据可能在任何时间到达异步时钟域的目的寄存器,所以无法保证满足目的寄存器Tsu和Th的要求;
(2)在异步信号采集中,由于异步信号可以在任意时间点到达目的寄存器,所以也无法保证满足目的寄存器Tsu和Th的要求;
当数据在目的寄存器Tsu-Th时间窗口发生变化,也即当数据的建立时间或者保持时间不满足时,就可能发生亚稳态现象。如图3.1所示。
由图可知,当产生亚稳态后Tco时间后会有Tmet(决断时间)的振荡时间段,当振荡结束回到稳定状态时为“0”或者“1”,这个是随机的。因此,会对后续电路判断造成影响。
2.2 复位电路的亚稳态
2.2.1 异步复位电路
在复位电路设计中,复位信号基本都是异步的,常用异步复位电路Verilog描述如下:
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
a <= 1’b0;
else
a <= b;
end
综合出来复位电路模型如图3.2所示:
如图3.3所示,为复位电路复位时序图。如果异步复位信号的撤销时间在Trecovery(恢复时间)和Tremoval(移除时间)之内,那势必造成亚稳态的产生,输出在时钟边沿的Tco后会产生振荡,振荡时间为Tmet(决断时间),最终稳定到“0”或者“1”,就会可能造成复位失败。
2.2.2 同步复位电路的亚稳态
在复位电路中,由于复位信号是异步的,因此,有些设计采用同步复位电路进行复位,并且绝大多数资料对于同步复位电路都认为不会发生亚稳态,其实不然,同步电路也会发生亚稳态,只是几率小于异步复位电路。
如下面verilog代码对同步复位电路的描述。
always @(posedge clk)
begin
if(!rst_n) a <= 1’b0;
else a <= b;
end
综合出硬件电路如图3.4所示
在此,我们不讨论同步复位的消耗资源问题,只讨论同步复位的亚稳态产生情况。
当输入端Din为高电平,而且复位信号的撤销时间在clk的Tsu和Th内时候,亚稳态就随之产生了。如图3.5时序所示,当复位撤销时间在clk的Tsu和Th内,输入数据为“1”,通过和输入数据相与后的数据也在clk的Tsu和Th内,因此,势必会造成类似异步信号采集的亚稳态情况。
2.3 亚稳态产生概率以及串扰概率
在实际的FPGA电路设计中,常常人们想的是怎么减少亚稳态对系统的影响,很少有人考虑怎么才能减少亚稳态发生几率,以及亚稳态串扰的概率问题。
2.3.1 亚稳态发生概率
由上面分析得知,系统亚稳态发生的都是由于clk的Tsu和Th不满足,又或者是复位信号的移除和恢复时间不满足。常用FPGA器件的Tsu+Th约等于1ns,复位移除和恢复时间相加约等于1ns。
当异步信号不是一组数据,或者信号量较少,那就需要对异步信号进行同步处理,例如对一个异步脉冲信号进行采集,只要脉冲信号变化发生在时钟Tsu和Th窗口内,那就很可能会产生亚稳态,亚稳态产生的概率大概为:
概率 = (建立时间 + 保持时间)/ 采集时钟周期 (公式3-1)
由公式3-1可以看出,随着clk频率的增加,亚稳态发生的几率是增加的。
例如,为系统采用100M时钟对一个外部信号进行采集,采集时钟周期为10ns,那采集产生亚稳态的概率为:1ns/10ns = 10%
同理采用300M时钟对一个外部信号进行采集,那产生亚稳态的概率为:1ns/3.3ns = 30%
如果采用三相相位差为120°的时钟对一个外部信号进行采集,那产生亚稳态的概率接近90%
所以在异步信号采集过程中,要想减少亚稳态发生的概率:
(1) 降低系统工作时钟,增大系统周期,亚稳态概率就会减小;
(2) 采用工艺更好的FPGA,也就是Tsu和Th时间较小的FPGA器件;
2.3.2 亚稳态的串扰概率
使用异步信号进行使用的时候,好的设计都会对异步信号进行同步处理,同步一般采用多级D触发器级联处理,如图3.6所示,采用三级D触发器对异步信号进行同步处理。
这种模型大部分资料都说的是第一级寄存器产生亚稳态后,第二级寄存器稳定输出概率为90%,第三极寄存器稳定输出的概率为99%,如果亚稳态跟随电路一直传递下去,那就会另自我修护能力较弱的系统直接崩溃。接下来我们分析这种串扰的概率问题。
如图3.7所示为一个正常第一级寄存器发生了亚稳态,第二级、第三极寄存器消除亚稳态时序模型。
由上图可以看出,当第一个寄存器发生亚稳态后,经过Tmet的振荡稳定后,第二级寄存器能采集到一个稳定的值。但是为什么第二级寄存器还是可能会产生亚稳态呢?
由于振荡时间Tmet是受到很多因素影响的,所以Tmet时间又长有短,所以当Tmet时间长到大于一个采集周期后,那第二级寄存器就会采集到亚稳态。如图3.8所示。
由上图可知,第二级也是一个亚稳态,所以在这种情况下,亚稳态产生了串扰,从第一级寄存器传到了第二级寄存器,同样也可能从第二级寄存器串扰到第三级寄存器。这样会让设计逻辑判断出错,产生亚稳态传输,可能导致系统死机奔溃。
2.3.3 亚稳态振荡时间Tmet
亚稳态震荡时间Tmet关系到后级寄存器的采集稳定问题,Tmet影响因素包括:器件的生产工艺、温度、环境以及寄存器采集到亚稳态离稳定态的时刻等。甚至某些特定条件,如干扰、辐射等都会造成Tmet增长。
- 应用分析
有亚稳态产生,我们就要对亚稳态进行消除,常用对亚稳态消除有三种方式:
(1) 对异步信号进行同步处理;
(2) 采用FIFO对跨时钟域数据通信进行缓冲设计;
(3) 对复位电路采用异步复位、同步释放方式处理。
3.1.1 对异步信号进行同步提取边沿
在异步通信或者跨时钟域通信过程中,最常用的就是对异步信号进行同步提取边沿处理。对一个异步信号进行提取上升沿通常采用程序清单 4.1所示。
程序清单 4.1 双极寄存器提取边沿
input sig_nsyn
wire sig_nsyn_p;
reg[1:0] sig_nsyn_r;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
sig_nsyn_r <= 2’d0;
else
sig_nsyn_r <= { sig_nsyn_r [0], sig_nsyn };
end
assign sig_nsyn_p = sig_nsyn_r[0] & ~sig_nsyn_r[1];
这种边沿提取方式对于一个稳定的系统是不合适的,例如:当第一级寄存器采集到亚稳态,那势必造成sig_nsyn_p输出亚稳态,这样就会对采用sig_nsyn_p的信号进行判断的电路造成影响,甚至判断出错误的值。
根据3.3.1小节的亚稳态产生概率,如果在100M时种下那第一级寄存器产生亚稳态的概率约为10%,随着系统采集频率升高,那产生亚稳态的概率也会随之上升。因此,在进行异步信号跨频提取边沿时候,一般采用多进行一级寄存器消除亚稳态,可能在系统稳定性要求高的情况下,采用更多级寄存器来消除亚稳态,如程序清单 4.2所示,即为采用4级寄存器消除亚稳态,相应的边沿信号产生的时间就晚了两个时钟周期。
程序清单 4.2 多级寄存器提取边沿信号
input sig_nsyn;
wire sig_nsyn_p;
reg[3:0] sig_nsyn_r;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
sig_nsyn_r <= 2’d0;
else
sig_nsyn_r <= { sig_nsyn_r [2::0], sig_nsyn };
end
assign sig_nsyn_p = sig_nsyn_r[2] & ~sig_nsyn_r[3];
3.1.2 FIFO进行异步跨频数据处理
当数据流从一个时钟域到另一个时钟域的时候,绝大多数情况下都采用FIFO来作为中间缓冲,采用双时钟对数据缓冲,就可以避免亚稳态的发生。
3.1.3 异步复位,同步释放
对于复位情况下的亚稳态,常常是由于恢复时间和移除时钟不满足造成的,因此,最常用的处理方式是采用异步复位、同步释放。常用电路模型如所示。采用第二级寄存器输出作为全局复位信号输出。
程序清单 4.3 异步复位处理
wire sys_rst_n;
reg [1:0] rst_r;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
rst_r <= 2’d0;
else
rst_r <= {rst_r[0], 1’b1};
end
assign sys_rst_n = rst_r[1];
通过上面三种方式处理异步信号、异步数据、以及异步复位可有效的提高系统的稳定性。减少亚稳态的产生。
9、IC设计中同步复位与异步复位的区别.
同步复位在时钟沿才复位信号,完成复位动作。异步复位不管时钟,只要复位信号满足条件,就完成复位动作。异步复位对复位信号要求比较高,不能有毛刺,如果其与时钟关系不确定,也可能出现亚稳态。
10、MOORE 与 MEELEY状态机的特征.
两种典型的状态机是摩尔(Moore)状态机和米立(Mealy)状态机。摩尔有限状态机输出只与当前状态有关,与输入信号的当前值无关,是严格的现态函数。在时钟脉冲的有效边沿作用后的有限个门延后,输出达到稳定值。即使在时钟周期内输入信号发生变化,输出也会保持稳定不变。从时序上看,Moore状态机属于同步输出状态机。Moore有限状态机最重要的特点就是将输入与输出信号隔离开来。
Mealy状态机的输出是现态和所有输入的函数,随输入变化而随时发生变化。从时序上看,Mealy状态机属于异步输出状态机,它不依赖于时钟
11、多时域设计中,如何处理信号跨时域.
多时钟域的设计中,对于信号跨时域的处理这里可以采用乒乓操作的方法来进行。乒乓操作的处理流程为:输入数据流通过‘输入数据选择单元”将数据流等时分配到两个数据缓冲区,数据缓冲模块可以为任何存储模块,比较常用的存储单元为双口RAM(DPRAM)、单口RAM(SPRAM)、FIFO等。
在第1个缓冲周期,将输入的数据流缓存到“数据缓冲模块1”;
在第2个缓冲周期,通过“输入数据选择单元”的切换,将输入的数据流缓存到“数据缓冲模块2”,同时将“数据缓冲模块1”缓存的第1个周期数据通过“输入数据选择单元”的选择,送到“数据流运算处理模块”进行运算处理;
在第3个缓冲周期通过“输入数据选择单元”的再次切换,将输入的数据流缓存到“数据缓冲模块1”,同时将“数据缓冲模块2”缓存的第2个周期的数据通过“输入数据选择单元”切换,送到“数据流运算处理模块”进行运算处理。如此循环。
乒乓操作的最大特点是通过“输入数据选择单元”和“输出数据选择单元”按节拍、相互配合的切换,将经过缓冲的数据流没有停顿地送到“数据流运算处理模块” 进行运算与处理。把乒乓操作模块当做一个整体,站在这个模块的两端看数据,输入数据流和输出数据流都是连续不断的,没有任何停顿,因此非常适合对数据流进行流水线式处理。所以乒乓操作常常应用于流水线式算法,完成数据的无缝缓冲与处理。还可以节约缓冲区空间。
还有一种方法,FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端时AD数据采集,另一端时计算机的PCI总线,假设其AD采集的速率为16 位 100K SPS,那么每秒的数据量为100K×16bit=1.6Mbps,而PCI总线的速度为率33MHz,总线宽度32bit,其最大传输速为 1056Mbps可以采,在两个不同的时钟域间就用FIFO来作为数据缓冲。另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而 DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。
不同的时钟域之间信号通信时需要进行同步处理,这样可以防止新时钟域中第一级触发器的亚稳态信号对下级逻辑造成影响,其中对于单个控制信号可以用两级同步器,如电平、边沿检测和脉冲,对多位信号可以用FIFO,双口RAM,握手信号等。
情况比较多,如果简单回答的话就是:跨时域的信号要经过同步器同步,防止亚稳态传播。例如:时钟域1中的一个信号,要送到时钟域2,那么在这个信号送到时钟域2之前,要先经过时钟域2的同步器同步后,才能进入时钟域2。这个同步器就是两级d触发器,其时钟为时钟域2的时钟。这样做是怕时钟域1中的这个信号,可能不满足时钟域2中触发器的建立保持时间,而产生亚稳态,因为它们之间没有必然关系,是异步的。这样做只能防止亚稳态传播,但不能保证采进来的数据的正确性。所以通常只同步很少位数的信号。比如控制信号,或地址。当同步的是地址时,一般该地址应采用格雷码,因为格雷码每次只变一位,相当于每次只有一个同步器在起作用,这样可以降低出错概率,象异步FIFO的设计中,比较读写地址的大小时,就是用这种方法。
如果两个时钟域之间传送大量的数据,可以用异步FIFO来解决问题
不同的时钟域之间信号通信时需要进行同步处理,这样可以防止新时钟域中第一级触发器的亚稳态信号对下级逻辑造成影响,其中对于单个控制信号可以用两级同步器,如电平、边沿检测和脉冲,对多位信号可以用FIFO,双口RAM,握手信号等。
12、给了reg的setup,hold时间,求中间组合逻辑的delay范围.
Delay < period - setup – hold
13、时钟周期为T,触发器D1的建立时间最大为T1max,最小为T1min.组合逻辑电路最大延
迟为T2max,最小为T2min.问,触发器D2的建立时间T3和保持时间应满足什么条件.
https://www.cnblogs.com/lilto/p/9581143.html
18、说说静态、动态时序模拟的优缺点.
19、一个四级的Mux,其中第二级信号为关键信号 如何改善timing.
20、给出一个门级的图,又给了各个门的传输延时,问关键路径是什么,还问给出输入,
使得输出依赖于关键路径.
21、逻辑方面数字电路的卡诺图化简,时序(同步异步差异),触发器有几种(区别,优
点),全加器等等.
29、画出NOT,NAND,NOR的符号,真值表,还有transistor level的电路.(Infineon笔
试)
34、画出CMOS电路的晶体管级电路图,实现Y=A*B+C(D+E).(仕兰微电子)
37、给出一个简单的由多个NOT,NAND,NOR组成的原理图,根据输入波形画出各点波形.
(Infineon笔试)
39、用与非门等设计全加法器.(华为)
50、LATCH和DFF的概念和区别.(未知)
57、用D触发器做个4进制的计数.(华为)
58、实现N位Johnson Counter,N=5.(南山之桥)
59、用你熟悉的设计方式设计一个可预置初值的7进制循环计数器,15进制的呢?
60、数字电路设计当然必问Verilog/VHDL,如设计计数器.
65、请用HDL描述四位的全加法器、5分频电路.
66、用VERILOG或VHDL写一段代码,实现7进制计数器.
67、用VERILOG或VHDL写一段代码,实现消除一个glitch. //glitch小故障; 小毛病; 小差错;
73、画出可以检测10010串的状态图,并verilog实现之.
74、用FSM实现101101的序列检测模块.
78、sram,falsh memory,及dram的区别?
=================================================
答案
描述8位D触发器逻辑。
module dff8(clk , reset, d, q);
input clk;
input reset;
input [7:0] d;
output [7:0] q;
reg [7:0] q;
always @ (posedge clk or posedge reset)
if(reset)
q <= 0;
else
q <= d;
endmodule
15 用verilog/vhdl写一个fifo控制器
包括空,满,半满信号。
//16*16 fifo//
//方法1
module fifo(clock,reset,read,write,fifo_in,fifo_out,fifo_empty,fifo_half,fifo_full);
input clock,reset,read,write;
input [15:0]fifo_in;
output[15:0]fifo_out;
output fifo_empty,fifo_half,fifo_full;//标志位
reg [15:0]fifo_out;
reg [15:0]ram[15:0];
reg [3:0]read_ptr,write_ptr,counter;//指针与计数
wire fifo_empty,fifo_half,fifo_full;
always@(posedge clock)
if(reset)
begin
read_ptr=0;
write_ptr=0;
counter=0;
fifo_out=0; //初始值
end
else
case({read,write})
2'b00:
counter=counter; //没有读写指令
2'b01: //写指令,数据输入fifo
begin
ram[write_ptr]=fifo_in;
counter=counter+1;
write_ptr=(write_ptr==15)?0:write_ptr+1;
end
2'b10: //读指令,数据读出fifo
begin
fifo_out=ram[read_ptr];
counter=counter-1;
read_ptr=(read_ptr==15)?0:read_ptr+1;
end
2'b11: //读写指令同时,数据可以直接输出
begin
if(counter==0)
fifo_out=fifo_in;
else
begin
ram[write_ptr]=fifo_in;
fifo_out=ram[read_ptr];
write_ptr=(write_ptr==15)?0:write_ptr+1;
read_ptr=(read_ptr==15)?0:write_ptr+1;
end
end
endcase
assign fifo_empty=(counter==0); //标志位赋值 组合电路
assign fifo_half=(counter==8);
assign fifo_full=(counter==15);
endmodule
//4*16 fifo
//方法2
module fifo_four(clk,rstp,din,readp,writep,dout,emptyp,fullp);
input clk; //时钟
input rstp; //复位
input[15:0]din; //16位输入信号
input readp; //读指令
input writep; //写指令
output[15:0]dout; //16位输出信号
output emptyp; //空指示信号
output fullp; //满指示信号
parameter DEPTH=2,MAX_COUNT=2'b11;
reg[15:0]dout;
reg emptyp;
reg fullp;
reg[(DEPTH-1):0] tail; //读指针
reg[(DEPTH-1):0] head;//写指针
reg[(DEPTH-1):0] count; //计数器
reg[15:0]fifomem[0:MAX_COUNT]; //四个16位存储单元
//read
always@(posedge clk)
if(rstp==1)
dout<=0;
else if(readp==1&&emptyp==0)
dout<=fifomem[tail];
//write
always@(posedge clk)
if(rstp==1&&writep==1&&fullp==0)
fifomem[head]<=din;
//更新head指针
always@(posedge clk)
if(rstp==1)
head<=0;
else if(writep==1&&fullp==0)
head<=head+1;
//更新tail指针
always@(posedge clk)
if(rstp==1)
tail<=0;
else if(readp==1&&emptyp==0)
tail<=tail+1;
//count
always@(posedge clk)
if(rstp==1)
count<=0;
else
case({readp,writep})
2'b00:
count<=count;
2'b01:
if(count!=MAX_COUNT)
count<=count+1;
2'b10:
if(count!=0)
count<=count-1;
2'b11:
count<=count;
endcase
//更新标志位emptyp
always@(count)
if(count==0)
emptyp<=1;
else
emptyp<=0;
//更新标志位tail
always@(count)
if(count==MAX_COUNT)
tail<=1;
else
tail<=0;
endmodule
另一种风格的同步FIFO
module FIFO_Buffer(
Data_out,
stack_full,
stack_almost_full,
stack_half_full,
stack_almost_empty,
stack_empty,
Data_in,
write_to_stack,
read_from_stack,
clk,rst
);
parameter stack_width=32;
parameter stack_height=8;
parameter stack_ptr_width=3;
parameter AE_level=2;
parameter AF_level=6;
parameter HF_level=4;
output [stack_width-1:0] Data_out;
output stack_full,stack_almost_full,stack_half_full;
output stack_almost_empty,stack_empty;
input[stack_width-1:0] Data_in;
input write_to_stack,read_from_stack;
input clk,rst;
reg[stack_ptr_width-1:0] read_ptr,write_ptr;
reg[stack_ptr_width:0] ptr_gap;
reg[stack_width-1:0] Data_out;
reg[stack_width-1:0] stack[stack_height-1:0];
assign stack_full=(ptr_gap==stack_height);
assign stack_almost_full=(ptr_gap==AF_level);
assign stack_half_full=(ptr_gap==HF_level);
assign stack_almost_empty=(ptr_gap==AE_level);
assign stack_empty=(ptr_gap==0);
always @(posedge clk or posedge rst)
if(rst)begin
Data_out<=0;
read_ptr<=0;
write_ptr<=0;
ptr_gap<=0;
end
else if(write_to_stack &&(!stack_full)&&(!read_from_stack))begin
stack[write_ptr]<=Data_in;
write_ptr<=write_ptr+1;
ptr_gap<=ptr_gap+1;
end
else if((!write_to_stack)&&(!stack_empty)&&read_from_stack)begin
Data_out<=stack[read_ptr];
read_ptr<=read_ptr+1;
ptr_gap<=ptr_gap-1;
end
else if(write_to_stack &&read_from_stack&&stack_empty)begin
stack[write_ptr]<=Data_in;
write_ptr<=write_ptr+1;
ptr_gap<=ptr_gap+1;
end
else if(write_to_stack &&read_from_stack&&stack_full)begin
Data_out<=stack[read_ptr];
read_ptr<=read_ptr+1;
ptr_gap<=ptr_gap-1;
end
else if(write_to_stack&&read_from_stack&&(!stack_full)&&(!stack_empty))
begin
Data_out<=stack[read_ptr];
stack[write_ptr]<=Data_in;
read_ptr<=read_ptr+1;
write_ptr<=write_ptr+1;
end
endmodule
22 写异步D触发器的verilog module
module dff8(clk , reset, d, q);
input clk;
input reset;
input d;
output q;
reg q;
always @ (posedge clk or posedge reset)
if(reset)
q <= 0;
else
q <= d;
endmodule
FPGA与CPLD内部结构区别?
CPLD
以altraMAX7000这种PLD为例,可分为三块结构:宏单元(Marocell),可编程连线(PIA)和I/O控制块。宏单元是PLD的基本结构,由它来实现基本的逻辑功能。可编程连线负责信号传递,连接所有的宏单元。I/O控制块负责输入输出的电气特性控制,比如可以设定集电极开路输出,摆率控制,三态输出等。
这种基于乘积项(实际就是与或阵列)的PLD基本都是由EEPROM和Flash工艺制造的,一上电就可以工作,无需其他芯片配合。布线方式是全局的,所以延时可预测。CPLD适合做逻辑设计。
FPGA
FPGA基于LUT,LUT本质上就是一个RAM,每一个LUT可以看成一个有4位地址线的16x1的RAM。这也是为什么FPGA需要外接一个rom来上电配置。
以xilinx的Spartan-II为例,主要包括CLBs,I/O块,RAM块和可编程连线。在spartan-II中,一个CLB包括2个Slices,每个slices包括两个LUT,两个触发器和相关逻辑。 Slices可以看成是SpartanII实现逻辑的最基本结构。
FPGA的制造工艺确定了FPGA芯片中包含的LUT和触发器的数量非常多,往往都是几千上万,PLD一般只能做到512个逻辑单元,而且如果用芯片价格除以逻辑单元数量,FPGA的平均逻辑单元成本大大低于PLD。 所以如果设计中使用到大量触发器,例如设计一个复杂的时序逻辑,那么使用FPGA就是一个很好选择。
2.Latch和Register区别?行为描述中Latch如何产生?
本质的区别在于:latch是电平触发,reg是边沿触发。时序设计中尽量使用reg触发。
行为描述中,如果对应所有可能输入条件,有的输入没有对应明确的输出,系统会综合出latch。
比如:always@( a or b) //缺少else语句
begin
if(a==1)
q <= b;
end
4.用Verilog设计一个5分频器。
5分频,奇数分频都可以类似这么做,只需要改div1和div2的参数。div1为奇数分频除2的余数。采用上升延和下降延分别触发不同波形,最后叠加的方式产生奇数分频。
module divfreq(clk, clk1x, rst, clk1xpose, clk1xnege, coutpose, coutnege);
input clk;
input rst;
output clk1x;
output clk1xpose;
output clk1xnege;
output[2:0] coutpose;
output[2:0] coutnege;
reg clk1xpose;
reg clk1xnege;
reg[2:0] coutpose;
reg[2:0] coutnege;
parameter div1 = 2 , div2 = 4; // div1 = 5 / 2, div2 = 5 - 1
assign clk1x = clk1xpose | clk1xnege;
always@(posedge clk or negedge rst)
begin
if(!rst)
clk1xpose = 0;
else if(coutpose == div1)
clk1xpose = ~clk1xpose;
else if(coutpose == div2)
clk1xpose = ~clk1xpose;
else
clk1xpose = clk1xpose;
end
always@(negedge clk or negedge rst)
begin
if(!rst)
clk1xnege = 0;
else if(coutnege == div1)
clk1xnege = ~clk1xnege;
else if(coutnege == div2)
clk1xnege = ~clk1xnege;
else
clk1xnege = clk1xnege;
end
always@(posedge clk or negedge rst)
begin
if(!rst)
coutpose = 0;
else if(coutpose == div2)
coutpose = 0;
else
coutpose = coutpose + 1;
end
always@(negedge clk or negedge rst)
begin
if(!rst)
coutnege = 0;
else if(coutnege == div2)
coutnege = 0;
else
coutnege = coutnege + 1;
end
endmodule
用D触发器实现2倍分频的逻辑电路?
Verilog描述:
module divide2( clk , clk_o, reset);
input clk , reset;
output clk_o;
wire in;
reg out ;
always @ ( posedge clk or posedge reset)
if ( reset)
out <= 0;
else
out <= in;
assign in = ~out;
assign clk_o = out;
endmodule