这一篇在干嘛?

做数字信号处理(DSP,Digital Signal Processing),比如滤波器、FFT,最核心的运算就是乘法,而且动不动就是几百万次每秒。FPGA 里如果用普通的逻辑单元(LUT)去搭乘法器,又慢又费资源。所以安路在 EG4 系列芯片里专门造了一类”硬件乘法器”,叫 DSP 模块——写好电路就固定在硅片上,又快又省。这一篇就带你把这个模块从里到外看明白:结构、位宽、模式、端口,最后落到 TD 软件里怎么把它用起来。手册基于 TD 4.2.003 版本。

DSP 模块是个啥?为什么需要它

一句话:DSP 模块就是芯片里”出厂焊好”的乘法器。它配置灵活、使用简单,专门用来做乘法这类数字信号处理运算。

EG4(SALEAGLE)系列器件把片上资源和外部接口结合在一起,好处是:提高性能、减少系统成本、降低 DSP 系统的功耗。它可以自己扛下 DSP 运算,也可以当作外部 DSP 芯片的协处理器来搭配使用,总之就是提升整个系统的性价比。

什么时候用 DSP 块?

只要你的设计里有乘法(尤其是滤波、累加这类信号处理运算),优先用 DSP 块,而不是让综合器用 LUT 去搭。用 LUT 搭一个 18×18 乘法器要吃掉一大片逻辑单元,而且速度上不去;DSP 块一个资源就搞定,还有自带寄存器帮你打拍。

体系结构:乘法器里面长什么样

每个嵌入式乘法器可以配置成一个 18×18 乘法器,或者两个独立的 9×9 乘法器。它由三个部分组成:

  • 乘法器级:真正做乘法运算的核心
  • 输入与输出寄存器:帮你把数据打一拍,让时序更稳、跑得更快
  • 输入与输出接口:和外部逻辑连接的通道

图 1:乘法器模块的体系结构,数据从输入寄存器进来,经过乘法器级,再从输出寄存器出去。

输入寄存器:进来的数据先打一拍

根据操作模式,每个乘法器的输入信号可以选择”先经过输入寄存器”或”直接连到内部乘法器”。关键点是:每个输入可以独立设置要不要用寄存器。比如可以把 mia 接到输入寄存器,同时让 mib 直连乘法器,非常灵活。

每个输入寄存器都有这些控制信号:

  • 时钟(clk)
  • 时钟使能
  • 同步/异步清零

时钟是共享的

同一个嵌入式乘法器里的所有输入和输出寄存器都由同一个时钟信号驱动,这点改不了。但时钟使能和异步清零可以按寄存器独立配置——也就是”大家同步干活,但各自可以偷懒/被叫停”。

乘法器级:有符号还是无符号

乘法器级支持 9×9 或 18×18,还能支持这些配置之间的其他位宽。根据数据宽度和操作模式,一个嵌入式乘法器可以同时执行一个或两个乘法运算

每个操作数都可以独立指定是有符号数还是无符号数,由 signa 和 signb 两个信号控制:signa 为高电平,mia 就按有符号数处理;为低电平就是无符号数。mib 同理,由 signb 控制。

两个输入的符号组合和乘积结果的关系如下表:

signamiasignbmib乘积
无符号0无符号0无符号
无符号0有符号1有符号
有符号1无符号0有符号
有符号1有符号1有符号

规律很好记:只要有一个操作数是有符号的,乘积就是有符号的

符号可以运行时动态改

signa 和 signb 不是写死的参数,可以在运行时动态改变,而且它们也有专用的输入寄存器可以打拍。另外,不管你怎么设置符号,乘法器都按全精度运算,不用担心精度损失。

还有个细节:如果这个模块配置成两个 9×9 乘法器,那么这两个乘法器会共享同一个 signa 和 signb——所有 mia 输入必须符号表示一致,所有 mib 输入也必须一致。

输出寄存器:出去之前再打一拍

根据操作模式,输出寄存器可以用 18 bit 或 36 bit 的形式来寄存乘法器的输出(36 bit 正好对应 18×18 乘法的全精度结果)。控制信号和输入寄存器一样:时钟、时钟使能、同步/异步清零。

模块结构图与端口一览

下面这张是 EG4 系列 DSP 模块的完整结构图,看懂它基本就懂了数据怎么流:

图 2:EG4 系列 DSP 模块结构图,可以看到输入 MUX、级联端口、寄存器和乘法器级的连接关系。

对照结构图,把端口整理成一张表(这些名字后面例化代码里还会见到,建议混个脸熟):

