三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

易灵思 DSP48 Block 详解

易灵思 DSP48 Block 详解

DSP Block

  1. DSP模块可以进行乘法、加法、减法、累加、4位可变右移;
    1. 4位可变右移模式;

      1. Normal 模式:支持 1 个通道 (one lane);
      2. Dual 模式:支持 2 个通道 (two lanes);
      3. Quad 模式:支持 4 个通道 (four lanes);
    2. 每个 DSP 模块有四种模式,支持以下乘法操作:

    3. 重要提示: 7 X 6 Quad模式的输出会被截断为12位;

  2. 3种4位可变右移模式设置:都来源于EFX原语
    1. EFX_DSP48
      1. 全功能DSP模块,EFX_DSP48原语可以模拟DSP模块的所有工作模式(NORMAL普通模式、BFLOAT浮点模式、DUAL双路模式、QUAD四路模式);
      2. 在DUAL/QUAD模式下,需要考虑独立数据通路的物理排布,以及最高有效位(MSB)数据位的特殊处理;
      3. 自动例化编译
        1. Efinity自动完成;
        2. Efinity会将2个DSP24模块或最多4个DSP12模块(在相同时钟、复位信号下)“打包” 成1个DSP48资源;
        3. 注意:不能混合打包DSP24和DSP12模块;
      4. 手动例化DSP为DUAL/QUAD模式:
        1. 注意QUAD四路模式:输出仅12位,若计算结果是13位会被截断,因此计算范围受限;
      5. 总结:
        1. EFX_DSP48可以把小DSP(DSP24/DSP12)合并成DSP48,也能手动拆分成双路/四路模式,适配不同位宽的乘法运算(比如 11×10、8×8、7×6、4×4 等),但要注意不同模式下的输入输出位宽限制(尤其是QUAD模式的12位输出截断风险)。
    2. EFX_DSP24
    3. EFX_DSP12

推断DSP

