IC设计基础
一 前言
这一周连续两场线下面试,紧接着又是微信视频面试,从连续三天的面试中,收获颇丰!
存在的问题:
一是对项目细节模糊;
二是IC基础知识薄弱;
具体表现是,在面试过程中,如被问到DDR3和千兆以太网的知识,讲不清楚,如DDR3的IP的输入数据位宽和时钟之类,DDR3的架构,标注项目系统框图的时钟和数据流等 ,用Verilog实现1.2*2.8的代码,小数1.2用八位无符号二进制位表示,不能准确写出来,还有问CRC32的原理也懵了;这些都是对项目细节理解不够;对于IC基础知识薄弱,就反映在做数字IC的笔试中,发现很多基础,如亚稳态,跨时钟域处理的方法,奇偶分频,建立时间和保持时间;都没有熟练写出Verilog代码来,能够准确说出他们的定义,解决方法等
二 笔试题(广州一家IC设计公司)
1. 比较同步复位与异步复位的区别,异步复位的同步释放改怎么处理?
复位最基本的目的就是使电路(主要是触发器)进入一个能稳定操作的确定状态(主要是触发器在在某个确定的状态),主要表现为下面两点:
①使电路在复位后从确定的初始状态运行:
·上电的时候,为了避免上电后进入随机状态而使电路紊乱,这个时候你就需要上电复位了。
·有时候,电路在某个状态下,你想或者别人要求你从电路的初始状态开始进行延时你的电路功能,这个时候你就要对你的电路进行复位,让它从最初的状态开始运行。
②使电路从错误状态回到可以控制的确定状态:
(1)同步复位
同步复位是指复位信号在时钟有效沿到来时才复位电路。因此同步复位的复位信号受到时钟信号的控制。Verilog代码和电路如下
always @(posedge clk)
优点:
1).有利于仿真器的仿真;
2).有利于静态时序分析工具的分析;
3).由于只在时钟有效电平到来时才有效,所以可以滤除高于时钟频率的复位毛刺。
缺点:
1).由于大多数的逻辑器件的目标库内的 DFF 都只有异步复位端口,倘若采用同步复位的话,综合器就会在寄存器的数据输入端口插入组合逻辑,这样就会一方面额外增加 FPGA 内部的逻辑资源,另一方面也增加了相应的组合逻辑门时延。
2).复位信号的有效时长必须大于时钟周期,才能真正被系统识别并完成复位任务。同时还要考虑诸如时钟偏移、组合逻辑路径延时、复位延时等因素(所以复位信号有时需要脉冲展宽,用以保证时钟有效期间有足够的复位宽度)
3).同步复位依赖于时钟,如果电路中的时钟信号出现问题,无法完成复位。
(2)异步复位
异步复位触发器则是在设计触发器的时候加入了一个复位引脚,也就是说复位逻辑集成在触发器里面。(一般情况下)低电平的复位信号到达触发器的复位端时,触发器进入复位状态,直到复位信号撤离。Verilog代码和电路如下always @(posedge clk or negedge rst_n)
优点:
1). ASIC库或FPGA器件的DFF都提供异步复位端口,无需多加的逻辑资源产生;
2).设计相对简单
3).复位信号不依赖于时钟,产生和响应都很方便。
缺点:
1) .属于异步逻辑,复位释放接近时钟有效沿时容易使得触发器的输出进入亚稳态;
2) 可能因为噪声或者毛刺造成虚假复位信号;
3) 静态时序分析困难,静态时序分析一般是针对同步设计,基于时钟周期分析时序;
4) 对于 DFT设计,如果复位信号不是直接来自于 I/O 引脚,在 DFT 扫描和测试时,复位信号必须被禁止,因此需要额外的同步电路。
(3)异步复位的同步释放
异步复位的同步释放电路也称为复位同步器,这个方法是将外部输入的异步复位信号进行处理,产生另外一个适合用于后面电路的复位信号,这个处理后的复位信号能够异步复位电路中的触发器,又不会存在撤离问题.异步复位同步释放就是在复位信号到来的时候不受时钟信号的同步,而是在复位信号释放的时候受到时钟信号的同步。
1 module system_ctrl 2 //==================<端口>================================================== 3 ( 4 //globel clock ---------------------------------- 5 input wire clk , //时钟,50Mhz 6 input wire rst_n , //复位,低电平有效 7 //user interface -------------------------------- 8 input wire a , //输入信号 9 output reg b //输出信号 10 ); 11 12 //========================================================================== 13 //== 异步复位的同步化设计 14 //========================================================================== 15 reg sys_rst_n_r; 16 reg sys_rst_n; 17 18 always @(posedge clk or negedge rst_n) begin 19 if(!rst_n) begin 20 sys_rst_n_r <= 0; 21 sys_rst_n <= 0; 22 end 23 else begin 24 sys_rst_n_r <= 1; 25 sys_rst_n <= sys_rst_n_r; 26 end 27 end 28 29 always @(posedge clk or negedge sys_rst_n) begin 30 if(!sys_rst_n) 31 b <= 0; 32 else 33 b <= a; 34 end 35 36 37 38 endmodule
电路结构图如下:
理解:将外部信号进行同步处理(sys_rst_n),作为后面电路的复位信号(带复位端的触发器b~reg0)
2. 什么是时钟偏移(Clockskew),负时钟偏移,正时钟偏移?
jitter:由于晶振本身稳定性,电源以及温度变化等原因造成了时钟频率的变化,就是jitter,指的是时钟周期的变化。指两个时钟周期之间存在的差值,这个误差是在时钟发生器内部产生的,和晶振或者PLL内部电路有关,布线对其没有影响。由于跟晶振本身的工艺有关,所以在设计中无法避免它能带来的影响,通产只能在设计中留有一定的margin。
Clockskew指同样的时钟产生的多个子时钟信号之间的延时差异。skew通常是时钟相位上的不确定。由于时钟源到达不同寄存器所经历路径的驱动和负载的不同,时钟边沿的位置有所差异,因此就带来了skew。完成布局布线后,物理路径延时是固定的,所以在设计中考虑到时钟偏移,就可以避免偏移带来的影响。
时钟偏斜是一个时钟信号沿着同一个时钟网络到达源寄存器与目的寄存器的时间差。负时钟偏斜,即当目标寄存器时钟早于源寄存器时钟到达时,时钟偏斜称为负时钟偏斜。
当源寄存器时钟早于目的寄存器时钟到达时,时钟偏斜称为正时钟偏斜。
参考资料:李锐博恩,《高性能FPGA系统——时序设计与分析》
3. 什么是亚稳态,如何防止?
触发器无法在某一个规定时间段内产生一个确定的状态(即既不是高电平1也不是低电平0)。
原因:由于触发器的建立时间和保持时间不满足,当触发器进入亚稳态,使得无法预测该单元的输出,也无法预测何时输出才能稳定到某个正确的电平上。在这个稳定期间,触发器输出一些中间级电平,或者可能处于振荡状态,这种不稳定是会沿着信号通道的各个触发器级联传播。
消除:两级或多级寄存器同步。理论上亚稳态不能完全消除,只能降低,一般采用两级触发器同步就可以大大降低亚稳态发生的概率,再加多级触发器改善不大。
如何消除亚稳态?
(1降低系统时钟;
(2)用反应更快的D触发器,锁存器;
(3)引入同步机制;
(4)改善时钟质量,用边沿变化快速的时钟信号消除;
4. 什么是setup时间和hold时间,描述区别并简单画出示意图?
建立时间:指在触发器的时钟信号上升沿到来以前,数据稳定不变的时间。如果建立的时间不满足要求那么数据将不能在这个时钟上升沿被稳定的打入触发器
保持时间:是指在触发器的时钟信号上升沿到来以后,数据稳定不变的时间。如果保持时间不满足要求那么数据同样也不能被稳定的打入触发器。
(setup time不受系统时钟频率影响)
因为触发器内部数据的形成是需要一定的时间的,如果不满足建立和保持时间,D触发器将进入亚稳态。
5、时序约束的基本概念和基本策略?
时序约束主要包括周期约束,偏移约束,静态时序约束。
通过附加时序约束可以综合布线工具调整映射和布局布线,使设计达到时序要求。
附加时序约束的一般策略是先附加全局约束,然后对快速和慢速例外路径附加专门约束,首先定义设计的所有时钟,对各时钟域内的同步元件进行分组,对分组附加时序偏移约束,对全组合逻辑的 PAD to PAD 路径附加约束。附加专门约束时,首先约束分组之间的路径,然后约束快慢速例外路径和周期路径,以及其他特殊路径。
6.描述跨时钟域设计会出现的问题及解决办法,多比特信号,单比特信号?
(一)问题
1 亚稳态问题
2数据丢失
这个现象经常出现在由快时钟域到慢时钟域时,由于信号保持时间过短,作为采集方的慢时钟域有可能采集不到该信号,造成数据丢失。
3.数据聚和错误
意思就是信号通过不同路径传输后重新聚合到一起使用。
参考资料:https://www.jianshu.com/p/05b434313997
(二)解决方法
单bit: (1)双D触发器打拍同步; (2)脉冲展宽处理(https://www.cnblogs.com/rouwawa/p/7501319.html)
多bit: (1)格雷码+双D触发器打拍; (2)DMUX数据使能选通设计;
(3)异步握手协议 (4)异步FIFO或RAM
(三)对各种方法解释
(1)格雷码+双D触发器
多bit信号转换为格雷码,再用双D触发器打拍。为什么不直接打两拍,而先转换格雷码:不同信号路径延时不同,信号打两拍之后可能出现不同状态。例如00->11,直接打拍可能变成00->10->11。而格雷码相邻状态只有1bit变换,即使路径延时不同,状态也不会出错。例如00->11格雷码是00->10,打拍可能变成00->00->10,只会出现某个状态多延时一拍而已,不会出错。注意:格雷码作同步时必须是2^N个状态。
其他的方法,如异步握手协议,有很多资料和博客解释,如微信公众号达尔闻说的求职系列75,咸鱼FPGA博客;
7.描述ASIC设计流程及工具
1.规格制定
芯片规格也像功能列表一样,是客户向芯片公司提出的设计要求,包括芯片需要达到的具体功能和性能方面的要求。
2.详细设计
根据客户提出的规格要求,拿出设计解决方案和具体时间架构,划分模块功能。
3.HDL编码
使用硬件描述语言(VHDL,Verilog HDL)。
4.仿真验证
工具:Mentor公司的Modelsim,Synopsys的VCS,还有Cadence的NC-Verilog均可以对RTL级代码进行验证。
5.逻辑综合
逻辑综合就是把设计实现的HDL代码翻译成门级网表netlist。综合需要设定约束条件,就是你希望综合出来的电路在面积、时序等目标参数上达到的标准。逻辑综合需要基于特定的综合库,不同的库中,门电路基本标准单元的面积,时序参数是不一样的。
6.STA(静态时序分析)state timing analysis
从时序上对电路进行验证,检查电路是否存在建立时间(setup time)和保持时间(hold time)的违例。
工具:Synopsys的prime time。
7.形式验证
从功能上对综合后的网表进行验证。常用的等价性检查方法,以功能验证后的HDL设计为参考,对比综合后的网表功能,他们是否在功能上存在等价性。
工具:Synopsys的Formality。
8. 异步FIFO设计
异步FIFO是一种FIFO设计,数据从一个时钟域进入到FIFO,在另一个时钟域读取数据,并且两个时钟域是异步。
异步FIFO的用于将数据从一个时钟域安全准确地传递到另一个时钟域。
1)传递多个异步信号
将多个信号从一个时钟域同步到另一个时钟域,并确保所有的信号都同步到新时钟域中的同一时钟周期这是一个关键问题。 FIFO在设计中用于将多位数据从一个时钟域安全地传递到另一个时钟域。 通过一个时钟域中的控制信号将数据存入FIFO缓存中,并通过来自第二时钟域的控制信号将数据从同一FIFO缓存的另一个端口中读取并删除。
IFO设计的难点在于生成FIFO指针以及FIFO上的满和空状态确定。
满(写满标志判断),空(读空标志判断)
1.1) 同步FIFO指针
对于同步FIFO设计(在同一时钟域中执行FIFO读写操作),一种实现方式是对FIFO的写入和读取次数进行计数,递增
(以FIFO写入但不读取) ),递减(在FIFO读取但无写入时)或保持(无写入和读或同时进行写入和读取操作)FIFO计数
值。 当FIFO计数器达到预定的最大值时,FIFO为满,而当FIFO计数器为零时,FIFO为空。
1.2) 异步FIFO指针
写指针总是指向下一个要写的字;因此,在复位时,两个指针都设置为零,这也恰好是下一个要写入的FIFO字位置。在FIFO写入操作中,将数据写入指针所指向的位置,然后将写指针递增以指向要写入的下一个位置。同样,读取指针始终指向要读取的当前FIFO字。再次复位时,两个指针均复位为零,FIFO为空,而读指针指向无效数据(因为FIFO为空且声明了空标志)。一旦第一个数据被写入FIFO,写入指针就会递增,清空标志,并且在寻址第一个FIFO存储字内容的读指针会立即将第一个有效数据驱动到FIFO数据输出端口,由接收端读取。读指针始终指向要读取的下一个FIFO字意味着,接收端不必使用两个时钟周期来读取数据。如果接收端在读取FIFO数据之前必须先递增读指针,则接收端必须先用一个周期等FIFO输出数据字,再用一个周期将数据字捕获到接收端,这回浪费一倍的时间。
当读写指针相等时,FIFO为空。当两个指针在复位操作期间都复位为零时,或者在从FIFO读取了最后一个字的情况下,读指针赶上了写指针,就会发生这种情况。
当指针再次相等时,也就是说,当写指针跑了一圈并追上读指针时,FIFO为满。
那么问题来了,当指针相等时,FIFO到底为空还是满?
区分是满还是空可以为每个指针添加一个额外的位。当写指针增加到最终FIFO地址之后,写指针将使未使用的MSB标志位递增,同时将其余位置回零,如下图所示(FIFO使用了带MSB标志位的指针)。读取指针也是如此。如果两个指针的MSB不同,则意味着写指针比读指针多跑了一圈。如果两个指针的MSB相同,则意味着两个指针的圈数一致相同。
使用n位指针(其中n-1是访问整个FIFO缓存所需的地址位数),当两个指针(包括MSB)相等时,FIFO为空。当两个
指针(MSB除外)相等时,FIFO已满。即读写指针相同,FIFO为空。最高位不同,其余位为相同,FIFO为满。
1)格雷码
关于格雷码,任何两个相邻数之间的编码距离仅为1(从一个格雷计数到下一个格雷计数,只能改变一位)。其次,最有用的格雷码计数器的深度必须是2的幂. 这意味着本文描述的技术。用于制作2^n深度的FIFO。
比较空满时,需要读写地址进行判断,二者属于跨时钟域,需要进行打拍的同步处理,为避免亚稳态,采用格雷码,因为格雷码相邻只有一位变化,这样同步多位时更不容易产生问题。
格雷码公式:
gray = (binary>>1) ^ binary;
格雷码特点:“读写的最高2位不同,其余位相同”时,处于写满状态。
1 //------------写时钟域------------// 2 //写时钟域内,写数据进FIFO,并将写指针加1 3 assign w_addr = w_pointer[POINTER_WIDTH-2:0]; 4 always@(posedge w_clk or negedge w_rstn)begin 5 if(w_en & (!full))begin 6 fifo_mem[w_addr]<=w_data; 7 end 8 end 9 //写指针计数器 10 always@(posedge w_clk or negedge w_rstn)begin 11 if(!w_rstn)begin 12 w_pointer<=0; 13 end 14 else if(w_en & (!full))begin 15 w_pointer <= w_pointer+1; 16 end 17 else begin 18 w_pointer<=w_pointer; 19 end 20 end 21 22 //-------------------- 23 24 //------------读时钟域------------// 25 //读时钟域内,把FIFO内的数据取出,并将读指针加1 26 assign r_addr = r_pointer[POINTER_WIDTH-2:0]; 27 always@(posedge r_clk or negedge r_rstn)begin 28 if(!r_rstn)begin 29 r_data<='h0; 30 end 31 else if(r_en & (!empty))begin 32 r_data<= fifo_mem[r_addr]; 33 end 34 end 35 //读指针计数器 36 always@(posedge r_clk or negedge r_rstn)begin 37 if(!r_rstn)begin 38 r_pointer<=0; 39 end 40 else if(r_en & (!empty))begin 41 r_pointer <= r_pointer+1; 42 end 43 else begin 44 r_pointer<=r_pointer; 45 end 46 end 47 //-------------------- 48 49 //--------------------指针同步---------- 50 //将格雷码写指针同步到读时钟域 51 //再将转换后的指针经过两级触发器同步 52 assign w_gray_pointer = w_pointer^[w_pointer>>1]; 53 always@(posedge r_clk or negedge r_rstn)begin 54 if(!r_rstn)begin 55 {w_pointer_d1,w_pointer_d2} <=0; 56 end 57 else begin 58 {w_pointer_d1,w_pointer_d2} <= {w_pointer_d1,w_gray_pointer}; 59 end 60 61 end 62 //将格雷码读指针打两拍同步到写时钟域 63 //读指针->格雷码 64 assign r_gray_pointer = r_pointer^[r_pointer>>1]; 65 //将格雷码读指针打两拍同步到写时钟域 66 always@(posedge w_clk or negedge w_rstn)begin 67 if(!w_rstn)begin 68 {w_pointer_d1,w_pointer_d2} <=0; 69 end 70 else begin 71 {r_pointer_d1,r_pointer_d2} <= {r_pointer_d1,r_gray_pointer}; 72 end 73 74 end 75 //--------------------指针同步---------- 76 77 //判断空满 78 assign full = ( 79 (r_pointer_d2[POINTER_WIDTH-1] != w_gray_pointer[POINTER_WIDTH-1])&& //最高位不同 80 (r_pointer_d2[POINTER_WIDTH-2] != w_gray_pointer[POINTER_WIDTH-2])&& //次高位不同 81 (r_pointer_d2[POINTER_WIDTH-3:0] != w_gray_pointer[POINTER_WIDTH-3:0])&& //其他低位不同 82 ); 83 assign empty = (w_pointer_d2 == r_gray_pointer); 84 85 endmodule
10. 时序分析基础
时序分析模型
系统时钟需要满足如下关系:
1)建立时间裕量
注释:其中T为时钟周期,Tcq为触发器时钟端到输出端Q的延时,Tgate或Tdelay为组合逻辑延时。Tsu为建立时间,由于时钟源到达不同寄存器所经历路径的驱动和负载的不同,时钟边沿的位置有所差异,因此就带来了skew。
所有的一切Tskew都是如下:
所以,Tskew有可能为正,也有可能为负,负的话就有利于满足保持时间,正的话就有利于满足建立时间;
2)保持时间裕量
与上面1)的解释相同,Th为保持时间。
总结:建立时间裕量何保持时间裕量是时序分析的两个基础公式,常用于IC笔试题的分析中。
3)例题
下面为联发科一道笔试题,利用上面的公式
11. verilog中不可综合的语句
不可综合verilog语句
(1)initial
只能在test bench中使用,不能综合。
(2)events
event在同步test bench时更有用,不能综合。
(3)real
不支持real数据类型的综合。
(4)time
不支持time数据类型的综合。
(5)force 和release
不支持force和release的综合。
(6)assign 和deassign
不支持对reg 数据类型的assign或deassign进行综合,支持对wire数据类型的assign或deassign进行综合。
(7) fork join
不可综合,可以使用非块语句达到同样的效果。
(8) primitives
支持门级原语的综合,不支持非门级原语的综合。
(9) table
不支持UDP 和table的综合。
(10) 敏感列表里同时带有posedge和negedge
如:always @(posedge clk or negedge clk) begin...end
这个always块不可综合。
(11) 同一个reg变量被多个always块驱动
(12) 延时
以#开头的延时不可综合成硬件电路延时,综合工具会忽略所有延时代码,但不会报错。
如:a=#10 b;
这里的#10是用于仿真时的延时,在综合的时候综合工具会忽略它。也就是说,在综合的时候上式等同于a=b;
(13) 与X、Z的比较
可能会有人喜欢在条件表达式中把数据和X(或Z)进行比较,殊不知这是不可综合的,综合工具同样会忽略。所以要确保信号只有两个状态:0或1。