所使用EDA软件:VIVADO2018.3
FPGA型号:xc7a35tcsg325-2
DSP48E1的内容比较多,但是我们实际运用它的时候不会去刻意的去调动它的原语。所以对于DSP48E1,我们只需要知道它内部的基本架构,能实现哪些具体的功能,以及它级联后的作用即可。在实际的编码过程中,合理充分的利用DSP48E1不仅可以节约不少CLB资源,还能提高整个FPGA系统的性能。
学习完本章你将会收获以下内容:
-
了解DSP48E1的内部大概的结构,知道里面每个模块的作用。
-
了解乘法、乘加、累加(计数)等计算功能在DSP48E1实现的路径。
首先我们来看一下DSP48E1的结构简图(图1),对其结构有一个初步的认识。
-
寄存器,相信大家都很熟悉。在DSP48E1中它主要是用来做流水线操作,来提高DSP48E1整体的运行性能。
-
框1是一个预加器(加法器),它主要实现的是A(最大位宽30)与D(最大位宽是25)的相加,做预加的话它输出的结果最大位宽为25,该预加器不用的时候可以旁路掉。
-
框2是一个25x18乘法器,它的两个乘数分别为B(最大位宽18位),以及A与D相加后结果的低25位,输出的结果为48(高5位是符号拓展位,低43位是数据位),该乘法器不用的时候可以旁路掉。
-
框3是一个的功能比较多。它能做加(减)法器,累加(减)法器,逻辑运算(与或非),它的输出最大位宽为48位数据位+4位进位。
-
框4是一个模式探测器,它的主要实现带掩膜的数据比较,上下溢出检测,计到一定数对结果进行重置功能。
-
框5是一个数据选择器,它的两个数据输入端分别为C和P(最大位宽48),因此DSP48E1做普通加法还是做累加就取决于它了。当然真实的DSP48E1里面有很多数据选择器,它们与DSP48E1所实现的功能密切相关。
看了我上面写了那么一堆,是不是一头雾水?很正常,因为几十页的的DSP48E1的USER GUIDE 被我强行压缩成这几点。啊哈哈哈哈,开个玩笑。其实,上面那些内容是我一个多月前写的,写着写着我就觉得超级不对劲,如果我一整篇文章都拿来介绍DSP内部的详细架构以及相关信号的话(图2)。最后无异于将DSP48E1 的USER GUIDE(UG479) 的内容硬搬过来,将会十分枯燥,看不下去,说不定评论区还会骂声一片。
所以我我苦思冥想一个多月(其实是疯狂加班一个多月/(ㄒoㄒ)/~~),终于想出了一个即形象生动,又能让客官大老爷们深入了解DSP48E1的方法。那叫是通过讲解DSP48E1 Marco这个神奇的IP(图3,直接在IP Catalog中搜索就有),再结合具有代表性的实例,一步步的去挖掘DSP48E1中的内容。
前面较为复杂的内容没看懂,没关系。但一定一定要知道图1中A、B、C、D、P所对应的端口!!!知道哪些是输入,哪些是输出,哪些是连加法器,哪些是连乘法器的,这是看懂后面内容的基础。
搞清楚A、B、C、D、P所对应的端口的关系后我们还得知道他们位宽限制。如果在没有意识的情况下多用那么几位,最后可能就会导致DSP48E1资源的浪费。举个例子,乘法因子在精度允许的范围内可选20-30位,你用25位最后只用了1个DSP48E1,但如果你用了30位最后就用到2个DSP48E1,使得多出来的DSP48E1利用率低下,造成浪费。在DSP48E1 Marco的IP core中,当我们在Instruction中输好表达式后(图4),即可到Implements中看相应输入输出位宽的限制(图5)。注意:图5中的CONCAT是将预加器旁路,将A和B拼起来所组成组成一个48位的数,所以使用CONCAT的时候,A、B、D是无效的。
接下来我们使用DSP48E1 Marco 这个IP来看几个较为经典的表达式样例以及它的路径。这里流水线我们将他设为自动,让IP 生成工具自动给我们插寄存器就好。当然如果你的数据是跨时钟输入的,你可以选择使用DSP内部的寄存器来减少CLB中寄存器的使用。如果对延迟比较敏感的情况,还可以适当减少寄存器的使用,但是一定要确保每条相关路径上的寄存器数保持一致。
样例1,与累加器相关:P<=C+P(图6)
C输入后打了3拍 与 P相加,相加的结果打1拍再输出到P。
样例2,与预加,乘法,加法相关:P= (A+D)*B+C (图7)
A、D打1拍后进行相加,相加后的结果打1拍与B打2拍的结果相乘。相乘后的结果再与C打3拍后的结果相加,相加的结果打1拍再输出到P。
哈哈哈哈,写到这里发现样例1,和样例2是最为经典的两例了,没啥再好说的了。再补充一下用DSP做加法/减法与CLB做加减法的区别吧。
如果用CLB做加减法(图8),如前面与进位链相关的章节讲到,最低位的进位CIN必须设为1/0。
但当用DSP48E1做加减法时(图9),当我们把ALUMODE[1:0]设置为2’00时,Y设为0时我们可以做加法A+B。当我们把ALUMODE[1:0]设置为2’01时,Y设为1时我们可以做减法A-B。此时CIN可以单独拿出来使用,不必强制设为0/1(当然我们也可以用CIN来代替Y的作用)。
此外一个DSP48E1除了能做1个48位与48位加法/减法/逻辑操作(ONE48),还能被用来做2个24位与24位加法(TWO24),4个12位与12位加法(FOUR12,如图10所示)。这些加法的结果都是带进位的,对应的进位关系如图11所示。
举个例子:我们可以将A:B拼成48位的CONCAT,与48位的C作为三输入就可以做4个12位与12位的加法/减法/逻辑操作。当然这里的CONCAT、C切成4等份。[47:36],[35:24],[23,12],[11,0]。
当ONE48时,CARRYOUY[3] 为 相应的进位结果。
当ONE24时,CARRYOUY[3] 、CARRYOUY[1] 为 相应的进位结果。
当ONE12时,CARRYOUY[3] 、CARRYOUY[2] 、CARRYOUY[1] 、CARRYOUY[0]为 相应的进位结果。
最后DSP48E1的PATTERN DETECT还是很值的一提的。它的结构如(图12)所示。
它的输入主要为PATTERN ,MASK,DATA(经常用的PATTERN和MASK我已经用红框给圈起来了)。DATA为进行DSP48E1运算后未打拍的结果。当我们使用PATTERN DETECT的时候输出要打一拍,这样PATTERNDECT和PATTERNBDECTECT的结果才能和输出P对的上。
-
PATTERN 是用来匹配的样式。当DATA与PATTERN 相同的时候,PATTERNDECT为1,否则为0。当DATA与PATTERN 的反码相同时,PATTENBDETECT为1,否则为0。PATTERN可以由DSP48E1的C打拍后作为输入,也可以选择“参数PATTERN”作为输入(这里的“参数PATTERN” 为PATTERN的其中一个可选输入,注意区分两者关系)。
-
MASK 是掩模,是上下溢出探测最为关键参数。它对应的DATA的每一位。MASK[0] ->DATA[0]...MASK[47] ->DATA[47]。当将MASK的某一位设为1时,它将忽略PATTERN对应位的结果,再将DATA和PATTERN进行比较。MASK可以由DSP48E1的C打拍后作为输入,也可以选择“参数MASK”作为输入,(这里的“参数MASK” 为MASK的其中一个可选输入,注意区分两者关系)。
-
PATTERNBDECTPAST和PATTERNDECTPAST 分别为PATTERNBDECT和PATTERNDECT打一拍的输出结果。
为什么说MASK是上下溢出最为关键的参数呢?我们看一下PATTERN DETECT上下溢出检测的逻辑结构(图13)。很显然overflow是用来检测PATTERNDECT的下降沿的,underflow是用来检测PATTERNBDECT的下降沿的。
当MASK={44'b0,4'b1111} ,当DATA>5'b01111(15)时就会上溢出,当DATA<5'b10000(-16)就会产生下溢出。
-
因为overflow的实质就是检测DATA的高44位(符号拓展位)是不是为全0,15+1=16(5'b10000),高44位就不为全0啦,上溢出。
-
underflow的实质就是检测DATA的高44位(符号拓展位)是不是全1(因为PATTERNBDECT检测的是反码哦,所以检测的是1),-16-1=-17(6'b101111),高44位不为全1,下溢出。
好的,DSP48E1理论相关的东西写到这里就差不多了。但是很多东西都是实践中才能有更多的体会,所以在下个章节我会举些相应例子来让大家体会下使用DSP48E1来优化我们的资源。(⊙﹏⊙)最近没啥灵感,级联什么的也拖到下一章再写吧。