超大规模集成电路设计笔记:第一篇
加法器
单个全加器
很简单:输入1bit的两个数以及前一级的进位,输出和与进位符。
1 | module f_add ( |
行波进位加法器
我们把N个上面的全加器f_add
首尾串联,便得到了一长串全加器链,它们的计算输入是N位,进位输入与输出均为1位。每次进行计算时,前一个的进位输出都会传进后一个的进位输入,看起来就像是进位在一整条全加器链上产生了波动,因此称其为“行波进位加法器”。
显然,行波进位加法器的优点是结构简单——只需串联就行,但缺点是延时太长。如上图所示,N个全加器串联后,总延时为,这是很致命的。
超前进位加法器
上面的行波进位加法器之所以延时太长,是因为每一位的进位计算都依赖前一位,层层叠加导致计算只能串行进行。那有没有什么办法能提高计算速度,比如计算出后续的进位而不依赖前面的结果呢?有的兄弟有的。
为了方便,我们定义两个新的信号为产生信号和传播信号,并对输入数据A与B的每一位都进行计算:
-
进位产生Generate:如果Ai和Bi均为1,那么第i位就会产生一个进位输出:
-
进位传播Propagate: 如果Ai或Bi为1,那么第i位将把一个进位输入传播到进位输出:
-
进位输出CarryOut: 第i的进位输出Ci表达式为:
将上面的流程应用到每一位,因其进位求值不需要前一级的结果,而是可以直接由每一位计算出,因此称其为“超前进位加法器”。
1 | module cla_3bit ( |
前缀加法器
观察上面的超前进位加法器,可以发现,我们并行计算每一位的进位,比原本的串行计算更快得出结果。还有什么地方可以提升速度呢?
我们使用“归约”的思想可以得到前缀加法器。前缀加法器是一种高性能的进位计算结构,其核心思想是通过前缀树结构实现多级并行归约,更高效地并行计算每一位的进位结果:
- 计算每一位的 g 和 p;
- 采用分层归约方式,逐步合并相邻位的 g 和 p,形成前缀树。例如Kogge-Stone结构:
- 第一层合并相邻两位
- 第二层合并更远的位
- 直到所有进位都被并行计算出来
- 进位的生成是通过多级归约实现的,层数为 log2(N),N为位宽。
- 最终和的计算与超前进位加法器类似。
1 | // 一个Kogge-Stone结构的3bit前缀加法器 |
再来一个8bit的例子:
1 | module prefix_adder_8bit ( |
也可以看这一篇:树形加法器(Brent-Kung加法器) - CSDN
ALU
ALU(Arithmetic Logic Unit),即算术逻辑单元,是计算机中负责运算和逻辑处理的核心模块。下面是一个简易的ALU结构图,包含CPSR高位的条件码标志NZCV:
其Verilog实现也比较简单:
1 | module easyALU ( |
波形看起来也没啥问题:
乘法器
乘法器输入俩N位宽的值,输出一个2N位宽的值。
自动综合乘法器
没啥说的必要。
1 | // 自动综合版 |
结构化移位加法乘法器
结构化移位加法乘法器很简单:算四遍之后移位相加。
1 | // 结构化移位加法实现版 |
阵列乘法器
上面的乘法器依旧用到加法,最终计算是串行计算,会降低计算速度。考虑并行计算,提出了阵列乘法器:
1 | module array_mul4 ( |
阵列乘法器的优点是其时间延时可预测,完成乘法所需最长时间由最右边的对角线以及最后一行来估算。两个N位数相乘的时间可以表示为:
其中指所有的乘积项可以由一个与门阵列同时产生。