关闭
sifarmer 2023-04-19 06:37 采纳率: 100%
浏览 58
已结题

quartus 综合时只将部分子模块中的乘法器用DSP实现,子模块为相同代码例化

问题遇到的现象和发生背景

quartus prime 21综合时只将部分子模块中的乘法器用DSP实现

操作环境、软件版本等信息

软件版本:Quartus Prime 21.4
在full_mul_level4中例化了多个mul,每个mul中有多个乘法器,但只有u0_mul中的乘法器在综合时用到了DSP,并且综合结果很不正常,full_mul_level4为1024bit的karatsuba大整数乘法器,不应该这么小。可能是什么原因呢。真心请教
代码如下:

(*multstyle="dsp"*)module full_mul_level4(    //384x384 or similar bits
clk,
rstn,
i_a,
i_b,
en0,
en1,
en2,
en3,
en4,
en5,
en6,
o_res
);
parameter A_WIDTH = 1024;
parameter B_WIDTH = 1024;
parameter R_WIDTH = 2048;
parameter DATA_IN_WIDTH = 64;
parameter DATA_OUT_WIDTH = 64; 

input    clk;
input    rstn;
input    [DATA_IN_WIDTH-1:0]    i_a;
input    [DATA_IN_WIDTH-1:0]    i_b;
input    en0;
input    en1;
input    en2;
input    en3;
input    en4;
input    en5;
input    en6;
output    [DATA_OUT_WIDTH-1:0]    o_res;


localparam    WIDTH         = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
localparam    WIDTH_ODD    = WIDTH % 2;
localparam    WIDTH_HALF    = (WIDTH - WIDTH_ODD) / 2;
localparam    H_WIDTH        = WIDTH_HALF + WIDTH_ODD;
localparam    L_WIDTH        = WIDTH_HALF;

localparam    F_WIDTH        = H_WIDTH + 1;

wire  [A_WIDTH-1:0] a;
wire  [B_WIDTH-1:0] b;
assign a = {16{i_a}};
assign b = {16{i_b}};

wire    [L_WIDTH-1:0]    a0;
wire    [H_WIDTH-1:0]    a1;
wire    [L_WIDTH-1:0]    b0;
wire    [H_WIDTH-1:0]    b1;

//                a1        a0
//x                b1        b0
//-------------------------
//    a1b1    a1b0+a0b1    a0b0
//    a1b0 + a0b1 = (a0+a1)(b0+b1) - a1b1 - a0b0


assign    {a1, a0} = a;
assign    {b1, b0} = b;

wire    [L_WIDTH*2-1:0]    a0b0_r5;
wire    [H_WIDTH*2-1:0]    a1b1_r5;
full_mul_level3 #(L_WIDTH, L_WIDTH) u0_mul (
    .clk    (clk), 
    .rstn    (rstn),
    .en0    (en0),
    .en1    (en1),
    .en2    (en2),
    .en3    (en3),
    .en4    (en4),
    .a        (a0),
    .b        (b0),
    .res    (a0b0_r5));
    
full_mul_level3 #(H_WIDTH, H_WIDTH) u1_mul (
    .clk    (clk), 
    .rstn    (rstn),
    .en0    (en0),
    .en1    (en1),
    .en2    (en2),
    .en3    (en3),
    .en4    (en4),
    .a        (a1),
    .b        (b1),
    .res    (a1b1_r5));

wire    [F_WIDTH-1:0]    a_fold = a0 + a1;
wire    [F_WIDTH-1:0]    b_fold = b0 + b1;

wire    [F_WIDTH*2-1:0]    temp0_r5;


full_mul_level3 #(F_WIDTH, F_WIDTH) u2_mul (
    .clk    (clk), 
    .rstn    (rstn),
    .en0    (en0),
    .en1    (en1),
    .en2    (en2),
    .en3    (en3),
    .en4    (en4),
    .a        (a_fold),
    .b        (b_fold),
    .res    (temp0_r5));


reg        [L_WIDTH*2-1:0]    a0b0_r6;
reg        [H_WIDTH*2-1:0]    a1b1_r6;
reg        [F_WIDTH*2-1:0]    temp0_r6;

always @(posedge clk)
if(en5) begin
    a0b0_r6 <= a0b0_r5;
    a1b1_r6 <= a1b1_r5;
    temp0_r6 <= temp0_r5;
end
reg        [L_WIDTH*2-1:0]    a0b0_r7;
reg        [H_WIDTH*2-1:0]    a1b1_r7;
reg        [F_WIDTH*2-1:0]    tmp_r7;

always @(posedge clk) begin
    if (en6) begin
        tmp_r7  <= temp0_r6-a0b0_r6-a1b1_r6;
        a0b0_r7 <= a0b0_r6;
        a1b1_r7 <= a1b1_r6;
    end
end
wire    [WIDTH*2-1:0]    r;

assign r = {{a1b1_r7, {(L_WIDTH){1'b0}}} + tmp_r7, {(L_WIDTH){1'b0}}} + a0b0_r7;

reg        [R_WIDTH-1:0]    res;
always @(posedge clk)
if(en6)
    res <= r[R_WIDTH-1:0];
assign o_res = res[DATA_OUT_WIDTH-1:0];
endmodule

img


img


编译流程从上到下

img

展开全部

  • 写回答

2条回答 默认 最新

  • 老皮芽子 2023-04-19 07:35
    关注
    
    assign a = {16{i_a}};
    assign b = {16{i_b}};
     
    assign    {a1, a0} = a;
    assign    {b1, b0} = b;
    
    wire    [F_WIDTH-1:0]    a_fold = a0 + a1;
    wire    [F_WIDTH-1:0]    b_fold = b0 + b1;
    
    //这样拼接赋值时 a0=a1,b0=b1,a_fold=2*a0,b_fold=2*b0
    //最终 a0b0_r5=a1b1_r5//temp0_r5 = 4*a0b0_r5
    //u1_mul 和 u2_mul 就被优化掉了
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
    sifarmer 2023-04-19 09:18

    谢谢您的回答,好像不是这个原因,在改变i_a和i_b进来的方式,每个cycle进一组数据,16个cycle之后再赋值给a和b,综合结果还是差不多。

    
    ```Verilog HDL
    wire  [A_WIDTH-1:0] a;
    wire  [B_WIDTH-1:0] b;
    reg   [3:0] cnt;
    always @ (posedge clk or negedge rstn) begin
        if (rstn)
            cnt <= 0;
       else 
            cnt <= cnt + 1;
    end
    
    reg [DATA_IN_WIDTH-1:0] a_ass [15:0];
    reg [DATA_IN_WIDTH-1:0] b_ass [15:0];
    
    always @ (posedge clk or negedge rstn) begin
        a_ass[cnt] <= i_a;
        b_ass[cnt] <= i_b;    
    end
    //assign a_ass[cnt] = i_a;
    //assign b_ass[cnt] = i_b;
    genvar i;
    generate
        for (i=0; i<16; i=i+1) begin
            assign a[(i+1)*64-1:i*64] = a_ass[i];
            assign b[(i+1)*64-1:i*64] = b_ass[i];
        end
    endgenerate
    
    

    ```

    回复
    sifarmer 回复 sifarmer 2023-04-20 08:14

    是o_res的原因,只选取部分结果输出,而且输出只与u0_mul中的部分乘法器有关,其他都优化掉了

    回复
查看更多回答(1条)
编辑
预览

报告相同问题?

问题事件

  • 系统已结题 4月28日
  • 已采纳回答 4月21日
  • 创建了问题 4月19日
手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部