端口名位宽方向说明
mia18in来自 PIB 的 DSP 操作数输入,具有寄存器输入模式
mib18in来自 PIB 的另一操作数输入,具有寄存器输入模式
acin18in来自前一级 DSP 的 acout 端口的级联数据输入,具有寄存器输入模式
acout18out连接到下一级 DSP 的 acin 端口的级联数据输出
bcin18in来自前一级 DSP 的 bcout 的级联数据输入,具有寄存器输入模式
bcout18out连接到下一级 DSP 的 bcin 端口的级联数据输出
cea / ceb1in输入寄存器时钟使能,高电平时输入有效
cepd1in输出寄存器时钟使能,高电平时输出有效
clk1inDSP 的输入时钟,作用于内部所有寄存器
rsta_n / rstb_n1in输入寄存器复位信号,低电平时寄存器输出为 0
rstpd_n1in输出寄存器复位信号,低电平时寄存器输出为 0
sourcea1in第一级数据选择器控制端:高电平选 a,低电平选 acin
sourceb1in第一级数据选择器控制端:高电平选 b,低电平选 bcin
mpd36outDSP 的乘积数据输出

级联端口是干嘛的

注意 acin/acout、bcin/bcout 这两对端口:它们是 DSP 块之间的”接力棒”。多个 DSP 块可以级联起来(本级的输出接到下一级的输入),配合 sourcea/sourceb 选择器,就能搭出乘加、滤波器这类多级运算结构,数据不用绕道外部布线,又快又省。

两种操作模式:18×18 还是两个 9×9

根据应用需要,每个嵌入式乘法器可以选下面两种工作模式之一:

  • 一个 18×18 乘法器:一路大数据宽的乘法
  • 两个 9×9 独立乘法器:两路小数据宽的乘法同时做,资源利用率翻倍

怎么选

数据位宽在 10~18 位 → 用 18×18 模式;数据位宽不超过 9 位 → 拆成两个 9×9 并行做,一个 DSP 块当两个用,最划算。

另外,配合逻辑单元还可以实现乘法加法器乘法累加器功能:乘法部分由嵌入式乘法器(DSP 块)完成,加法器或累加器部分则放在普通逻辑单元里实现。滤波器里的”乘一下、加一下、再累加”就是这么搭出来的。

18 位乘法器模式

通过配置,嵌入式乘法器可以支持输入位宽 10 到 18 位的单一 18×18 乘法器。所有 18 位乘法器的输入数据与结果都被独立地送入寄存器。输入可以是有符号整数、无符号整数,或者两者的组合;signa 和 signb 也可以动态修改,并通过专用输入寄存器发送。

图 3:18 位乘法器模式,一个嵌入式乘法器整体作为一路 18×18 使用。

9 位乘法器模式

通过配置,嵌入式乘法器可以支持最多 9 位输入位宽的两个 9×9 乘法器。两路的输入数据与结果各自独立寄存,互不干扰。

图 4:9 位乘法器模式,一个嵌入式乘法器拆成两路独立的 9×9。

9×9 模式的符号共享坑

前面提过:两个 9×9 乘法器共享同一个 signa 和 signb。也就是说,同一个模块里所有 mia 输入的符号表示必须相同,所有 mib 输入的符号表示也必须相同。如果你想一路算有符号、另一路算无符号,得把它们放到两个不同的 DSP 模块里。

在 TD 软件里怎么用:两种调用方式

实际项目中调用 DSP 模块有两种方式:IP Generate 生成代码实例化。两种都合法,看团队习惯。

方式一:软件 IP Generate(图形界面点出来)

在 TD 软件里按这个路径找到 DSP 模块:Tools → IP Generate → IP core → Arithmetic → DSP

图 5:TD 软件中 IP Generate 的入口,在 Arithmetic 分类下找到 DSP。

然后根据实际情况勾选需要的配置,完成 DSP IP 的生成:

图 6:DSP IP 生成配置界面,可以设置输入格式、位宽、寄存器和实现方式等参数。

生成出来的 IP 接口长这样:

接口名位宽输入/输出描述
a2~64inDSP 模块 a 端的数据输入,可配置位宽
b2~64inDSP 模块 b 端的数据输入,可配置位宽
p4~128outDSP 的乘积输出,位宽由输入决定
cea / ceb1in输入寄存器时钟使能信号,高电平时输入有效
cepd1in输出寄存器时钟使能信号,高电平时输出有效
rstan / rstbn1in输入寄存器复位信号,低电平有效
rstpdn1in输出寄存器复位信号,低电平有效
clk1inDSP 的输入时钟,作用于内部所有寄存器

软件界面上那些参数的含义:

