简述FPGA开发流程
系统规划,RTL设计,功能仿真,综合,综合后仿真,实现,布局布线,时序仿真,板级验证与仿真
简述ASIC设计流程,并列举各部分用到的工具
名词解释
ROM: Read Only Memory,只读存储器,掉电后数据不会丢失,但现在的所说的ROM不只是Read Only了,也是可以写入的。
RAM: Random Access Memory,随机访问存储器,其内部存储单元的内容可按需随意的取出或存入,且存、取的速度与存储单元在存储芯片中的位置无关。不过这种存储器在断电时会丢失其存储内容,故主要用于存储短时间使用的程序。
SRAM: Static Random-Access Memory,静态随机访问存储器,只要供电数据就会保持,但断电数据就会消失。
DRAM: Dynamic Random Access Memory,动态随机访问存储器,主要原理是利用电容存储电荷的多少来代表一个bit是0还是1,由于晶体管的漏电电流现象,电容会放电,所以要周期性的给电容充电,叫刷新。
SDRAM: Synchronous Dynamic Random Access Memory,同步动态随机访问存储器,同步写入和读出数据的DRAM。同步是指存储器在工作的时候需要同步时钟信号,无论存储芯片内部命令的发送还是数据的传输,都必须以时钟信号为基准;而动态是指存储阵列需要不断刷新来保证数据不丢失。
EPROM: Erasable Programmable ROM,可擦除可编程只读存储器。它解决了PROM只能编程一次的问题,不过其存储内容的擦除必须借助紫外线的长时间照射才能完成。
EEPROM: Electrically Erasable Programmable ROM,电可擦除可编程只读存储器,它克服了EPROM在擦除时较为麻烦的问题,可以直接通过计算机程序对其进行重复的擦写。
DDR: Double Data Synchronous Dynamic Random Access Memory,双倍速率同步动态随机存储器,双倍速率传输的SDRAM,在时钟的上升沿和下降沿都可以进行数据传输。我们电脑的内存条都是DDR芯片。
FLASH: Flash Memory,闪存,非易失性固态存储,EEPROM的擦除和重写都是针对整个芯片而言的,但Flash的数据删除和重写则是以块(块的容量一般在256KB~20MB之间)为单位的,因此Flash的更新速度要远比EEPROM快。
什么是竞争和冒险,如何消除
竞争:如果在某一个时刻,从组合逻辑的某一个输入端到其输出端存在两条以上的电信号通路时,信号由于经由不同路径传输达到某一汇合点的时间有先有后的现象,就称该组合逻辑在当前状态下针对这个输入端存在竞争。
举例:
两个输入存在先后问题,导致有一小段零脉冲出现在输出中,这是非预期的。
在FPGA中消除的方法:
修改逻辑表达式,增加冗余项
eg:
逻辑表达式如下:
Z = (~A)&B&C + A&B当B = C = 1时, 电路存在“0”型竞争。
增加项:冗余项 B&C
更变后:
Z = (~A)&B&C + A&B + B & C采样时序采样,仅在时钟边沿采样【推荐,事实上也最常用】
在输出数据稳定时,再将数据采集,时序采样法几乎是万能的,因为对于任何一个组合逻辑来说,其输入与输出之间总存在一个最大延迟的路径。设这个最大的路径延迟为T,在0到T时刻之间,该组合逻辑的输出可能会出现一系列不稳定现象。因此,我们只需要适当选择周期大于T的信号作为时钟就可以绕过0到T这段有问题的时刻,而采样到T时刻以后的稳定且正确的输出。
在芯片外部并联电容滤波消除窄脉冲【物理方法】
二分频实现
用D触发器实现带同步高置数和异步高复位端的二分频的电路,画出逻辑电路,Verilog描述
1 | module freq_div2 ( |
2 | input clk, |
3 | input rst, |
4 | input set, |
5 | output reg q |
6 | ); |
7 | always@(posedge clk) begin |
8 | if(rst == 1'b1) begin |
9 | q <= 1'b0; |
10 | end |
11 | else if(set == 1'b1) begin |
12 | q <= 1'b1; |
13 | end |
14 | else |
15 | q <= ~q; |
16 | end |
17 | endmodule |
逻辑电路:
建立时间和保持时间
setup timing check
第二个触发器D的数据必须在setup time之前就稳定。
用公式来表示:
数据在传输过程中的延迟必须小于建立时间卡的时间节点。
hold timing check
hold time 和 setup time有区别:
setup 是一个周期之后check,hold check 的capture clk 和launch clk是同一个沿
hold time check 和时钟周期无关
- setup用max,而hold用min
用公式来表示:
1. 简述并画图表示
建立时间Tsu(setup):在时钟上升沿之前,输入数据建立稳定的时间。
保持时间Th(hold):在时钟上升沿之后,输入数据的保持不变的时间。
2.例
T_launch + T_ck2q + T_dp < T_cycle + T_skew - T_setup
T_skew = 0, T_ck2q = 6ns, T_dp = 2ns, T_setup = 2ns
T_cycle > 10ns
f_max = 100MHz
3.下图的电路中,flip-flop2 的setup time margin = () ns
setup time margin就是slack,建立时间裕量
T_launch + T_ck2q + T_dp = 0.2ns + 0.65ns + 0.35ns = 1.2ns
T_cycle + T_skew - T_setup = 10ns + 0.6ns - 0.45ns = 10.15ns
slack = 10.15ns - 1.2ns = 0.95ns
4. 下图中的电路,器件延迟如图中标注,将框内的电路作为一个寄存器,其有效setup time = ? ns,hold time = ? ns
有效setup time分析:
对于D触发器而言,T_setup = 2ns,也就是说数据信号需要提前时钟信号2ns到达触发器D端。
考虑时钟路径延迟,时钟CLK要早于触发器的时钟1ns到达,因此对于D触发器建立时间的满足是有害的, T_setup_valid = T_setup - 1ns = 1ns
在考虑数路径延迟: T_setup_valid = T_setup - 1ns + 2ns = 3ns ;
有效hold time分析:
对于D触发器而言,T_hold = 2ns,也就是说数据信号需要在时钟信号到达后保持2ns
考虑时钟路径延迟, T_hold_valid = T_hold + 1ns = 3ns ;
在考虑数路径延迟: T_hold_valid = T_hold + 1ns - 2ns = 1ns ;
简述触发器和锁存器之间的差别?
锁存器对电平信号敏感,在输入脉冲的电平作用下改变状态。
D触发器对时钟边沿敏感,检测到上升沿或下降沿触发瞬间改变状态。
什么是Clock Jitter和Clock Skew,这两者有什么区别?
时钟抖动(Clock Jitter): 时钟抖动是时钟沿与理想位置的偏差”。
时钟抖动通常由时钟发生器电路,噪声,电源变化,附近电路的干扰等引起。抖动是为时序收敛指定的设计余量的一个影响因素。
如图:
蓝色的时钟表示理想情况下的时钟,红色的线表示抖动时钟边沿可以出现的问题。
时钟抖动可以带来很多问题,例如:data setup time violation, data hold time violation
时钟偏移(Clock Skew): 是由于布线长度及负载不同引起的,导致同一个时钟信号到达相邻两个时序单元的时间不一致。
什么是亚稳态,产生的原因,如何消除?
如果触发器的输入电压采样时间过短,即时序不够,则触发器需要花很长时间来实现输出逻辑达到标准电平,也就是说,电路处于中间态的时间变长,使得电路“反应”迟钝,这就是“亚稳态”。一个触发器一旦进入亚稳态状态,则无法预测触发器的输出电平,也无法预测什么时候可以稳定在某个确定的电平上。
在同步系统中,输入总是与时钟同步,因此寄存器的setup time和hold time是满足的,一般情况下是不会发生亚稳态情况的。(首先在同步逻辑中只要STA分析过了正常是不会遇到亚稳态问题的。由于在同步逻辑中STA分析以及保证了每个触发器都能满足自己的建立时间以及保持时间。)
亚稳态一般是发生在跨时钟传输和异步信号采集中。
消除:两级或多级寄存器同步。理论上亚稳态不能完全消除,只能降低,一般采用两级触发器同步就可以大大降低亚稳态发生的概率,再加多级触发器改善不大。
但注意双触发器作为同步器只能用在单比特数据的传递中,因为同步器输出只能保证是一个稳态。对于多比特数据的操作一般使用异步FIFO。
同步与异步?
1. 同步复位和异步复位的区别?
同步复位是时钟边沿触发时判断是否有效,和时钟有关。异步复位是复位信号有效和时钟无关。
异步复位:
同步复位:
2. 同步电路和异步电路区别
同步电路有统一的时钟源,经过PLL分频后的时钟驱动的模块,因为是一个统一的时钟源驱动,所以还是同步电路。异步电路没有统一的时钟源。
什么是高阻态?
高阻态:
电路的一种输出状态,既不是高电平也不是低电平,如果高阻态再输入下一级电路的话,对下级电路无任何影响,可以理解为断路,不被任何东西所驱动,也不驱动任何东西。
集成时钟门控单元(Integrated Clock Gating Cell)
时钟门控是一种通过时钟使能信号关闭模块时钟来降低时钟功耗的常用技术。时钟门控功能仅需要一个AND或OR门。 考虑你正在使用带时钟的AND门。 高EN边沿可能随时出现,可能与时钟边沿不一致。 在这种情况下,AND门的输出将比时钟占空比的时间短1。 您最终会在时钟信号中出现毛刺。
为避免这种情况,使用了一种特殊的时钟门控单元,它使EN与时钟边沿同步。 这些叫集成时钟门控单元或ICG。
通常有两种类型的实现方式:
与门实现方式:
或门实现方式:
名词解释:超标量,MESI,TLB,缓存一致性,PA与VA之间的转化
超标量:execute more than one instruction per cycle, 在一个时钟周期可以同时分派(dispatching)多条指令在不同的执行单元中被执行,这就实现了指令级的并行。
MESI: MESI协议是一个基于失效的缓存一致性协议,是支持回写(write-back)缓存的最常用协议,与写通过(write through)缓存相比,回写缓冲能节约大量带宽。总是有“脏”(dirty)状态表示缓存中的数据与主存中不同。MESI协议要求在缓存不命中(miss)且数据块在另一个缓存时,允许缓存到缓存的数据复制。与MSI协议相比,MESI协议减少了主存的事务数量。
TLB: 页表缓存,为CPU的一种缓存,由内存管理单元用于改进虚拟地址到物理地址的转译速度。
缓存一致性(Cache coherence),是指保留在缓冲存储器中的共享资源,保持资料一致性的机制。
在一个系统中,当许多不同的设备共享一个共同存储器资源,在缓冲存储器中的资料不一致,就会产生问题。
PA与VA之间的转化:没启动MMU时,CPU核、cache、MMU、外设等所有部件使用的都是物理地址。启动MMU后,CPU核对外发出虚拟地址VA;VA被转换为MVA供cache、MMU使用,在这里MVA被转换为PA;最后使用PA读写实际设备。MMU的作用就是负责虚拟地址(virtual address)转化成物理地址(physical address)
用过哪些EDA工具,各负责什么功能
功能仿真:Synopsys VCS, Mentor ModelSim, Cadence Verilog-XL
逻辑综合:Synopsys Design Complier,Cadence Genus
静态时序工具:Synopsys Prime Time
物理设计:Cadence Innovus
版图设计:Cadence Virtuoso
单比特脉冲跨时钟域同步设计
电平(level signal)同步器
在电平同步器中,跨时钟域的信号在新时钟域中要保持高电平或低电平两个时钟周期以上。同步之后的信号是电平的形式,而该电平所维持的时钟周期个数是其在跨时钟域期间被上升沿检测到的次数。
1 | module synzer_ls( |
2 | data_out, |
3 | clk1, |
4 | clk2, |
5 | data_in |
6 | ); //level signal synchronizer |
7 | |
8 | output data_out; // signal that after synchronized |
9 | input clk1; // old clk signal |
10 | input clk2; // new clk signal |
11 | input data_in; // signal that before synchronized |
12 | |
13 | reg a; // DFF in the old clk domain |
14 | reg b; // the first DFF in the new clk domain |
15 | reg c; // the second DFF in the new clk domain |
16 | |
17 | always @(posedge clk1) //a |
18 | a<=data_in; |
19 | |
20 | always @(posedge clk2) //b |
21 | b<=a; |
22 | |
23 | always @(posedge clk2) //c |
24 | c<=b; |
25 | |
26 | assign data_out=c; |
27 | |
28 | endmodule |
边沿检测(edge detecting)同步器
边沿检测同步器在电平同步器的输出端增加了一个触发器。新增触发器的输出经反相后和电平同步器的输出进行与操作,这一电路会检测同步器输入的上升沿,产生一个与时钟周期等宽、高电平有效的脉冲。
如果将与门的两个输入端交换使用,就可以构成一个检测输入信号下降沿的同步器。将与门改为非门可以构建一个产生低电平有效脉冲的电路。
当一个脉冲进入更快的时钟域中时,边沿检测同步器可以工作的很好。这一电路会产生一个脉冲,用来指示输入信号上升或下降沿。
这种同步器有一个限制,即输入脉冲的宽度必须大于同步时钟周期与第一个同步触发器所需保持时间之和。最保险的脉冲宽度是同步器时钟周期的两倍。
如果输入是一个单时钟宽度脉冲进入一个较慢的时钟域,则这种同步器没有作用,在这种情况下就要采用脉冲同步器。
1 | module synzer_ed( |
2 | data_out, |
3 | clk1, |
4 | clk2, |
5 | data_in |
6 | ); // edge detecting synchronizer |
7 | |
8 | output data_out; // signal that after synchronized |
9 | input clk1; // old clk signal |
10 | input clk2; // new clk signal |
11 | input data_in; // signal that before synchronized |
12 | |
13 | reg a; // DFF in the old clk domain |
14 | reg b; // the first DFF in the new clk domain |
15 | reg c; // the second DFF in the new clk domain |
16 | reg d; // the third DFF in the new clk domain |
17 | |
18 | always @(posedge clk1) //a |
19 | a<=data_in; |
20 | |
21 | always @(posedge clk2) //b |
22 | b<=a; |
23 | |
24 | always @(posedge clk2) //c |
25 | c<=b; |
26 | |
27 | always @(posedge clk2) //d |
28 | d<=c; |
29 | |
30 | assign data_out=c&&(~d); //上升沿 |
31 | |
32 | endmodule |
脉冲(Pulse)同步器
脉冲同步器的输入信号是一个单时钟宽度脉冲,它触发原时钟域中的一个翻转电路。每当翻转电路接收到一个脉冲时,它就会在高低电平间进行转换,然后通过电平同步器到达异或门的一个输入端,而另一个信号经过一个时钟周期的延迟进入异或门的另一端,翻转电路每转换一次状态,这个同步器的输出端就产生一个单时钟宽度的脉冲。
脉冲同步器的基本功能是从某个时钟域取出一个单时钟宽度脉冲,然后在新时钟域中建立另一个单时钟宽度的脉冲。
脉冲同步器也有一个限制,即输入脉冲之间的最小间隔必须等于两个同步器时钟周期。如果输入脉冲相互过近,则新时钟域中的输出脉冲也紧密相邻,结果是输出脉冲宽度比一个时钟周期宽。
当输入脉冲时钟周期大于两个同步器时钟周期时,这个问题更加严重。这种情况下,如果输入脉冲相邻太近,则同步器就不能检测到每个脉冲。
1 | module synzer_pl( |
2 | data_out, |
3 | clk1, |
4 | clk2, |
5 | data_in, |
6 | rst_n |
7 | ); // pulse synchronizer |
8 | |
9 | output data_out; // signal that after synchronized |
10 | input clk1; // old clk signal |
11 | input clk2; // new clk signal |
12 | input data_in; // signal that before synchronized |
13 | input rst_n; // signal indicating reset |
14 | |
15 | reg a; // DFF in the old clk domain |
16 | reg b; // the first DFF in the new clk domain |
17 | reg c; // the second DFF in the new clk domain |
18 | reg d; // the third DFF in the new clk domain |
19 | |
20 | wire q; |
21 | wire q1; |
22 | wire di; |
23 | |
24 | assign di=data_in?q1:q; |
25 | assign q=a; |
26 | assign q1=~a; |
27 | assign data_out=(c==d)?0:1; |
28 | |
29 | always @(posedge clk1) //a |
30 | begin |
31 | if(!rst_n) |
32 | a<=1'b0; |
33 | else |
34 | a<=di; |
35 | end |
36 | |
37 | always @(posedge clk2) //b |
38 | b<=a; |
39 | |
40 | always @(posedge clk2) //c |
41 | c<=b; |
42 | |
43 | always @(posedge clk2) //d |
44 | d<=c; |
45 | |
46 | endmodule |
序列产生与序列检测
(1)了解状态机:什么是摩尔型状态机,什么是米利型状态机,两者的区别是什么?一段式、二段式、三段式状态机的区别?
(2)使用状态机检测“1101”,串行输入的测试序列为“11101101011010”,输出信号为valid有效信号,检测到时输出高,否则为低,考虑序列叠加情况,比如“1101101”,则有两个“1101”
(1)状态机
状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。有限状态机简写为FSM(Finite State Machine),主要分为2大类:
第一类,若输出只和状态有关而与输入无关,则称为Moore状态机;
第二类,输出不仅和状态有关而且和输入有关系,则称为Mealy状态机。
Mealy型:输出信号不仅取决于当前状态,还取决于输入;
Moore型:输出信号只取决于当前状态;
实现相同的功能时,Mealy型比Moore型能节省一个状态(大部分情况下能够节省一个触发器资源,其余情况下使用的资源相同,视状态数和状态编码方式决定),Mealy型比Moore型输出超前一个时钟周期。
(2)状态机写法
一段式:一个always块,既描述状态转移,又描述状态的输入输出,当前状态用寄存器输出。一段式写法简单,但是不利于维护,状态扩展麻烦,状态复杂时易出错,不推荐;
二段式:两个always块,时序逻辑与组合逻辑分开,一个always块采用同步时序描述状态转移;另一个always块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出,当前状态用组合逻辑输出,可能出现竞争冒险,产生毛刺,而且不利于约束,不利于综合器和布局布线器实现高性能的设计;
三段式:三个always块,一个always模块采用同步时序描述状态转移;一个always采用组合逻辑判断状态转移条件,描述状态转移规律;第三个always块使用同步时序描述状态输出,寄存器输出。
三段式与二段式相比,关键在于根据状态转移规律,在上一状态根据输入条件判断出当前状态的输出,从而在不插入额外时钟节拍的前提下,实现了寄存器输出。
(3)状态机序列检测
使用三段式FSM有限状态机进行序列检测,使用摩尔型状态机,最终输出与输入无关。
根据待检测的序列“1101”确定状态,其中S1为检测到第1个有效位“1”,S2为检测到2个有效位“11”,S3为检测到3个有效位“110”,S4位检测到4个有效位“1101”,IDLE为其他状态;
IDLE:初始状态,除S1~S4外的其他所有状态
S1:1, 来1则到S2(11),否则回到IDLE;
S2:11, 来0则到S3(110),否则保持S2(11);
S3:110, 来1则到S4(1101),否则回到IDLE;
S4:1101, 来1则到S2(11),否则回到IDLE;
摩尔型,输出和输入无关,S4时无论输入什么,都输出1
1 | module FSM_SequDetection_1( |
2 | input clk, |
3 | input rst_n, |
4 | input data_in, |
5 | output reg data_valid |
6 | ); |
7 | //定义状态,这里采用的独热码(One-Hot),FPGA中推荐用独热码和格雷码(Gray) |
8 | //状态较少时(4-24个状态)用独热码效果好,状态多时格雷码(状态数大于24)效果好 |
9 | parameter IDLE = 5'b00001; |
10 | parameter S1 = 5'b00010; |
11 | parameter S2 = 5'b00100; |
12 | parameter S3 = 5'b01000; |
13 | parameter S4 = 5'b10000; |
14 | |
15 | reg [4:0] current_state; //现态 |
16 | reg [4:0] next_state; //次态 |
17 | |
18 | //三段式FSM,第一段,同步时序逻辑,描述状态切换,这里的写法固定 |
19 | always @ ( posedge clk ) |
20 | begin |
21 | if( !rst_n ) begin |
22 | current_state <= IDLE; |
23 | end |
24 | else begin |
25 | current_state <= next_state; |
26 | end |
27 | end |
28 | |
29 | //三段式FSM,第二段,组合逻辑,判断状态转移条件,描述状态转移规律 |
30 | //这里面用"="赋值和用"<="没区别 |
31 | always @ (*) |
32 | begin |
33 | if( !rst_n ) begin |
34 | next_state <= IDLE; |
35 | end |
36 | else begin |
37 | case( current_state ) |
38 | IDLE: begin |
39 | if( data_in == 1 ) |
40 | next_state <= S1; |
41 | else |
42 | next_state <= IDLE; |
43 | end |
44 | S1 : begin |
45 | if( data_in == 1 ) |
46 | next_state <= S2; |
47 | else |
48 | next_state <= IDLE; |
49 | end |
50 | S2 : begin |
51 | if( data_in == 0 ) |
52 | next_state <= S3; |
53 | else |
54 | next_state <= S2; |
55 | end |
56 | S3 : begin |
57 | if( data_in == 1 ) |
58 | next_state <= S4; |
59 | else |
60 | next_state <= IDLE; |
61 | end |
62 | S4 : begin |
63 | if( data_in == 1 ) |
64 | next_state <= S2; |
65 | else |
66 | next_state <= IDLE; |
67 | end |
68 | default : begin |
69 | next_state <= IDLE; |
70 | end |
71 | endcase |
72 | end |
73 | end |
74 | |
75 | //三段式FSM,第三段,同步时序逻辑,描述状态输出,摩尔型输出 |
76 | always @ ( posedge clk ) |
77 | begin |
78 | if( !rst_n ) begin |
79 | data_valid <= 1'b0; |
80 | end |
81 | else begin |
82 | case( next_state ) |
83 | S4 : data_valid <= 1'b1; |
84 | default : data_valid <= 1'b0; |
85 | endcase |
86 | end |
87 | end |
88 | endmodule |