MAC89_DSP48E1

DSP48E1ユニットを4つ使って、49bit*35bit=84bitの積を求め、89bitアキュムレータで和を求めるユニット。
初めからいろいろつけると途中で挫折しそうだったので最小限の構成。
マジックナンバーもとりあえず直書きで、繰り返しもベタに展開した。


基本アイディアは桁ごとに積和を求め、最後に最終結果算出(ファイナライズ)命令を発行して初めて結果としてまとめるということ。
これにより、アキュムレータ用に別途DPS48E1を2つ使わなくてよい。
ただし、DSP48E1を別に使えば96bitのアキュムレータになるので、悪くはない。


レイテンシ6のパイプラインで、通常演算も位ごとに1サイクルずつずらし和と最終結果算出で取り合うPレジスタのハザードをなくしたので、スループットは1。
可能な限りDSP48E1ユニット内のレジスタと配線リソースを使うようにしたが、一部のレジスタはスライス上に実装する必要がある。


クロックゲーティングも一応入れた。
命令内容を見てマスクすればもっとスイッチングを減らせそうだが、記述量の割には効果が?だったのでとりあえずなし。
NOP命令はクロックゲーティングで代用できるのでいらなかったかも。


シミュレーションでA*Bに乱数を与えてVerilogの*演算子で計算した結果と一致させるテストをしばらく走らせていたが、結果はずっと合ってるのでとりあえずは大丈夫か?
他の積和とかも順次検証する。


後は一応つけてあるけど動いていないオーバーフロー/アンダーフロー検出とか。