参数名称参数描述配置方式
Input FormatDSP 输入格式Signed(有符号)/ Unsigned(无符号)
Input Option输入选项A: 264、B: 264 可配置位宽;a、b、c: Registered 可在输入输出加入寄存器
SR Mode复位模式ASYNC(异步)/ SYNC(同步)
ImplementDSP 实现方式AUTO、DSP、GATE 三种实现方式

Implement 三个选项的区别

  • DSP:强制用 DSP 块实现,吃硬资源但快
  • GATE:用逻辑门(LUT)搭,不占 DSP 资源但慢
  • AUTO:交给工具自己权衡

如果你的乘法位宽很小、DSP 资源又紧张,可以选 GATE;信号处理的关键路径乘法,老老实实选 DSP 或 AUTO。

方式二:代码里直接实例化(原语调用)

DSP 模块也允许在代码里直接例化调用,灵活且易于配置使用。常用参数如下:

参数名称参数描述配置方式
INPUT_WIDTH_A输入位宽可配置位宽:2~64
INPUT_WIDTH_B输入位宽可配置位宽:2~64
OUTPUT_WIDTH输出位宽位宽由输入决定
INPUTFORMAT输入格式Signed、Unsigned
INPUTREGA输入寄存器 AENABLE、DISABLE
INPUTREGB输入寄存器 BENABLE、DISABLE
OUTPUTREG输出寄存器ENABLE、DISABLE
IMPLEMENT实现方式AUTO、DSP、GATE
SRMODE复位模式ASYNC、SYNC

手册给了一个完整例子:有符号、DSP 9×9、输入输出都带寄存器的配置:

EG4_LOGIC_MULT #(
    .INPUT_WIDTH_A (9),
    .INPUT_WIDTH_B (9),
    .OUTPUT_WIDTH  (18),
    .INPUTFORMAT   ("SIGNED"),
    .INPUTREGA     ("ENABLE"),
    .INPUTREGB     ("ENABLE"),
    .OUTPUTREG     ("ENABLE"),
    .IMPLEMENT     ("DSP"),
    .SRMODE        ("ASYNC")
) INST (
    .a      (a),
    .b      (b),
    .p      (p),
    .cea    (cea),
    .ceb    (ceb),
    .cepd   (cepd),
    .clk    (clk),
    .rstan  (rstan),
    .rstbn  (rstbn),
    .rstdn  (rstpdn)
);

9 位有符号数乘 9 位有符号数,结果 18 位,正好对应前面说的 9×9 模式和”输出寄存器 18/36 bit”的说法。

最佳实践

输入输出寄存器(INPUTREGA / INPUTREGB / OUTPUTREG)能开就开。DSP 块内部的寄存器是”白送”的流水线级,开了以后工具布线更从容,时序容易收敛,Fmax 也能往上抬一截。

参考时序图:数据什么时候有效

下图是按上面例程(9×9、带输入输出寄存器)配置的时序参考图:

图 7:DSP 模块的时序参考图,展示时钟、输入、乘积输出之间的时间关系。

读时序图的要点:输入数据在时钟沿被输入寄存器采样,经过乘法器级运算,再在后面的时钟沿被输出寄存器采样送出。也就是说,从输入到输出有效,中间隔了固定的几个时钟周期——这正是”流水线”的代价与收益:单笔数据延迟变大,但吞吐率可以做到每时钟周期一个结果。

对齐你的控制逻辑

因为 DSP 带了流水线寄存器,下游模块读结果 p 时要记得”晚几拍”,别在输入刚送进去的同一拍就去取结果。跟踪 cea/ceb/cepd 使能信号和复位时序,让整条流水线步调一致。

更多资料与小结

想深入了解 EG4 器件本身的规格,可以参考官方的 EG4_DataSheet.pdf(数据手册),它和这份 DSP 用户指南是配套关系。

回顾一下这一篇的核心内容:

  • DSP 模块是 EG4 系列 FPGA 里”焊死”的硬件乘法器,比 LUT 搭乘法更快更省
  • 结构上是三段式:输入寄存器 → 乘法器级 → 输出寄存器,寄存器开不开自己定
  • 两种模式:一个 18×18(10~18 位输入),或两个 9×9(最多 9 位输入)
  • 符号由 signa/signb 控制,“有一个有符号,乘积就有符号”;9×9 模式下两路共享符号信号
  • 级联端口 acin/acout、bcin/bcout 用于多个 DSP 块接力,搭乘加/累加结构
  • TD 里两种用法:Tools → IP Generate → IP core → Arithmetic → DSP 点图形界面,或者直接例化 EG4_LOGIC_MULT 原语;Implement 选 DSP/GATE/AUTO 决定用硬乘法器还是逻辑门