推断乘法器

  1. 推断规则:

    1. 位宽 ≤4 时,推断为EFX_DSP12原语;
    2. 位宽 ≤8 时,推断为EFX_DSP24原语;
    3. 位宽 ≤19,18(即19 X 18)时,推断为EFX_DSP48原语;
    4. 例程:
      `define AWIDTH 4 `define BWIDTH 4 module mult(a, b, x); input signed [`AWIDTH-1:0] a; input signed [`BWIDTH-1:0] b; output signed [`AWIDTH+`BWIDTH-1:0] x; assign x = a * b; endmodule
  2. 推导乘累加:

    1. 乘加运算可以被打包到单个EFX_DSP48原语中,因为输入C的位宽适配了EFX_DSP48的C端口的规则;
    2. 例程:
      module dsp_multadd_s(a, b, c, o); input signed [17:0] a; // 输入:18位带符号数a input signed [17:0] b; // 输入:18位带符号数b input signed [17:0] c; // 输入:18位带符号数c output signed [35:0] o; // 输出:36位带符号数o wire signed [35:0] p; // 中间变量:36位带符号数p(存储a*b的结果) assign p = a * b; // 步骤1:a和b相乘,18位×18位=36位 assign o = p + c; // 步骤2:乘积p与c相加,得到最终输出o endmodule
  3. 带级联的乘累加:

    1. 通常这类级联的乘累加运算无法打包到单个EFX_DSP48原语中,因为输入C的位宽不匹配EFX_DSP48的C端口的规则;通过添加syn_use_dsp属性,综合工具会利用另一个DSP模块的A,B,C级联通路实现乘累加功能;
    2. 例程:
      module dsp_multadd_s(a, b, c, o); input signed [17:0] a; // 输入:18位带符号数a input signed [17:0] b; // 输入:18位带符号数b input signed [35:0] c; // 输入:36位带符号数c(位宽超过单个DSP的C端口) output signed [35:0] o; // 输出:36位带符号数o wire signed [35:0] p; // 中间变量:36位带符号数p(存储a*b的结果) (* syn_use_dsp = "yes" *) wire [35:0] sum; // 综合属性:强制使用DSP资源 assign p = a * b; // 步骤1:a和b相乘,18位×18位=36位 assign sum = p + c; // 步骤2:乘积p与36位的c相加 assign o = sum; // 输出结果 endmodule
  4. 带输出反馈的乘累加:

    1. 反馈通路可以将DSP模块的输出取回,重新用于累加运算。可以通过syn_use_dsp属性启用该功能;
    2. 例程:(实现连续累加)
      module dsp_multadd_s(a, b, clk, o); input signed [17:0] a; // 输入:18位带符号数a input signed [17:0] b; // 输入:18位带符号数b input clk; // 时钟信号(用于寄存器同步) output signed [35:0] o; // 输出:36位带符号数o wire signed [35:0] p; // 中间变量:36位带符号数p(存储a*b的结果) (* syn_use_dsp = "yes" *) reg [35:0] sum; // 带DSP属性的寄存器sum(存储累加结果) assign p = a * b; // 步骤1:a和b相乘,18位×18位=36位 always @(posedge clk) begin // 时钟上升沿触发:将“当前乘积p + 之前的累加结果sum”存回sum sum <= p + sum; end assign o = sum; // 输出最终累加结果 endmodule
    3. 每次时钟上升沿,都会把 “当前a*b的乘积” 和 “之前的累加结果sum” 相加,再存回sum;
  5. 独立反馈累加:

    1. DSP反馈通路可将自身输出取回并用于累加运算,输入a被连接到DSP模块的C端口;同时将M_SEL参数设为C、N_SEL参数设为W,并启用了W_REG寄存器。
    2. 例程:(仅用 DSP 实现的独立反馈累加模块(无乘法,只有累加 + 反馈))
      module dsp_add_s(a, clk, o); input signed [17:0] a; // 输入:18位带符号数a(连接到DSP的C端口) input clk; // 时钟信号(同步累加操作) output signed [35:0] o; // 输出:36位带符号数o(累加结果) (* syn_use_dsp = "yes" *) reg [35:0] sum; // 带DSP属性的寄存器sum(存储累加结果) always @(posedge clk) begin // 时钟上升沿触发:将“当前输入a + 之前的累加结果sum”存回sum sum <= a + sum; end assign o = sum; // 输出最终累加结果 endmodule
  6. 推导移位器

    1. DSP 模块在W寄存器与O寄存器之间具备移位功能。以下代码通过将移位值s连接到C端口来推导移位器:需将SHIFTER参数设为1,并使用P_REG与O_REG参数;同时,移位值必须用同一个时钟进行寄存。
    2. 例程:(**“乘法 + 移位” 功能模块 **利用 DSP 内置移位器实现)
      `define SIZEA 8 // 定义输入a的位宽为8 `define SIZEB 8 // 定义输入b的位宽为8 module dsp_shiftout (a, b, s, clk, x); input clk;// 时钟信号 input [`SIZEA-1:0] a; // 输入:8位信号a input [`SIZEB-1:0] b; // 输入:8位信号b input [3:0] s; // 输入:4位移位值s output [`SIZEA+`SIZEB-1:0] x; // 输出:16位结果x(8×8乘法后移位的结果) reg [`SIZEA+`SIZEB-1:0] p1, p2, p3; // 中间寄存器:存储乘法、移位过程值 reg [3:0] sreg; // 移位值寄存寄存器 always @(posedge clk) begin // 时钟上升沿同步操作 p1 <= a * b; // 步骤1:a和b相乘(8×8=16位) sreg <= s; // 步骤2:寄存移位值s(需与运算同时钟) p3 <= p1 >> sreg; // 步骤3:乘法结果p1右移sreg位 end assign x = p3; // 输出移位后的结果 endmodule
  7. 推导减法运算

    1. 由于位宽较窄,软件会推导(调用)DSP12原语。第一个DSP原语执行p2 = d X c的运算,其输出通过 CASCOUT(级联输出)传递到第二个DSP原语;第二个DSP原语负责处理p1 = a X b和x = p1−p2的运算(通过将2’b01赋值给OP输入端口来实现减法)。
    2. 例程:通过DSP12级联实现的减法模块(基于两次 4×4 乘法的结果做减法)
      module dsp_cas_sub (a, b, c, d, x); input [3:0] a, b, c, d; // 输入:4位信号a、b、c、d output [7:0] x; // 输出:8位结果x(4×4乘法结果的减法值) wire [7:0] p1,p2; // 中间变量:8位(存储两次4×4乘法的结果) assign p1 = a*b; // 运算1:a和b相乘(4×4=8位) assign p2 = d*c; // 运算2:d和c相乘(4×4=8位) assign x = p1-p2; // 运算3:两次乘法结果做减法,得到输出x endmodule
  8. 推导宽位宽乘法器

    1. 对于位宽超过 18×17 的乘法运算,软件会将其分解为多个更小的运算单元;随后,软件会对这些部分积(部分和) 进行累加,最终得到完整的乘积结果。
    2. 例如:一个 32×32 的乘法运算会被拆解为 4 个更小的乘法运算和 3 次累加运算。
    3. 默认情况下,这些部分积的累加操作会利用 DSP 模块的后加法器特性以及 DSP 模块之间的级联通路在 DSP 模块内部完成。
    4. 由于较长的组合逻辑级联通路可能会导致最高工作频率(fMAX)降低,可以在DSP运算中插入流水线寄存器,以额外的延迟为代价,提升数据吞吐量(即提高 fMAX);
  9. 浮点运算

    1. DSP 模块支持BFLOAT16格式(精简16位浮点格式)的融合乘加(FMA)操作。BFLOAT16被映射为16位,格式如下列图示:

    第 15 位是符号位,14-7 位是指数位,6-0 位是尾数位;
    3. 若要使用该功能,必须手动实例化EFX_DSP48原语,并将MODE参数设置为BFLOAT。在此模式下:
    1. DSP模块的输入A、B、C需为BFLOAT16格式;
    2. 最终输出O为32位浮点格式(FP32),这是因为内部累加用 FP32 执行,避免 BFLOAT16 尾数过短导致的精度损失;
    3. 内部累加运算以32位浮点精度执行;
    4.除O_REG外,所有流水线寄存器必须启用,才能保证操作正确;
    4. ```verilog
    EFX_DSP48 dut (
    .A(a), .B(b), .C(18’d0), .OP(op), .O(o), .CASCIIN({48{1’b0}}),
    .CLK(clk), .RST(rst), .CE(1’b1), .SHIFT_ENA(1’b0)
    );
    defparam dut.MODE = “BFLOAT”;
    defparam dut.M_SEL = “P”;
    defparam dut.N_SEL = “W”;
    defparam dut.W_SEL = “X”;
    defparam dut.A_REG = 1;
    defparam dut.B_REG = 1;
    defparam dut.C_REG = 0;
    defparam dut.P_REG = 1;
    defparam dut.OP_REG = 1;
    defparam dut.W_REG = 0;
    defparam dut.O_REG = 1;
    defparam dut.RST_POLARITY = 1;
    5. 代码中A_REG=1、B_REG=1等配置(除O_REG外均启用)是必须的:

    1. 这些寄存器是 DSP 的流水线单元,用于同步输入 / 运算数据,避免长组合路径导致的时序错误;
    2. 若未启用,BFLOAT 模式下的运算时序会紊乱,最终结果错误;
  10. 有效使用DSP模块

    1. EFX_DSP24和EFX_DSP12原语被打包到同一个EFX_DSP48中,需要满足:
      1. 待打包的EFX_DSP24/12的时钟、CE(时钟使能)、RST(复位)、SHIFT_ENA(移位使能)、OP输入必须是相同的信号网络;这些端口可以接VCC、GND或断开,只要所有原语的配置匹配即可;
      2. 所有 DSP 原语的 Verilog HDL 参数必须匹配,包括寄存器端口(A_REG、B_REG、W_REG)和工作模式;
    2. 约束质量
      软件不会随机打包DSP模块 —— 这会负面影响fMAX(最高工作频率)。相反,它会优先打包逻辑相关的DSP模块(例如共享相邻模块、共享输入网络的原语),从而形成在FPGA上适配性最佳的集群。
    3. 提升打包密度方法
      1. 调整设计,让更多DSP模块拥有一致的控制信号和模式设置(例如避免让综合工具为每个EFX_DSP24/12推导独特的时钟使能),使它们满足打包条件;
      2. 将综合选项–dspinput-regs-packing、–dsp-output-regs-packing、–dsp-mac-packing设为 0;这会提升打包密度,但代价是触发器和加法器的资源消耗增加。这些选项可在 “项目编辑器> 综合” 标签页中设置;
      3. 可以根据报告进行辅助调试:
        1. place.rpt:包含 DSP 打包摘要,显示 “忽略控制信号和属性相关的合法性约束时可打包的 DSP 模块数量”—— 这个数字能帮你判断 “调整设计提升打包密度” 是否可行(实际中,调整设计通常能提升约 50% 的打包密度)。报告还会列出每个 DSP 模块的控制集和属性:EFX_DSP24/12 要被打包,必须拥有匹配的控制集和属性。你可以通过这份报告找出 “与其他模块不共享控制集 / 属性的 DSP 模块”,再查看dsp_control_sets.csv获取详细的调整建议;
        2. dsp_control_sets.csv:这是一个 CSV 格式的表格,列出了每个 DSP 模块的所有控制信号和属性。你可以用电子表格打开它,识别出 “因设置独特而无法打包” 的 EFX_DSP24/12 原语;
  11. 时序考量

    1. 高DSP模块利用率下的时序收敛:如果设计中超过50%的 DSP 模块是用EFX_DSP24或EFX_DSP12原语实现的,fMAX(最高工作频率)会因布局种子(placement seed)的不同而显著变化。可以进行“种子扫描” ;
    2. 宽乘法器的处理:当乘法器处于设计的关键路径时,可以尝试不同的综合选项来处理拆解后的乘加结构:
      1. –mult-auto-pipeline:自动在DSP中添加流水线寄存器,以减少关键路径延迟(代价是增加运算延迟);
      2. –mult-decomp-retime:执行反向重定时(backward retiming)以减少关键路径延迟;需在宽乘法器的输出端添加额外寄存器,才能让重定时生效;
      3. 将级联连接的 DSP 模块最大数量设为 2(–max-cc-dsp48=2):在某些情况下,这可以减少关键路径延迟;
    3. 仅略微超过 DSP 位宽的宽乘法器(例如 19×19、20×20):
      1. 其扩展后的部分和 / 部分积可能过小,无法通过 DSP 或进位逻辑高效实现;此时,这些运算可能会被 “位拆分”(bit-blasting)到 LUT 中实现。这种位拆分可能会阻碍前述命令行选项发挥作用,进而影响 fMAX 的优化效果;
      2. 这种情况下,可以将以下命令行选项设为 0,禁用对小型加法器 / 乘法器的位拆分:
        1. –small-adder-limit(默认值:4);
        2. –small-mult-limit(默认值:2);

Readme:上述资料来源为Efinity-synthesis-v4.4版本

← 返回列表