module MAC89_DSP48E1
(
    //Clock & Reset
    input   wire            i_clk,
    input   wire            i_rst,
    
    //Control
    input   wire            i_ce,
    output  wire            o_ce,
    output  wire            o_valid,        //0:non finalized data
                                            //1:finalized data
    //Status
    output  wire            o_overflow,     //Overflow any P reg
    output  wire            o_underflow,    //Underflow any P reg
    
    //Command
    input   wire    [2:0]   i_cmd,          //refer:C_* localparam
    
    //Data
    input   wire    [48:0]  i_a,
    input   wire    [34:0]  i_b,
    input   wire    [88:0]  i_c,
    
    output  wire    [88:0]  o_p
);
    //Command
    localparam  [2:0]   C_NOP   = 3'b000; //NOP(P<=P)
    localparam  [2:0]   C_AB    = 3'b001; //P<=A*B
    localparam  [2:0]   C_AB_P  = 3'b010; //P<=A*B+P
    localparam  [2:0]   C_AB_C  = 3'b011; //P<=A*B+C
    localparam  [2:0]   C_C     = 3'b100; //P<=C
    localparam  [2:0]   C_C_P   = 3'b101; //P<=P+C
    localparam  [2:0]   C_ZERO  = 3'b110; //P<=0
    localparam  [2:0]   C_FINAL = 3'b111; //Finalize(must 3cycle assert)
    
    //XY MUX    OPMODE[3:0] (X&Y not indipendent, unison)
    localparam  [3:0]   XY_ZERO = 4'b0000;  //0
    localparam  [3:0]   XY_MUL  = 4'b0101;  //M
    localparam  [3:0]   XY_P    = 4'b0010;  //P
    localparam  [3:0]   XY_C    = 4'b1100;  //C
    
    //Z MUX     OPMODE[6:4]
    localparam  [6:4]   Z_ZERO      = 3'b000;   //0
    localparam  [6:4]   Z_PCIN      = 3'b001;   //PCIN
    localparam  [6:4]   Z_P         = 3'b010;   //P
    localparam  [6:4]   Z_C         = 3'b011;   //C
    localparam  [6:4]   Z_PCIN_17S  = 3'b101;   //PCIN(17bit shift)
    localparam  [6:4]   Z_P_17S     = 3'b110;   //P(17bit shift)
    
    //Control wire
    wire    [3:0]   ALUMODE_ALBL;
    wire    [3:0]   ALUMODE_ALBH;
    wire    [3:0]   ALUMODE_AHBL;
    wire    [3:0]   ALUMODE_AHBH;
    
    wire    [2:0]   CARRYINSEL_ALBL;
    wire    [2:0]   CARRYINSEL_ALBH;
    wire    [2:0]   CARRYINSEL_AHBL;
    wire    [2:0]   CARRYINSEL_AHBH;
    
    wire    [4:0]   INMODE_ALBL;
    wire    [4:0]   INMODE_ALBH;
    wire    [4:0]   INMODE_AHBL;
    wire    [4:0]   INMODE_AHBH;
    
    wire    [6:0]   OPMODE_ALBL;
    wire    [6:0]   OPMODE_ALBH;
    wire    [6:0]   OPMODE_AHBL;
    wire    [6:0]   OPMODE_AHBH;
    
    wire            OVERFLOW_ALBL;
    wire            OVERFLOW_ALBH;
    wire            OVERFLOW_AHBL;
    wire            OVERFLOW_AHBH;
    
    wire            UNDERFLOW_ALBL;
    wire            UNDERFLOW_ALBH;
    wire            UNDERFLOW_AHBL;
    wire            UNDERFLOW_AHBH;
    
    //Control Reg
    reg             r_ce    [1:6];
    reg     [2:0]   r_cmd   [1:6];
    
    //Data wire
    wire    [29:0]  AL;
    wire    [29:0]  AH;
    wire    [17:0]  BL;
    wire    [17:0]  BH;
    wire    [47:0]  C_ALBL;
    wire    [47:0]  C_AHBH;
    
    wire    [29:0]  ACOUT_ALBL;
    wire    [29:0]  ACOUT_AHBL;
    
    wire    [47:0]  PCOUT_ALBL;
    wire    [47:0]  PCOUT_AHBL;
    
    wire    [47:0]  P_ALBH_TO_C_AHBL;
    
    wire    [47:0]  P_ALBL;
    wire    [47:0]  P_ALBH;
    wire    [47:0]  P_AHBL;
    wire    [47:0]  P_AHBH;
    
    //Data Reg
    reg     [29:0]  r_AH        [1:1];
    reg     [17:0]  r_BL        [1:1];
    reg     [17:0]  r_BH        [1:2];
    reg     [47:0]  r_C_ALBL    [1:1];
    reg     [47:0]  r_C_AHBH    [1:4];
    
    reg     [16:0]  r_low_ALBH;
    reg     [23:0]  r_low_AHBL;
    reg     [40:0]  r_low_AHBH;
    
    //Clock Enable FF
    always @(posedge i_clk) begin
        if(i_rst) begin
            r_ce[1] <= 1'b0;
            r_ce[2] <= 1'b0;
            r_ce[3] <= 1'b0;
            r_ce[4] <= 1'b0;
            r_ce[5] <= 1'b0;
            r_ce[6] <= 1'b0;
        end else begin
            r_ce[1] <= i_ce;
            r_ce[2] <= r_ce[1];
            r_ce[3] <= r_ce[2];
            r_ce[4] <= r_ce[3];
            r_ce[5] <= r_ce[4];
            r_ce[6] <= r_ce[5];
        end
    end
    
    assign  o_ce = r_ce[6];
    
    //Command FF
    always @(posedge i_clk) begin
        if(i_rst) begin
            r_cmd[1]    <= 3'b0;
            r_cmd[2]    <= 3'b0;
            r_cmd[3]    <= 3'b0;
            r_cmd[4]    <= 3'b0;
            r_cmd[5]    <= 3'b0;
            r_cmd[6]    <= 3'b0;
        end else begin
            if(i_ce)    r_cmd[1]    <= i_cmd;
            if(r_ce[1]) r_cmd[2]    <= r_cmd[1];
            if(r_ce[2]) r_cmd[3]    <= r_cmd[2];
            if(r_ce[3]) r_cmd[4]    <= r_cmd[3];
            if(r_ce[4]) r_cmd[5]    <= r_cmd[4];
            if(r_ce[5]) r_cmd[6]    <= r_cmd[5];
        end
    end
    
    assign  o_valid = (r_cmd[6] == C_FINAL) ? 1'b1 : 1'b0;
    
    //overflow underflow
    assign  o_overflow  = OVERFLOW_ALBL | OVERFLOW_ALBH |
                          OVERFLOW_AHBL | OVERFLOW_AHBH ;

    assign  o_underflow = UNDERFLOW_ALBL | UNDERFLOW_ALBH |
                          UNDERFLOW_AHBL | UNDERFLOW_AHBH ;
    
    //INMODE
    assign  INMODE_ALBL[0]  = 1'b0; //A2
    assign  INMODE_ALBL[1]  = 1'b0; //Pass A Value
    assign  INMODE_ALBL[2]  = 1'b0; //Default
    assign  INMODE_ALBL[3]  = 1'b0; //Default
    assign  INMODE_ALBL[4]  = 1'b0; //B2
    
    assign  INMODE_ALBH = INMODE_ALBL;
    assign  INMODE_AHBL = INMODE_ALBL;
    assign  INMODE_AHBH = INMODE_ALBL;
    
    //CARRYINSEL
    assign  CARRYINSEL_ALBL = 3'b000;   //Use User carry(Fixed zero)
    assign  CARRYINSEL_ALBH = 3'b000;
    assign  CARRYINSEL_AHBL = 3'b000;
    assign  CARRYINSEL_AHBH = 3'b000;
    
    //OPMODE
    assign  OPMODE_ALBL = ((r_cmd[2] != C_FINAL) &&                       //Last Executed Command
                           (r_cmd[1] == C_FINAL)) ? {Z_ZERO, XY_P     } : //Finalize
                           
                           (r_cmd[1] == C_NOP  )  ? {Z_ZERO, XY_P     } : //NOP(P<=P)
                           (r_cmd[1] == C_AB   )  ? {Z_ZERO, XY_MUL   } : //P<=A*B
                           (r_cmd[1] == C_AB_P )  ? {Z_P,    XY_MUL   } : //P<=A*B+P
                           (r_cmd[1] == C_AB_C )  ? {Z_C,    XY_MUL   } : //P<=A*B+C
                           (r_cmd[1] == C_C    )  ? {Z_ZERO, XY_C     } : //P<=C
                           (r_cmd[1] == C_C_P  )  ? {Z_P,    XY_C     } : //P<=P+C
                           (r_cmd[1] == C_ZERO )  ? {Z_ZERO, XY_ZERO  } : //P<=0
                                                    {Z_ZERO, XY_P     } ; //Default
    
    assign  OPMODE_ALBH = ((r_cmd[3] != C_FINAL) &&                       //Last Executed Command
                           (r_cmd[2] == C_FINAL)) ? {Z_PCIN_17S, XY_P } : //Finalize
                           
                           (r_cmd[2] == C_NOP  )  ? {Z_ZERO,  XY_P    } : //NOP(P<=P)
                           (r_cmd[2] == C_AB   )  ? {Z_ZERO,  XY_MUL  } : //P<=A*B
                           (r_cmd[2] == C_AB_P )  ? {Z_P,     XY_MUL  } : //P<=A*B+P
                           (r_cmd[2] == C_AB_C )  ? {Z_ZERO,  XY_MUL  } : //P<=A*B+C
                           (r_cmd[2] == C_C    )  ? {Z_ZERO,  XY_ZERO } : //P<=C
                           (r_cmd[2] == C_C_P  )  ? {Z_P,     XY_ZERO } : //P<=P+C
                           (r_cmd[2] == C_ZERO )  ? {Z_ZERO,  XY_ZERO } : //P<=0
                                                    {Z_ZERO,  XY_P    } ; //Default
    
    assign  OPMODE_AHBL = ((r_cmd[4] != C_FINAL) &&                       //Last Executed Command
                           (r_cmd[3] == C_FINAL)) ? {Z_C, XY_P        } : //Finalize
                           
                           (r_cmd[3] == C_NOP  )  ? {Z_ZERO,  XY_P    } : //NOP(P<=P)
                           (r_cmd[3] == C_AB   )  ? {Z_ZERO,  XY_MUL  } : //P<=A*B
                           (r_cmd[3] == C_AB_P )  ? {Z_P,     XY_MUL  } : //P<=A*B+P
                           (r_cmd[3] == C_AB_C )  ? {Z_ZERO,  XY_MUL  } : //P<=A*B+C
                           (r_cmd[3] == C_C    )  ? {Z_ZERO,  XY_ZERO } : //P<=C
                           (r_cmd[3] == C_C_P  )  ? {Z_P,     XY_ZERO } : //P<=P+C
                           (r_cmd[3] == C_ZERO )  ? {Z_ZERO,  XY_ZERO } : //P<=0
                                                    {Z_ZERO,  XY_P    } ; //Default
    
    assign  OPMODE_AHBH = ((r_cmd[5] != C_FINAL) &&                       //Last Executed Command
                           (r_cmd[4] == C_FINAL)) ? {Z_PCIN_17S, XY_P } : //Finalize
                           
                           (r_cmd[4] == C_NOP  )  ? {Z_ZERO, XY_P     } : //NOP(P<=P)
                           (r_cmd[4] == C_AB   )  ? {Z_ZERO, XY_MUL   } : //P<=A*B
                           (r_cmd[4] == C_AB_P )  ? {Z_P,    XY_MUL   } : //P<=A*B+P
                           (r_cmd[4] == C_AB_C )  ? {Z_C,    XY_MUL   } : //P<=A*B+C
                           (r_cmd[4] == C_C    )  ? {Z_ZERO, XY_C     } : //P<=C
                           (r_cmd[4] == C_C_P  )  ? {Z_P,    XY_C     } : //P<=P+C
                           (r_cmd[4] == C_ZERO )  ? {Z_ZERO, XY_ZERO  } : //P<=0
                                                    {Z_ZERO, XY_P     } ; //Default
    
    //ALUMODE
    assign  ALUMODE_ALBL    = 4'b0000;  //Z+X+Y+CIN
    assign  ALUMODE_ALBH    = 4'b0000;
    assign  ALUMODE_AHBL    = 4'b0000;
    assign  ALUMODE_AHBH    = 4'b0000;
    
    //Input Data Packing
    assign  AL  = {6'b0, i_a[23: 0]};
    assign  AH  = {5'b0, i_a[48:24]};
    assign  BL  = {1'b0, i_b[16: 0]};
    assign  BH  =        i_b[34:17] ;
    
    assign  C_ALBL  = {7'b0, i_c[40: 0]};
    assign  C_AHBH  =        i_c[88:41] ;
    
    assign  P_ALBH_TO_C_AHBL    = {{7{P_ALBH[47]}}, P_ALBH[47:7]};
    
    //Input Data Pipeline Reg
    always @(posedge i_clk) begin
        if(i_rst) begin
            r_AH[1]  <= 0;
            r_BL[1]  <= 0;
            r_BH[1]  <= 0;
            
            r_BH[2]  <= 0;
            
            r_C_ALBL[1] <= 0;
            
            r_C_AHBH[1] <= 0;
            
            r_C_AHBH[2] <= 0;
            r_C_AHBH[3] <= 0;
            r_C_AHBH[4] <= 0;
        end else begin
            if(i_ce) r_AH[1]  <= AH;
            if(i_ce) r_BL[1]  <= BL;
            if(i_ce) r_BH[1]  <= BH;
            
            if(r_ce[1]) r_BH[2]  <= r_BH[1];
            
            if(i_ce) r_C_ALBL[1]  <= C_ALBL;
            
            if(i_ce) r_C_AHBH[1]  <= C_AHBH;
            
            if(r_ce[1]) r_C_AHBH[2] <= r_C_AHBH[1];
            if(r_ce[2]) r_C_AHBH[3] <= r_C_AHBH[2];
            if(r_ce[3]) r_C_AHBH[4] <= r_C_AHBH[3];
        end
    end
    
    //P Pipeline Reg
    always @(posedge i_clk) begin
        if(i_rst) begin
            r_low_ALBH  <= 0;
            r_low_AHBL  <= 0;
            r_low_AHBH  <= 0;
        end else begin
            if(r_ce[3]) r_low_ALBH  <= P_ALBL[16:0];
            if(r_ce[4]) r_low_AHBL  <= {P_ALBH[6:0], r_low_ALBH};
            if(r_ce[5]) r_low_AHBH  <= {P_AHBL[16:0], r_low_AHBL};
        end
    end
    
    //Output Data Pcaking
    assign  o_p = {P_AHBH, r_low_AHBH};
    
    //DSP Cores
    DSP48E1 #(
        // Feature Control Attributes: Data Path Selection
        .A_INPUT            ( "DIRECT"          ), // Selects A input source, "DIRECT" (A port) or "CASCADE" (ACIN port)
        .B_INPUT            ( "DIRECT"          ), // Selects B input source, "DIRECT" (B port) or "CASCADE" (BCIN port)
        .USE_DPORT          ( "FALSE"           ), // Select D port usage (TRUE or FALSE)
        .USE_MULT           ( "MULTIPLY"        ), // Select multiplier usage ("MULTIPLY", "DYNAMIC", or "NONE")
        .USE_SIMD           ( "ONE48"           ), // SIMD selection ("ONE48", "TWO24", "FOUR12")
        // Pattern Detector Attributes: Pattern Detection Configuration
        .AUTORESET_PATDET   ( "NO_RESET"        ), // "NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH"
        .MASK               ( 48'h3fffffffffff  ), // 48-bit mask value for pattern detect (1=ignore)
        .PATTERN            ( 48'h000000000000  ), // 48-bit pattern match for pattern detect
        .SEL_MASK           ( "MASK"            ), // "C", "MASK", "ROUNDING_MODE1", "ROUNDING_MODE2"
        .SEL_PATTERN        ( "PATTERN"         ), // Select pattern value ("PATTERN" or "C")
        .USE_PATTERN_DETECT ( "NO_PATDET"       ), // Enable pattern detect ("PATDET" or "NO_PATDET")
        // Register Control Attributes: Pipeline Register Configuration
        .ACASCREG           ( 1                 ), // Number of pipeline stages between A/ACIN and ACOUT (0, 1 or 2)
        .ADREG              ( 1                 ), // Number of pipeline stages for pre-adder (0 or 1)
        .ALUMODEREG         ( 1                 ), // Number of pipeline stages for ALUMODE (0 or 1)
        .AREG               ( 1                 ), // Number of pipeline stages for A (0, 1 or 2)
        .BCASCREG           ( 1                 ), // Number of pipeline stages between B/BCIN and BCOUT (0, 1 or 2)
        .BREG               ( 1                 ), // Number of pipeline stages for B (0, 1 or 2)
        .CARRYINREG         ( 1                 ), // Number of pipeline stages for CARRYIN (0 or 1)
        .CARRYINSELREG      ( 1                 ), // Number of pipeline stages for CARRYINSEL (0 or 1)
        .CREG               ( 1                 ), // Number of pipeline stages for C (0 or 1)
        .DREG               ( 1                 ), // Number of pipeline stages for D (0 or 1)
        .INMODEREG          ( 1                 ), // Number of pipeline stages for INMODE (0 or 1)
        .MREG               ( 1                 ), // Number of multiplier pipeline stages (0 or 1)
        .OPMODEREG          ( 1                 ), // Number of pipeline stages for OPMODE (0 or 1)
        .PREG               ( 1                 ) // Number of pipeline stages for P (0 or 1)
    ) DSP48E1_ALBL (
        // Cascade: 30-bit (each) output: Cascade Ports
        .ACOUT              ( ACOUT_ALBL        ), // 30-bit output: A port cascade output
        .BCOUT              (                   ), // 18-bit output: B port cascade output
        .CARRYCASCOUT       (                   ), // 1-bit output: Cascade carry output
        .MULTSIGNOUT        (                   ), // 1-bit output: Multiplier sign cascade output
        .PCOUT              ( PCOUT_ALBL        ), // 48-bit output: Cascade output
        // Control: 1-bit (each) output: Control Inputs/Status Bits
        .OVERFLOW           ( OVERFLOW_ALBL     ), // 1-bit output: Overflow in add/acc output
        .PATTERNBDETECT     (                   ), // 1-bit output: Pattern bar detect output
        .PATTERNDETECT      (                   ), // 1-bit output: Pattern detect output
        .UNDERFLOW          ( UNDERFLOW_ALBL    ), // 1-bit output: Underflow in add/acc output
        // Data: 4-bit (each) output: Data Ports
        .CARRYOUT           (                   ), // 4-bit output: Carry output
        .P                  ( P_ALBL            ), // 48-bit output: Primary data output
        // Cascade: 30-bit (each) input: Cascade Ports
        .ACIN               ( 30'b0             ), // 30-bit input: A cascade data input
        .BCIN               ( 18'b0             ), // 18-bit input: B cascade input
        .CARRYCASCIN        ( 1'b0              ), // 1-bit input: Cascade carry input
        .MULTSIGNIN         ( 1'b0              ), // 1-bit input: Multiplier sign input
        .PCIN               ( 48'b0             ), // 48-bit input: P cascade input
        // Control: 4-bit (each) input: Control Inputs/Status Bits
        .ALUMODE            ( ALUMODE_ALBL      ), // 4-bit input: ALU control input
        .CARRYINSEL         ( CARRYINSEL_ALBL   ), // 3-bit input: Carry select input
        .CLK                ( i_clk             ), // 1-bit input: Clock input
        .INMODE             ( INMODE_ALBL       ), // 5-bit input: INMODE control input
        .OPMODE             ( OPMODE_ALBL       ), // 7-bit input: Operation mode input
        // Data: 30-bit (each) input: Data Ports
        .A                  ( AL                ), // 30-bit input: A data input
        .B                  ( BL                ), // 18-bit input: B data input
        .C                  ( r_C_ALBL[1]       ), // 48-bit input: C data input
        .CARRYIN            ( 1'b0              ), // 1-bit input: Carry input signal
        .D                  ( 25'b0             ), // 25-bit input: D data input
        // Reset/Clock Enable: 1-bit (each) input: Reset/Clock Enable Inputs
        .CED                ( 1'b0              ), // 1-bit input: Clock enable input for DREG
        .CEAD               ( 1'b0              ), // 1-bit input: Clock enable input for ADREG
        .CEA1               ( 1'b0              ), // 1-bit input: Clock enable input for 1st stage AREG
        .CEB1               ( 1'b0              ), // 1-bit input: Clock enable input for 1st stage BREG
        
        .CEA2               ( i_ce              ), // 1-bit input: Clock enable input for 2nd stage AREG
        .CEB2               ( i_ce              ), // 1-bit input: Clock enable input for 2nd stage BREG
        .CEINMODE           ( i_ce              ), // 1-bit input: Clock enable input for INMODEREG
        
        .CEM                ( r_ce[1]           ), // 1-bit input: Clock enable input for MREG
        .CEC                ( r_ce[1]           ), // 1-bit input: Clock enable input for CREG
        .CECARRYIN          ( r_ce[1]           ), // 1-bit input: Clock enable input for CARRYINREG
        .CECTRL             ( r_ce[1]           ), // 1-bit input: Clock enable input for OPMODEREG and CARRYINSELREG
        .CEALUMODE          ( r_ce[1]           ), // 1-bit input: Clock enable input for ALUMODE
        
        .CEP                ( r_ce[2]           ), // 1-bit input: Clock enable input for PREG
        
        .RSTA               ( i_rst             ), // 1-bit input: Reset input for AREG
        .RSTALLCARRYIN      ( i_rst             ), // 1-bit input: Reset input for CARRYINREG
        .RSTALUMODE         ( i_rst             ), // 1-bit input: Reset input for ALUMODEREG
        .RSTB               ( i_rst             ), // 1-bit input: Reset input for BREG
        .RSTC               ( i_rst             ), // 1-bit input: Reset input for CREG
        .RSTCTRL            ( i_rst             ), // 1-bit input: Reset input for OPMODEREG and CARRYINSELREG
        .RSTD               ( i_rst             ), // 1-bit input: Reset input for DREG and ADREG
        .RSTINMODE          ( i_rst             ), // 1-bit input: Reset input for INMODEREG
        .RSTM               ( i_rst             ), // 1-bit input: Reset input for MREG
        .RSTP               ( i_rst             ) // 1-bit input: Reset input for PREG
    );
    
    DSP48E1 #(
        // Feature Control Attributes: Data Path Selection
        .A_INPUT            ( "CASCADE"         ), // Selects A input source, "DIRECT" (A port) or "CASCADE" (ACIN port)
        .B_INPUT            ( "DIRECT"          ), // Selects B input source, "DIRECT" (B port) or "CASCADE" (BCIN port)
        .USE_DPORT          ( "FALSE"           ), // Select D port usage (TRUE or FALSE)
        .USE_MULT           ( "MULTIPLY"        ), // Select multiplier usage ("MULTIPLY", "DYNAMIC", or "NONE")
        .USE_SIMD           ( "ONE48"           ), // SIMD selection ("ONE48", "TWO24", "FOUR12")
        // Pattern Detector Attributes: Pattern Detection Configuration
        .AUTORESET_PATDET   ( "NO_RESET"        ), // "NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH"
        .MASK               ( 48'h3fffffffffff  ), // 48-bit mask value for pattern detect (1=ignore)
        .PATTERN            ( 48'h000000000000  ), // 48-bit pattern match for pattern detect
        .SEL_MASK           ( "MASK"            ), // "C", "MASK", "ROUNDING_MODE1", "ROUNDING_MODE2"
        .SEL_PATTERN        ( "PATTERN"         ), // Select pattern value ("PATTERN" or "C")
        .USE_PATTERN_DETECT ( "NO_PATDET"       ), // Enable pattern detect ("PATDET" or "NO_PATDET")
        // Register Control Attributes: Pipeline Register Configuration
        .ACASCREG           ( 1                 ), // Number of pipeline stages between A/ACIN and ACOUT (0, 1 or 2)
        .ADREG              ( 1                 ), // Number of pipeline stages for pre-adder (0 or 1)
        .ALUMODEREG         ( 1                 ), // Number of pipeline stages for ALUMODE (0 or 1)
        .AREG               ( 1                 ), // Number of pipeline stages for A (0, 1 or 2)
        .BCASCREG           ( 1                 ), // Number of pipeline stages between B/BCIN and BCOUT (0, 1 or 2)
        .BREG               ( 2                 ), // Number of pipeline stages for B (0, 1 or 2)
        .CARRYINREG         ( 1                 ), // Number of pipeline stages for CARRYIN (0 or 1)
        .CARRYINSELREG      ( 1                 ), // Number of pipeline stages for CARRYINSEL (0 or 1)
        .CREG               ( 1                 ), // Number of pipeline stages for C (0 or 1)
        .DREG               ( 1                 ), // Number of pipeline stages for D (0 or 1)
        .INMODEREG          ( 1                 ), // Number of pipeline stages for INMODE (0 or 1)
        .MREG               ( 1                 ), // Number of multiplier pipeline stages (0 or 1)
        .OPMODEREG          ( 1                 ), // Number of pipeline stages for OPMODE (0 or 1)
        .PREG               ( 1                 ) // Number of pipeline stages for P (0 or 1)
    ) DSP48E1_ALBH (
        // Cascade: 30-bit (each) output: Cascade Ports
        .ACOUT              (                   ), // 30-bit output: A port cascade output
        .BCOUT              (                   ), // 18-bit output: B port cascade output
        .CARRYCASCOUT       (                   ), // 1-bit output: Cascade carry output
        .MULTSIGNOUT        (                   ), // 1-bit output: Multiplier sign cascade output
        .PCOUT              (                   ), // 48-bit output: Cascade output
        // Control: 1-bit (each) output: Control Inputs/Status Bits
        .OVERFLOW           ( OVERFLOW_ALBH     ), // 1-bit output: Overflow in add/acc output
        .PATTERNBDETECT     (                   ), // 1-bit output: Pattern bar detect output
        .PATTERNDETECT      (                   ), // 1-bit output: Pattern detect output
        .UNDERFLOW          ( UNDERFLOW_ALBH    ), // 1-bit output: Underflow in add/acc output
        // Data: 4-bit (each) output: Data Ports
        .CARRYOUT           (                   ), // 4-bit output: Carry output
        .P                  ( P_ALBH            ), // 48-bit output: Primary data output
        // Cascade: 30-bit (each) input: Cascade Ports
        .ACIN               ( ACOUT_ALBL        ), // 30-bit input: A cascade data input
        .BCIN               ( 18'b0             ), // 18-bit input: B cascade input
        .CARRYCASCIN        ( 1'b0              ), // 1-bit input: Cascade carry input
        .MULTSIGNIN         ( 1'b0              ), // 1-bit input: Multiplier sign input
        .PCIN               ( PCOUT_ALBL        ), // 48-bit input: P cascade input
        // Control: 4-bit (each) input: Control Inputs/Status Bits
        .ALUMODE            ( ALUMODE_ALBH      ), // 4-bit input: ALU control input
        .CARRYINSEL         ( CARRYINSEL_ALBH   ), // 3-bit input: Carry select input
        .CLK                ( i_clk             ), // 1-bit input: Clock input
        .INMODE             ( INMODE_ALBH       ), // 5-bit input: INMODE control input
        .OPMODE             ( OPMODE_ALBH       ), // 7-bit input: Operation mode input
        // Data: 30-bit (each) input: Data Ports
        .A                  ( 30'b0             ), // 30-bit input: A data input
        .B                  ( BH                ), // 18-bit input: B data input
        .C                  ( 48'b0             ), // 48-bit input: C data input
        .CARRYIN            ( 1'b0              ), // 1-bit input: Carry input signal
        .D                  ( 25'b0             ), // 25-bit input: D data input
        // Reset/Clock Enable: 1-bit (each) input: Reset/Clock Enable Inputs
        .CEA1               ( 1'b0              ), // 1-bit input: Clock enable input for 1st stage AREG
        .CED                ( 1'b0              ), // 1-bit input: Clock enable input for DREG
        .CEAD               ( 1'b0              ), // 1-bit input: Clock enable input for ADREG
        
        .CEB1               ( i_ce              ), // 1-bit input: Clock enable input for 1st stage BREG
        
        .CEA2               ( r_ce[1]           ), // 1-bit input: Clock enable input for 2nd stage AREG
        .CEB2               ( r_ce[1]           ), // 1-bit input: Clock enable input for 2nd stage BREG
        .CEINMODE           ( r_ce[1]           ), // 1-bit input: Clock enable input for INMODEREG
        
        .CEM                ( r_ce[2]           ), // 1-bit input: Clock enable input for MREG
        .CEC                ( r_ce[2]           ), // 1-bit input: Clock enable input for CREG
        .CECARRYIN          ( r_ce[2]           ), // 1-bit input: Clock enable input for CARRYINREG
        .CECTRL             ( r_ce[2]           ), // 1-bit input: Clock enable input for OPMODEREG and CARRYINSELREG
        .CEALUMODE          ( r_ce[2]           ), // 1-bit input: Clock enable input for ALUMODE
        
        .CEP                ( r_ce[3]           ), // 1-bit input: Clock enable input for PREG
        
        .RSTA               ( i_rst             ), // 1-bit input: Reset input for AREG
        .RSTALLCARRYIN      ( i_rst             ), // 1-bit input: Reset input for CARRYINREG
        .RSTALUMODE         ( i_rst             ), // 1-bit input: Reset input for ALUMODEREG
        .RSTB               ( i_rst             ), // 1-bit input: Reset input for BREG
        .RSTC               ( i_rst             ), // 1-bit input: Reset input for CREG
        .RSTCTRL            ( i_rst             ), // 1-bit input: Reset input for OPMODEREG and CARRYINSELREG
        .RSTD               ( i_rst             ), // 1-bit input: Reset input for DREG and ADREG
        .RSTINMODE          ( i_rst             ), // 1-bit input: Reset input for INMODEREG
        .RSTM               ( i_rst             ), // 1-bit input: Reset input for MREG
        .RSTP               ( i_rst             ) // 1-bit input: Reset input for PREG
    );
    
    DSP48E1 #(
        // Feature Control Attributes: Data Path Selection
        .A_INPUT            ( "DIRECT"          ), // Selects A input source, "DIRECT" (A port) or "CASCADE" (ACIN port)
        .B_INPUT            ( "DIRECT"          ), // Selects B input source, "DIRECT" (B port) or "CASCADE" (BCIN port)
        .USE_DPORT          ( "FALSE"           ), // Select D port usage (TRUE or FALSE)
        .USE_MULT           ( "MULTIPLY"        ), // Select multiplier usage ("MULTIPLY", "DYNAMIC", or "NONE")
        .USE_SIMD           ( "ONE48"           ), // SIMD selection ("ONE48", "TWO24", "FOUR12")
        // Pattern Detector Attributes: Pattern Detection Configuration
        .AUTORESET_PATDET   ( "NO_RESET"        ), // "NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH"
        .MASK               ( 48'h3fffffffffff  ), // 48-bit mask value for pattern detect (1=ignore)
        .PATTERN            ( 48'h000000000000  ), // 48-bit pattern match for pattern detect
        .SEL_MASK           ( "MASK"            ), // "C", "MASK", "ROUNDING_MODE1", "ROUNDING_MODE2"
        .SEL_PATTERN        ( "PATTERN"         ), // Select pattern value ("PATTERN" or "C")
        .USE_PATTERN_DETECT ( "NO_PATDET"       ), // Enable pattern detect ("PATDET" or "NO_PATDET")
        // Register Control Attributes: Pipeline Register Configuration
        .ACASCREG           ( 2                 ), // Number of pipeline stages between A/ACIN and ACOUT (0, 1 or 2)
        .ADREG              ( 1                 ), // Number of pipeline stages for pre-adder (0 or 1)
        .ALUMODEREG         ( 1                 ), // Number of pipeline stages for ALUMODE (0 or 1)
        .AREG               ( 2                 ), // Number of pipeline stages for A (0, 1 or 2)
        .BCASCREG           ( 1                 ), // Number of pipeline stages between B/BCIN and BCOUT (0, 1 or 2)
        .BREG               ( 2                 ), // Number of pipeline stages for B (0, 1 or 2)
        .CARRYINREG         ( 1                 ), // Number of pipeline stages for CARRYIN (0 or 1)
        .CARRYINSELREG      ( 1                 ), // Number of pipeline stages for CARRYINSEL (0 or 1)
        .CREG               ( 0                 ), // Number of pipeline stages for C (0 or 1)
        .DREG               ( 1                 ), // Number of pipeline stages for D (0 or 1)
        .INMODEREG          ( 1                 ), // Number of pipeline stages for INMODE (0 or 1)
        .MREG               ( 1                 ), // Number of multiplier pipeline stages (0 or 1)
        .OPMODEREG          ( 1                 ), // Number of pipeline stages for OPMODE (0 or 1)
        .PREG               ( 1                 ) // Number of pipeline stages for P (0 or 1)
    ) DSP48E1_AHBL (
        // Cascade: 30-bit (each) output: Cascade Ports
        .ACOUT              ( ACOUT_AHBL        ), // 30-bit output: A port cascade output
        .BCOUT              (                   ), // 18-bit output: B port cascade output
        .CARRYCASCOUT       (                   ), // 1-bit output: Cascade carry output
        .MULTSIGNOUT        (                   ), // 1-bit output: Multiplier sign cascade output
        .PCOUT              ( PCOUT_AHBL        ), // 48-bit output: Cascade output
        // Control: 1-bit (each) output: Control Inputs/Status Bits
        .OVERFLOW           ( OVERFLOW_AHBL     ), // 1-bit output: Overflow in add/acc output
        .PATTERNBDETECT     (                   ), // 1-bit output: Pattern bar detect output
        .PATTERNDETECT      (                   ), // 1-bit output: Pattern detect output
        .UNDERFLOW          ( UNDERFLOW_AHBL    ), // 1-bit output: Underflow in add/acc output
        // Data: 4-bit (each) output: Data Ports
        .CARRYOUT           (                   ), // 4-bit output: Carry output
        .P                  ( P_AHBL            ), // 48-bit output: Primary data output
        // Cascade: 30-bit (each) input: Cascade Ports
        .ACIN               ( 30'b0             ), // 30-bit input: A cascade data input
        .BCIN               ( 18'b0             ), // 18-bit input: B cascade input
        .CARRYCASCIN        ( 1'b0              ), // 1-bit input: Cascade carry input
        .MULTSIGNIN         ( 1'b0              ), // 1-bit input: Multiplier sign input
        .PCIN               ( 48'b0             ), // 48-bit input: P cascade input
        // Control: 4-bit (each) input: Control Inputs/Status Bits
        .ALUMODE            ( ALUMODE_AHBL      ), // 4-bit input: ALU control input
        .CARRYINSEL         ( CARRYINSEL_AHBL   ), // 3-bit input: Carry select input
        .CLK                ( i_clk             ), // 1-bit input: Clock input
        .INMODE             ( INMODE_AHBL       ), // 5-bit input: INMODE control input
        .OPMODE             ( OPMODE_AHBL       ), // 7-bit input: Operation mode input
        // Data: 30-bit (each) input: Data Ports
        .A                  ( r_AH[1]           ), // 30-bit input: A data input
        .B                  ( r_BL[1]           ), // 18-bit input: B data input
        .C                  ( P_ALBH_TO_C_AHBL  ), // 48-bit input: C data input
        .CARRYIN            ( 1'b0              ), // 1-bit input: Carry input signal
        .D                  ( 25'b0             ), // 25-bit input: D data input
        // Reset/Clock Enable: 1-bit (each) input: Reset/Clock Enable Inputs
        .CED                ( 1'b0              ), // 1-bit input: Clock enable input for DREG
        .CEAD               ( 1'b0              ), // 1-bit input: Clock enable input for ADREG
        .CEC                ( 1'b0              ), // 1-bit input: Clock enable input for CREG
        
        .CEA1               ( r_ce[1]           ), // 1-bit input: Clock enable input for 1st stage AREG
        .CEB1               ( r_ce[1]           ), // 1-bit input: Clock enable input for 1st stage BREG
        
        .CEA2               ( r_ce[2]           ), // 1-bit input: Clock enable input for 2nd stage AREG
        .CEB2               ( r_ce[2]           ), // 1-bit input: Clock enable input for 2nd stage BREG
        .CEINMODE           ( r_ce[2]           ), // 1-bit input: Clock enable input for INMODEREG
        
        .CEM                ( r_ce[3]           ), // 1-bit input: Clock enable input for MREG
        .CECARRYIN          ( r_ce[3]           ), // 1-bit input: Clock enable input for CARRYINREG
        .CECTRL             ( r_ce[3]           ), // 1-bit input: Clock enable input for OPMODEREG and CARRYINSELREG
        .CEALUMODE          ( r_ce[3]           ), // 1-bit input: Clock enable input for ALUMODE
        
        .CEP                ( r_ce[4]           ), // 1-bit input: Clock enable input for PREG
        
        .RSTA               ( i_rst             ), // 1-bit input: Reset input for AREG
        .RSTALLCARRYIN      ( i_rst             ), // 1-bit input: Reset input for CARRYINREG
        .RSTALUMODE         ( i_rst             ), // 1-bit input: Reset input for ALUMODEREG
        .RSTB               ( i_rst             ), // 1-bit input: Reset input for BREG
        .RSTC               ( i_rst             ), // 1-bit input: Reset input for CREG
        .RSTCTRL            ( i_rst             ), // 1-bit input: Reset input for OPMODEREG and CARRYINSELREG
        .RSTD               ( i_rst             ), // 1-bit input: Reset input for DREG and ADREG
        .RSTINMODE          ( i_rst             ), // 1-bit input: Reset input for INMODEREG
        .RSTM               ( i_rst             ), // 1-bit input: Reset input for MREG
        .RSTP               ( i_rst             ) // 1-bit input: Reset input for PREG
    );
    
    DSP48E1 #(
        // Feature Control Attributes: Data Path Selection
        .A_INPUT            ( "CASCADE"         ), // Selects A input source, "DIRECT" (A port) or "CASCADE" (ACIN port)
        .B_INPUT            ( "DIRECT"          ), // Selects B input source, "DIRECT" (B port) or "CASCADE" (BCIN port)
        .USE_DPORT          ( "FALSE"           ), // Select D port usage (TRUE or FALSE)
        .USE_MULT           ( "MULTIPLY"        ), // Select multiplier usage ("MULTIPLY", "DYNAMIC", or "NONE")
        .USE_SIMD           ( "ONE48"           ), // SIMD selection ("ONE48", "TWO24", "FOUR12")
        // Pattern Detector Attributes: Pattern Detection Configuration
        .AUTORESET_PATDET   ( "NO_RESET"        ), // "NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH"
        .MASK               ( 48'h3fffffffffff  ), // 48-bit mask value for pattern detect (1=ignore)
        .PATTERN            ( 48'h000000000000  ), // 48-bit pattern match for pattern detect
        .SEL_MASK           ( "MASK"            ), // "C", "MASK", "ROUNDING_MODE1", "ROUNDING_MODE2"
        .SEL_PATTERN        ( "PATTERN"         ), // Select pattern value ("PATTERN" or "C")
        .USE_PATTERN_DETECT ( "NO_PATDET"       ), // Enable pattern detect ("PATDET" or "NO_PATDET")
        // Register Control Attributes: Pipeline Register Configuration
        .ACASCREG           ( 1                 ), // Number of pipeline stages between A/ACIN and ACOUT (0, 1 or 2)
        .ADREG              ( 1                 ), // Number of pipeline stages for pre-adder (0 or 1)
        .ALUMODEREG         ( 1                 ), // Number of pipeline stages for ALUMODE (0 or 1)
        .AREG               ( 1                 ), // Number of pipeline stages for A (0, 1 or 2)
        .BCASCREG           ( 1                 ), // Number of pipeline stages between B/BCIN and BCOUT (0, 1 or 2)
        .BREG               ( 2                 ), // Number of pipeline stages for B (0, 1 or 2)
        .CARRYINREG         ( 1                 ), // Number of pipeline stages for CARRYIN (0 or 1)
        .CARRYINSELREG      ( 1                 ), // Number of pipeline stages for CARRYINSEL (0 or 1)
        .CREG               ( 1                 ), // Number of pipeline stages for C (0 or 1)
        .DREG               ( 1                 ), // Number of pipeline stages for D (0 or 1)
        .INMODEREG          ( 1                 ), // Number of pipeline stages for INMODE (0 or 1)
        .MREG               ( 1                 ), // Number of multiplier pipeline stages (0 or 1)
        .OPMODEREG          ( 1                 ), // Number of pipeline stages for OPMODE (0 or 1)
        .PREG               ( 1                 ) // Number of pipeline stages for P (0 or 1)
    ) DSP48E1_AHBH (
        // Cascade: 30-bit (each) output: Cascade Ports
        .ACOUT              (                   ), // 30-bit output: A port cascade output
        .BCOUT              (                   ), // 18-bit output: B port cascade output
        .CARRYCASCOUT       (                   ), // 1-bit output: Cascade carry output
        .MULTSIGNOUT        (                   ), // 1-bit output: Multiplier sign cascade output
        .PCOUT              (                   ), // 48-bit output: Cascade output
        // Control: 1-bit (each) output: Control Inputs/Status Bits
        .OVERFLOW           ( OVERFLOW_AHBH     ), // 1-bit output: Overflow in add/acc output
        .PATTERNBDETECT     (                   ), // 1-bit output: Pattern bar detect output
        .PATTERNDETECT      (                   ), // 1-bit output: Pattern detect output
        .UNDERFLOW          ( UNDERFLOW_AHBH    ), // 1-bit output: Underflow in add/acc output
        // Data: 4-bit (each) output: Data Ports
        .CARRYOUT           (                   ), // 4-bit output: Carry output
        .P                  ( P_AHBH            ), // 48-bit output: Primary data output
        // Cascade: 30-bit (each) input: Cascade Ports
        .ACIN               ( ACOUT_AHBL        ), // 30-bit input: A cascade data input
        .BCIN               ( 18'b0             ), // 18-bit input: B cascade input
        .CARRYCASCIN        ( 1'b0              ), // 1-bit input: Cascade carry input
        .MULTSIGNIN         ( 1'b0              ), // 1-bit input: Multiplier sign input
        .PCIN               ( PCOUT_AHBL        ), // 48-bit input: P cascade input
        // Control: 4-bit (each) input: Control Inputs/Status Bits
        .ALUMODE            ( ALUMODE_AHBH      ), // 4-bit input: ALU control input
        .CARRYINSEL         ( CARRYINSEL_AHBH   ), // 3-bit input: Carry select input
        .CLK                ( i_clk             ), // 1-bit input: Clock input
        .INMODE             ( INMODE_AHBH       ), // 5-bit input: INMODE control input
        .OPMODE             ( OPMODE_AHBH       ), // 7-bit input: Operation mode input
        // Data: 30-bit (each) input: Data Ports
        .A                  ( 30'b0             ), // 30-bit input: A data input
        .B                  ( r_BH[2]           ), // 18-bit input: B data input
        .C                  ( C_AHBH[4]         ), // 48-bit input: C data input
        .CARRYIN            ( 1'b0              ), // 1-bit input: Carry input signal
        .D                  ( 25'b0             ), // 25-bit input: D data input
        // Reset/Clock Enable: 1-bit (each) input: Reset/Clock Enable Inputs
        .CEA1               ( 1'b0              ), // 1-bit input: Clock enable input for 1st stage AREG
        .CED                ( 1'b0              ), // 1-bit input: Clock enable input for DREG
        .CEAD               ( 1'b0              ), // 1-bit input: Clock enable input for ADREG
        
        .CEB1               ( r_ce[2]           ), // 1-bit input: Clock enable input for 1st stage BREG
        
        .CEA2               ( r_ce[3]           ), // 1-bit input: Clock enable input for 2nd stage AREG
        .CEB2               ( r_ce[3]           ), // 1-bit input: Clock enable input for 2nd stage BREG
        .CEINMODE           ( r_ce[3]           ), // 1-bit input: Clock enable input for INMODEREG
        
        .CEM                ( r_ce[4]           ), // 1-bit input: Clock enable input for MREG
        .CEC                ( r_ce[4]           ), // 1-bit input: Clock enable input for CREG
        .CECARRYIN          ( r_ce[4]           ), // 1-bit input: Clock enable input for CARRYINREG
        .CECTRL             ( r_ce[4]           ), // 1-bit input: Clock enable input for OPMODEREG and CARRYINSELREG
        .CEALUMODE          ( r_ce[4]           ), // 1-bit input: Clock enable input for ALUMODE
        
        .CEP                ( r_ce[5]           ), // 1-bit input: Clock enable input for PREG
        
        .RSTA               ( i_rst             ), // 1-bit input: Reset input for AREG
        .RSTALLCARRYIN      ( i_rst             ), // 1-bit input: Reset input for CARRYINREG
        .RSTALUMODE         ( i_rst             ), // 1-bit input: Reset input for ALUMODEREG
        .RSTB               ( i_rst             ), // 1-bit input: Reset input for BREG
        .RSTC               ( i_rst             ), // 1-bit input: Reset input for CREG
        .RSTCTRL            ( i_rst             ), // 1-bit input: Reset input for OPMODEREG and CARRYINSELREG
        .RSTD               ( i_rst             ), // 1-bit input: Reset input for DREG and ADREG
        .RSTINMODE          ( i_rst             ), // 1-bit input: Reset input for INMODEREG
        .RSTM               ( i_rst             ), // 1-bit input: Reset input for MREG
        .RSTP               ( i_rst             ) // 1-bit input: Reset input for PREG
    );
endmodule