数字 IC 知识总结
芯片衡量指标(PPA)
- Performance(性能)
- Power(功耗)
- Area(面积)
吞吐率
- 每秒传递的 bit 位
数字 IC 设计流程
前端(逻辑设计)
-
需求分析:客户向fabless提出设计要求,fabless将其翻译为对芯片产品的技术需求。
-
算法设计:使用高级编程语言如C++设计和优化芯片钟所使用的算法;使用建模仿真工具如MATLAB进行浮点和定点的仿真,进而对算法进行评估和优化。
-
功能架构设计:根据分析的功能需求以及算法分析的结果,设计芯片架构。此外,架构师将系统功能进行分解和细化,形成SPEC规范,将设计参数化。
其中,包括处理器架构的选择(ARM、RISC-V),总线接口的选择(APB、AHB、AXI),软硬件功能的划分以及性能参数(引脚选择、电压频率、工艺选择、功耗和温度范围)。
在这一阶段,可以使用SystemC对芯片构架进行模拟和分析。 -
RTL设计(代码输入):使用Verilog HDL、VHDL等硬件描述语言将模块功能以代码来实现。
-
功能仿真验证(前仿):对RTL级的代码进行验证,以验证设计功能的正确性是否满足SPEC中的要求。
-
逻辑综合:基于特定的工艺库,设定电路的面积、时序等目标参数的约束条件,将设计的RTL级代码映射为门级网表netlist。逻辑综合需要基于特定的综合库,在不同的库中,门电路的基本标准单元(standard cell)的面积、时序参数是不一样的。
-
门级验证(后仿):对综合后的门级网表进行验证,这一阶段通常会使用仿真、静态时序分析和形式验证等工具。
-
静态时序分析(STA):在时序上对电路进行验证,检查电路是否存在建立时间(setup time)和保持时间(hold time)的违例。
-
形式验证(Formality):从功能上对综合后的网表进行验证,将综合后的网表与验证后的RTL设计对比,检查其是否在功能上存在等价性,保证逻辑综合过程中没有改变RTL描述的电路功能。
后端(物理设计)
后端设计
-
可测性设计(DFT):在设计适当增加一些专门用于测试的电路,提高电路的可控制性和可观察性,从而降低电路的测试难度和复杂性,提高电路的测试效率,降低测试成本。
-
布局规划(Floorplanning):放置芯片的宏单元模块,在总体上确定各种功能电路的摆放位置,如IP模块、RAM、I/O引脚等。其会影响芯片的最终面积。
-
时钟树综合CTS(Clock Tree Synthesis):芯片中的时钟网络要驱动电路中所有的时序单元,所以时钟源端门单元带载很多,其负载延时很大并且不平衡,需要插入缓冲器减小负载和平衡延时。时钟网络及其上的缓冲器共同构成了时钟树。一般要反复几次才能做出一个比较理想的时钟树。
-
布线(Place & Route):布线是指在满足工艺规则和布线层数限制、线宽、线间距限制和各线网电性能约束的条件下,根据电路的连接关系将各单元和I/O Pad用互连线连接起来,这些是在时序驱动(Timing driven)的条件下进行的,保证关键时序路径上的连线长度能够最小。
-
寄生参数提取:由于导线本身存在的电阻,相邻导线之间的互感、耦合电容在芯片内部会产生信号噪声、串扰和反射。提取寄生参数进行再次分析验证,分析信号完整性问题。
-
物理版图验证:对布线完成的版图进行功能和时序上的验证。
- LVS(Layout Vs Schematic):与电路图一致性验证,版图和逻辑综合后的门级电路图对比验证。
- DRC(Design Rule Checking):设计规则检查,检查连线间距,连线宽度。
-
ERC:电气规则检查,检查短路开路。
实际的后端流程还包括电路功耗分析,以及随着制造工艺不断进步产生的DFM(可制造性问题)。 -
流片(Tape out):在所有检查和验证都正确无误的情况下把最后的物理版图以GDS II的文件格式交给Foundry,在晶圆硅片上做出实际的电路,再进行封装和测试,就得到了可以使用的芯片。
数字 IC 各流程对应的各公司 EDA
流程 | Synopsys | Cadence | Mentor |
---|---|---|---|
RTL 代码仿真 | VCS、Verdi(收购) | NC-Verilog、Verilog-XL | Modelsim |
综合 | Design complier | Genus | Leonardo |
STA (静态时序分析) | Prime Time | Tempus | SST Velocity |
Formality(形式验证) | Formality | LEC、FormalCheck | FormalPro |
DFT (可测实性设计) | TestMax | modus | BSDArchit |
PnR (布局布线--硬宏) | ICC or ICC2 | Innovus(新) 、 Encounter(旧) | |
CTS(时钟树综合) | Clock Tree Compiler | CT-Gen | |
DRC(设计规则检查) LVS (与电路图一致性验证) | Hercules | Dracula | calibre |
GDSII 文件 |
Cadence的优势在于模拟设计和数字后端。
Synopsys的优势在于数字前端、数字后端和PT signoff。
Mentor的优势是Calibre signoff和DFT。
任务和函数的区别
异步复位 同步释放
所谓异步复位同步释放(Synchronized Asynchronous Reset),就是在复位信号到来的时候不受时钟信号的同步,而是在复位信号释放的时候和时钟信号保持同步。
电路目的:防止复位信号撤除时产生亚稳态事件。
异步复位:显而易见,reset_n异步复位后,rst_n将拉低,即实现异步复位。
同步释放:这个是关键,看如何实现同步释放,即当复位信号reset_n撤除时,由于双缓冲电路(双寄存器)的作用,rst_n复位信号不会随着reset_n的撤除而撤除。
异步复位同步释放的原理图和代码如下:
//Synchronized Asynchronous Reset
//异步复位、同步释放:只适用于没有PLL的系统复位信号的设置
module sync_async_reset(clock,reset_n,rst_n);
input clock, reset_n;
output rst_n;
reg rst_nr1, rst_nr2;
always @(posedge clock or negedge reset_n) begin
if(!reset_n) begin
rst_nr1 <= 1'b0;
rst_nr2 <= 1'b0; //异步复位
end
else begin
rst_nr1 <= 1'b1;
rst_nr2 <= rst_nr1; //同步释放
end
end
assign rst_n = rst_nr2; //新的系统复位信号rst_n
//信号rst_n作为新的系统复位信号,后续可以用来直接“异步复位”
endmodule // sync_async_reset
⚠️:既解决了同步复位的资源消耗问题,又解决了异步复位的亚稳态问题,其根本思想是异步信号同步化
跨时钟域(CDC: Clock Domain Crossing)
门控电路
门控时钟是低功耗技术的一种常规方法
![image-20230716104825457](/Users/tanglong/Library/Application Support/typora-user-images/image-20230716104825457.png)
二进制转格雷码
将二进制数右移移位,再异或上二进制数本身。
assign grey_code = data ^ (data >> 1) //二进制与二进制右移一位的二进制异或
计数器
加 flag 标志位
reg [2:0] cnt ;
reg cnt_flag ;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt <= 'd0;
cnt_flag <= 'd0 ;
end
else if (cnt == 3'd6) begin
cnt <= 'd0 ;
cnt_flag <= 'b1 ;
end
else begin
cnt <= cnt + 'd1 ;
cnt_flag <= 'd0 ;
end
end
不加 flag 标志位
reg [2:0] cnt ;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt <= 'd0;
else if (cnt == 'd6)
cnt <= 'd0 ;
else
cnt <= cnt + 'd1 ;
end
检测边沿
reg [1:0] b;
always@(posedge clk or negedge rst_n)
if(!rst_n)
b<=0;
else
b<={b[0],a};
assign rise=(b===2'b01); //上升沿
assign down=(b===2'b10); //下降沿
序列检测
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [7:0] seq ;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
seq <= 0 ;
match <= 0 ;
end
else begin
seq <= {seq[7:0],a}; //重点是这个
end
end
always@(posedge clk ) begin
if(seq == 8'b01110001)
match <= 1 ;
else
match <= 0 ;
end
endmodule
二段式状态机
//*************code***********//
parameter S0 = 5'b00001 ;
parameter S1 = 5'b10000 ;
parameter S2 = 5'b01000 ;
parameter S3 = 5'b00100 ;
parameter S4 = 5'b00010 ;
reg [4:0] Cur_state ;
reg [4:0] Nxt_state ;
//第一段式
always@(posedge clk or negedge rst) begin
if(!rst)
Cur_state <= S0 ;
else
Cur_state <= Nxt_state ;
end
//第二段式
always@(*) begin
if(!rst) begin
flag = 0;
Nxt_state = S0 ;
end
else
case(Cur_state)
S0:if(data == 0) begin
flag = 0;
Nxt_state = S0 ;
end
else begin
flag = 0;
Nxt_state = S1 ;
end
S1:if(data == 0) begin
flag = 0;
Nxt_state = S1 ;
end
else begin
flag = 0;
Nxt_state = S2 ;
end
S2:if(data == 0) begin
flag = 0;
Nxt_state = S2 ;
end
else begin
flag = 0;
Nxt_state = S3 ;
end
S3:if(data == 0) begin
flag = 0;
Nxt_state = S3 ;
end
else begin
flag = 0;
Nxt_state = S4 ;
end
S4:if(data == 0) begin
flag = 1;
Nxt_state = S0 ;
end
else begin
flag = 1;
Nxt_state = S1 ;
end
default: Nxt_state = S0 ;
endcase
end
//*************code***********//
分频
1、奇数 50%占空比。对下降沿和上升沿都计数
//*************code***********//
parameter N = 7 ;
reg [2:0] cnt;
reg clk7;
always@(posedge clk or negedge clk or negedge rst)
if(!rst)
cnt <= 3'b0;
else if(cnt == N-1)
cnt <= 'b0;
else
cnt <= cnt + 1'b1;
always@(posedge clk or negedge clk or negedge rst)
if(!rst)
clk7 <= 1'b0;
else if(cnt == N-1)
clk7 <= ~clk7;
assign clk_out7 =clk7;
最大公约数 (GCD)
1、辗转相除法
⚠️:求最大公约数:辗转相除法(35:14)-->(21:14)-->(7:14)-->(7:7)
if(A_r > B_r) begin
A_r <= A_r - B_r;
B_r <= B_r;
end
else if(A_r < B_r) begin //A_r < B_r
B_r <= B_r - A_r;
A_r <= A_r;
else
GCD <= A_r ;
end
最小公倍数
⚠️:最小公倍数=A*B / 最大公约数
模逆
扩展欧几里得(Extended Euclidean algorithm) 又称辗转相除法
扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数)
设exgcd(a,n)为扩展欧几里得算法的函数,则可得到ax+ny=g,g是a,n的最大公因数。
ax+by=gcd(a,b) 贝祖等式
当gcd(a,b) = 1 , 模逆才存在
//运算原理
1、实例 两个贝祖等式
a*x1 + b*y1 = u
a*x2 + b*y2 = v
2、{x1, y1, x2, y2} = 4'b1001;
3 判断 模数 b 是否为 0 进入死循环
a%b = a - [a/b]*b
x1 = x2;
x2 = x1 - [a/b]*y2;
y1 = y2;
y2 = y1 - [a/b]*y2;
a <= b ;
b <= a%b ;
4、b == 0
输出gcd(a,b) = a, x1 为 a 的模逆
模逆流程图
⚠️原理:a mod b = a - [a/b]*b;a<-b ; b <- a%b;
乘法器
流水线型
integer i ;
reg [7:0] temp[3:0];
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
for(i=0;i<4;i=i+1)
temp[i] = 0;
end
else begin
temp[0] <= b[0] ? {{4{1'b0}},a} : 8'd0 ;
temp[1] <= b[1] ? {{3{1'b0}},a,{1{1'b0}}} : 8'd0 ;
temp[2] <= b[2] ? {{2{1'b0}},a,{2{1'b0}}} : 8'd0 ;
temp[3] <= b[3] ? {{1{1'b0}},a,{3{1'b0}}} : 8'd0 ;
end
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
c <= 0;
else
c <= {temp[0] + temp[1] + temp[2] + temp[3]};
end
组合逻辑型
wire [23:0] temp[7:0];
assign temp[0] = (b[0])? {{8{1'b0}},a,{8{1'b0}}}:24'd0;
assign temp[1] = (b[1])? {{7{1'b0}},a,{9{1'b0}}}:24'd0;
assign temp[2] = (b[2])? {{6{1'b0}},a,{10{1'b0}}}:24'd0;
assign temp[3] = (b[3])? {{5{1'b0}},a,{11{1'b0}}}:24'd0;
assign temp[4] = (b[4])? {{4{1'b0}},a,{12{1'b0}}}:24'd0;
assign temp[5] = (b[5])? {{3{1'b0}},a,{13{1'b0}}}:24'd0;
assign temp[6] = (b[6])? {{2{1'b0}},a,{14{1'b0}}}:24'd0;
assign temp[7] = (b[7])? {{1{1'b0}},a,{15{1'b0}}}:24'd0;
assign Data_out_reg = temp[0]+temp[1]+temp[2]+temp[3]+temp[4]+temp[5]+temp[6]+temp[7];
乘法器
max min
always@() begin
else if(cnt == 'd0 && InEN)
max_reg <= r;
else if(cnt == 'd1) begin
if(InData >= max_reg) begin
max_reg <= InData ;
min_reg <= max_reg ;
end
else begin
min_reg <= InData ;
max_reg <= max_reg ;
end
end
else begin
max_reg <= max_reg ;
min_reg <= min_reg ;
end
end
**************************
always@() begin
else if(cnt == 'd2) begin
if(InData >= max_reg)
max <= InData ;
else if(InData <= min_reg)
min <= InData ;
else begin
max <= max_reg ;
min <= min_reg ;
end
end
end