FPGA工程师面试资料【1】
数字IC设计流程
大方向有以下3步:
确定项目需求
前端设计
后端设计
PPA:功耗,性能,面积,即Power, Performance, Area ;
确定项目需求
确定速度、功耗以及功能指标,用高级语言MATLAB、C等对各个模块进行描述,完成方案可行性验证;
前端设计
RTL级代码设计;- 功能验证(前仿真) :对
RTL级的代码进行设计验证,检验设计功能的正确性,是否满足规格中的 所有要求。 - 逻辑综合:添加约束文件,逻辑综合得到门级网表;
- 形式验证(后仿真) :常用的就是等价性检查方法,以功能验证后的
HDL设计为参考,对比综合后的网表功能,他们是否在功能上存在等价性。 STA静态时序分析;检查电路是否存在建立时间和保持时间的违例。
后端设计
DFT可测性设计 :为了在芯片生产之后,测试芯片的良率,看制作有无缺陷,一般是在电路中插入扫描链,DFT是在得到Netlist之后,布局布线之前进行设计;- 布局布线;包括时钟树插入(布局时钟线)和普通信号线;
- 寄生参数提取: 提取延迟信息;
- 版图物理验证 :
DRC(设计规则检查)、LVS(版图一致性检查); - 流片;
FPGA内部资源
主流的FPGA均采用SRAM工艺的查找表(LUT)结构,LUT的本质也是RAM;FPGA的内部组成主要有:
- 可编程输入/输出块(
IOB):FPGA内部的IOB被划分为多个BANK,一个BANK只能有一种接口电压,不同BANK的接口电压可以不一样; - 可配置逻辑块(
CLB): 由查找表(LUT)和可编程寄存器组成,查找表完成纯组合逻辑,内部寄存器可配置成触发器或锁存器;在xilinx的FPGA中,CLB由多个(一般为2个或4个)相同的slice和附加逻辑构成,每个CLB逻辑不仅可以实现组合逻辑、时序逻辑,还可以配置为分布式ram和分布式rom;slice: 是xilinx定义的基本逻辑单位,1个CLB里面有2个SLICE,SLICE可分为SLICEM和SLICEL,M代表memory,L代表logic,顾名思义,带M的SLICE可以用于组成disturbuted ram和shift register,带L的SLICE用于逻辑资源。- **
LUT: **1个SLICE中有4个LUT6(现有FPGA中多使用6输入的LUT,还存在4输入的LUT),8个寄存器,3个2选1 MUX和一个4bit的加法器进位链;由于LUT6有6个输入,那么地址线就可以有6根,输出端为1bit,那么本质上LUT6可以组成一个最大64深,1bit位宽的单口RAM。Distributed RAM深度较大但是位宽很小,所以适用场景也就是小位宽大深度的,同时要知道Distributed RAM时序timing要比Block RAM差。
- **
- 嵌入式块
RAM: 可配置成单端口RAM、双端口RAM以及FIFO等常用存储结构;在7系列的xilinx器件中,每个bram有36Kbit的容量; - 布线资源: 布线资源连通
FPGA内部的所有单元,主要分为全局布线资源、长线资源、短线资源以及分布式布线资源,与采用固定长度的金属线将所有的宏单元连接在一起的CPLD不同,FPGA内部任意两点之间的线延迟是无法预测的,必须等布局、布线完成之后才能确定。 - 底层内嵌的功能单元: 主要包括
DLL、PLL、DSP、CPU等;
二进制、独热码、格雷码
二进制编码
- 优点: 属于压缩状态编码,使用的触发器位数少,可以直接比较大小和算术运算;
- 缺点: 译码复杂;相邻状态变换时,多位发生改变,电噪声大,转换速度较慢,易出错;
独热码
- 优点: 状态比较时仅仅需要比较一个位,从而一定程度上简化了译码逻辑,译码简单,减少了毛刺产生的概率;
- 缺点: 速度较慢,触发器资源占用较多,面积较大;
格雷码
- 优点: 属于压缩状态编码,使用的触发器位数少;相邻状态变换时,仅一位发生改变,电噪声小,转换速度较快;
- 缺点: 译码复杂,没有固定大小,很难直接进行比较大小和算术运算,需要转换为自然二进制码来判断;
相邻 的格雷码之间只有单比特信号变化,多用在异步时钟域处理上,如异步 FIFO 中地址指针的索引就采用格雷码编码。
二进制转换为格雷码的原理
二进制的最高位作为格雷码的最高位,次高位的格雷码为二进制的高位和次高位相异或得到,其他位与次高位类似。即二进制码右移 1 位后与本身异或,其结果就是格雷码。如下图所示:

二进制转换为格雷码的代码为:
verilog
assign gray_out = (bin_in >> 1) ^ bin_in;
格雷码转换为二进制的原理
使用格雷码的最高位作为二进制的最高位,二进制次高位产生过程是使用二进制的高位和次高位格雷码相异或得到,其他位的值与次高位产生过程类似。如下图所示:

对于4bit数据,格雷码转换为二进制的代码为:
verilog
always @(*) begin
bin_out[3] = gray_in[3];
bin_out[2] = gray_in[2]^bin_out[3];
bin_out[1] = gray_in[1]^bin_out[2];
bin_out[0] = gray_in[0]^bin_out[1];
end
0-15的格雷码表示
二进制计数编码从 0 到 15 的计数过程如下:
| 十进制数 | 二进制数 | 格雷码 |
|---|---|---|
| 0 | 0000 | 0000 |
| 1 | 0001 | 0001 |
| 2 | 0010 | 0011 |
| 3 | 0011 | 0010 |
| 4 | 0100 | 0110 |
| 5 | 0101 | 0111 |
| 6 | 0110 | 0101 |
| 7 | 0111 | 0100 |
| 8 | 1000 | 1100 |
| 9 | 1001 | 1101 |
| 10 | 1010 | 1111 |
| 11 | 1011 | 1110 |
| 12 | 1100 | 1010 |
| 13 | 1101 | 1011 |
| 14 | 1110 | 1001 |
| 15 | 1111 | 1000 |
原码、反码、补码
- 原码: 原码的最高位为符号位,其余位均为数值位;
- 反码: 正数的反码等于原码;负数的原码符号位不变,数值位按位取反即为负数的反码;
- 补码: 正数的原码、反码、补码均相等;负数的反码
+1即为补码;
task和function
共同点
- 只能调用本模块内的任务和函数;
- 在任务和函数中不能声明网络连接类型的变量;
- 所有的输入和输出变量实际上都是本地寄存器;
- 任务函数执行完成后才返回结果;
task-任务
一般用于编写测试模块,或者行为描述的模块。
- 可以包含时间控制(如:
# delays,@,wait),但加入时间控制后则该部分无法综合; - 可以包含
input、output、inout端口定义和参数,其也可以没有输入,不返回值; - 可以调用其他的任务或函数;
- 任务可以定义自己的仿真时间单位;
function-函数
一般用于计算,或者用来代替组合逻辑。
- 不能包含任何延迟、函数在零时间执行,所以可综合,多用来模块化组合逻辑,方便复用;
- 函数只有
input变量,虽然没有output变量,但可以通过函数名返回一个值; - 可以调用其他的函数,但不可以调用任务;
- 函数只能与主模块共同用一个仿真时间单位;
位宽计算
二进制数相加减
- 将要进行加减的数据全部转换为补码;
- 选取位宽最大的那个数据的位宽
+1作为计算结果的位宽; - 将要进行加减运算的补码拓展符号位(正数为
0,负数为1)至计算结果的位宽; - 计算结果中的最高位即为符号位,其余位则为计算结果数据位。(此时的数据仍为补码,可根据需求将补码转换为原码输出即可);
二进制数乘法
- 将所有乘数全部转换为补码。
- 计算结果的位宽为乘数的位宽之和。
- 将乘数的补码拓展符号位(正数为
0,负数为1)至计算结果的位宽。 - 计算结果位宽中的最高位即为符号位,其余位则为计算结果数据位。(此时的数据仍为补码,可根据需求将补码转换为原码输出即可)。
例:两个8bit有符号数相乘,其结果需要的位宽是多少?
8bit有符号数的范围为-128~127,最大绝对值的数为-128,因此在极限下为(-128)×(-128)=16384=2^14,为15bit,而15bit有符号数的范围为-16384~16383,并不能表示16384,因此需要16bit位宽。
小数的二进制表示
( 1101.01 ) 2 = 1 × 2 3 + 1 × 2 2 + 0 × 2 1 + 1 × 2 0 + 0 × 2 − 1 + 1 × 2 − 2 = 13.25 (1101.01)_2=1\times2^3+1\times2^2 +0\times2^1+1\times2^0+0\times2^{-1}+1\times2^{-2} = 13.25 (1101.01)2=1×23+1×22+0×21+1×20+0×2−1+1×2−2=13.25
浮点数定点化
例:对12.918做无损定点化,需要的最小位宽是多少位?位宽选择11位时的量化误差是多少?
整数部分为12,即占4位进行量化,即1100。则小数仅剩余8位,0.918*2^8=235.008,取整为235,反量化后为235/256=0.91796875,作差0.91796875-0.918=0.00003125,原小数有效位为3位,而0.00003125小数点后3位为0,量化误差为0.00003125,因此为无损定点化;
当位宽为11位时,整数占4位,小数占7位,0.918*2^7=117.504,取整为118(四舍五入 ),反量化后为118/128=0.921875,作差0.921875-0.918=0.003875,量化误差为0.0039;
例:以8bit数为例,若整数位占3位,小数位占4位,表示的最大值是多少?
最大精度为:
1 ÷ 2 4 = 1 ÷ 16 = 0.0625 1\div2^4=1\div16=0.0625 1÷24=1÷16=0.0625
所能表示的最大值为:7.9375;
阻塞赋值与非阻塞赋值
- 阻塞赋值 :用"
="表示,其对应的电路往往与触发沿没有关系,只与输入电平的变化有关系。立刻执行,右侧表达式求值完后会立即更新至表达式左侧,其后的语句只能在当前的赋值操作执行完成后才能顺序执行,但是在同一个时钟周期内处理完的; - 非阻塞赋值 :用"
<="表示,其对应的电路往往与触发沿有关系,只有在触发沿时才能发生赋值的情况。非阻塞赋值语句执行过程不会被阻塞,即赋值过程可以同时并行执行,非阻塞赋值的过程不影响其他语句的执行;
verilog
initial begin
in = 0;
q = 1;
q_r = 2;
q_rr = 3;
end
always @(posedge clk) begin
q <= in;
q_r <= q;
q_rr <= q_r;
end
其运行后的结果如下图:

综合后的结果如下图:

verilog
initial begin
in = 0;
q = 1;
q_r = 2;
q_rr = 3;
end
always @(posedge clk) begin
q = in; //即使是在时钟的上升沿,q=q_r=q_rr=in=0!!!!!!
q_r = q;
q_rr = q_r;
end
其运行后的结果如下图:

综合后的电路如下:

同步/异步时钟、时钟抖动/偏移
同步/异步时钟
- 同步时钟: 两个时钟的相位关系是固定的;
- 异步时钟: 两个时钟的相位关系无法确定;
经过一个PLL产生的相位不同但相位固定的两个时钟,他们依旧是同步时钟;若是由两个晶振产生的时钟,因为两个晶振在上电时的相位差是随机的,且不同晶振的时钟漂移抖动也不一样,即相位不固定,所以为异步时钟;
同步电路可以很好的避免毛刺,利于器件的移植、静态时序分析等,异步电路则相反;
时钟抖动
时钟频率具有随环境温度变化的特性。理想的方波是不存在的,在不影响系统性能的情况下,允许时钟周期在很小的时间范围内变化。(两个时钟周期存在差值,是时钟发生器内部产生的,和晶振或者PLL内部电路有关,布线对其没有影响);其是频率上的不确定。
时钟偏移(Clock Skew)
由于布线长度以及负载不同引起的,导致同一个时钟信号到达相邻两个时序单元的时间不一致。(同样的时钟产生的多个子时钟之间的延时差异),(同一时钟信号到达两个不同寄存器之间的时间差值)。其是相位上的不确定。
锁存器/触发器
- 锁存器(latch):锁存器对电平信号敏感,在输入脉冲的电平作用下改变状态。
- 触发器(flip-flop) :
D触发器对时钟边沿敏感,检测到上升沿或下降沿触发瞬间改变状态。
锁存器对毛刺敏感,很容易在信号上产生毛刺,不易进行静态时序分析,但占用面积小;
触发器在同一时钟边沿下进行处理,符合同步电路设计的思想;
💓 💖 💓 💖 🍉 🌈 🍓 🕔 ~ 本节完结 ~ 🕔 🍓 🌈 🍉 💖 💓 💖 💓
