Multiplicador complejo Xilinx DSP48 Single Slice 18x18

1

Estoy escribiendo un código verilog para el multiplicador complejo 18x18 utilizando la implementación de un solo segmento DSP48 en Vertex 4. Aquí está mi código

module SS_CM_18x18(Areal,Aimag,Breal,Bimag,Clk,Rst,Preal,Pimag);
input Clk,Rst;
input [17:0]Areal,Aimag,Breal,Bimag;
output [47:0]Preal,Pimag;

reg [47:0]Preal,Pimag;
reg [17:0]Areal_Reg,Aimag_Reg,Breal_Reg,Bimag_Reg;
wire [17:0]Areal_Wire,Aimag_Wire,Breal_Wire,Bimag_Wire;
reg [17:0]I,Q;
wire [47:0]POut;
reg [47:0]POut_Reg1;
reg [1:0]Count;
reg [6:0]OPMODE;
reg Subtract;

always @(posedge Clk or posedge Rst)
    begin
        if (Rst)
            Count<=2'b11;
        else if (Count<2'b11)
            Count<=Count+1;
        else
            Count<=2'b0;
    end

always @(posedge Clk or posedge Rst)
    begin
        if (Rst)
            begin
                Areal_Reg<=18'b0;
                Aimag_Reg<=18'b0;
                Breal_Reg<=18'b0;
                Aimag_Reg<=18'b0;
            end
        else if(Count==2'b00)
            begin
                Areal_Reg<=Areal;
                Aimag_Reg<=Aimag;
                Breal_Reg<=Breal;
                Aimag_Reg<=Bimag;
            end
        else
            begin
                Areal_Reg<=Areal_Reg;
                Aimag_Reg<=Aimag_Reg;
                Breal_Reg<=Breal_Reg;
                Aimag_Reg<=Bimag_Reg;
            end
    end

assign Areal_Wire=Areal_Reg;
assign Aimag_Wire=Aimag_Reg;
assign Breal_Wire=Breal_Reg;
assign Bimag_Wire=Bimag_Reg;

always @(posedge Clk or posedge Rst)
    begin
        if (Rst)
            begin
                I<=18'b0;
                Q<=18'b0;
                OPMODE<=7'b0;
                Subtract<=1'b0;
            end
        else
            begin
                case(Count)
                    2'd0:   begin
                                I<=Areal_Wire;
                                Q<=Breal_Wire;
                                OPMODE<=7'b0000101;
                                Subtract<=1'b0;
                            end
                    2'd1:   begin
                                I<=Aimag_Wire;
                                Q<=Bimag_Wire;
                                OPMODE<=7'b0100101;
                                Subtract<=1'b1;
                            end
                    2'd2:   begin
                                I<=Areal_Wire;
                                Q<=Bimag_Wire;
                                OPMODE<=7'b0000101;
                                Subtract<=1'b0;
                            end
                    2'd3:   begin
                                I<=Aimag_Wire;
                                Q<=Breal_Wire;
                                OPMODE<=7'b0100101;
                                Subtract<=1'b0;
                            end
                endcase
            end
    end

// DSP48: DSP Function Block
//        Virtex-4
// Xilinx HDL Language Template, version 13.4

DSP48 #(
  .AREG(0),           // Number of pipeline registers on the A input, 0, 1 or 2
  .BREG(0),           // Number of pipeline registers on the B input, 0, 1 or 2
  .B_INPUT("DIRECT"), // B input DIRECT from fabric or CASCADE from another DSP48
  .CARRYINREG(0),     // Number of pipeline registers for the CARRYIN input, 0 or 1
  .CARRYINSELREG(0),  // Number of pipeline registers for the CARRYINSEL, 0 or 1
  .CREG(0),           // Number of pipeline registers on the C input, 0 or 1
  .LEGACY_MODE("MULT18X18"), // Backward compatibility, NONE, MULT18X18 or MULT18X18S
  .MREG(0),           // Number of multiplier pipeline registers, 0 or 1
  .OPMODEREG(0),      // Number of pipeline regsiters on OPMODE input, 0 or 1
  .PREG(1),           // Number of pipeline registers on the P output, 0 or 1
  .SUBTRACTREG(0)     // Number of pipeline registers on the SUBTRACT input, 0 or 1
   )  
 DSP48_inst1 (
      .BCOUT(),  // 18-bit B cascade output
      .P(POut),          // 48-bit product output
      .PCOUT(),  // 48-bit cascade output
      .A(I),          // 18-bit A data input
      .B(Q),          // 18-bit B data input
      .BCIN(18'd0),    // 18-bit B cascade input
      .C(48'd0),          // 48-bit cascade input
      .CARRYIN(1'd0), // Carry input signal
      .CARRYINSEL(2'd0), // 2-bit carry input select
      .CEA(1'b1),      // A data clock enable input
      .CEB(1'b1),      // B data clock enable input
      .CEC(1'b0),      // C data clock enable input
      .CECARRYIN(1'b0), // CARRYIN clock enable input
      .CECINSUB(1'b1), // CINSUB clock enable input
      .CECTRL(1'b0), // Clock Enable input for CTRL regsiters
      .CEM(1'b1),       // Clock Enable input for multiplier regsiters
      .CEP(1'b1),       // Clock Enable input for P regsiters
      .CLK(Clk),       // Clock input
      .OPMODE(OPMODE), // 7-bit operation mode input
      .PCIN(48'b0),     // 48-bit PCIN input 
      .RSTA(Rst),     // Reset input for A pipeline registers
      .RSTB(Rst),     // Reset input for B pipeline registers
      .RSTC(Rst),     // Reset input for C pipeline registers
      .RSTCARRYIN(Rst), // Reset input for CARRYIN registers
      .RSTCTRL(Rst), // Reset input for CTRL registers
      .RSTM(Rst), // Reset input for multiplier registers
      .RSTP(Rst), // Reset input for P pipeline registers
      .SUBTRACT(Subtract) // SUBTRACT input
   );

   // End of DSP48_inst instantiation

always @(posedge Clk or posedge Rst)
    begin
        if (Rst)
            POut_Reg1<=48'b0;
        else
            POut_Reg1<=POut;
    end
always @(posedge Clk or posedge Rst)
    begin
        if (Rst)
            begin
                Preal<=48'b0;
                Pimag<=48'b0;
            end
        else if (Count==2'b00)
            Preal<=POut_Reg1;
        else if (Count==2'd10)
            Pimag<=POut_Reg1;
        else
            begin
                Preal<=Preal;
                Pimag<=Pimag;
            end
    end

endmodule  

El banco de pruebas para el programa es

module Test_SS_CM_18x18;

    // Inputs
reg [17:0] Areal;
reg [17:0] Aimag;
reg [17:0] Breal;
reg [17:0] Bimag;
reg Clk;
reg Rst;

// Outputs
wire [47:0] Preal;
wire [47:0] Pimag;

// Instantiate the Unit Under Test (UUT)
SS_CM_18x18 uut1 (
    .Areal(Areal), 
    .Aimag(Aimag), 
    .Breal(Breal), 
    .Bimag(Bimag), 
    .Clk(Clk), 
    .Rst(Rst), 
    .Preal(Preal), 
    .Pimag(Pimag)
);

initial begin
    // Initialize Inputs
    Areal = 0;
    Aimag = 0;
    Breal = 0;
    Bimag = 0;
    Clk = 0;
    Rst = 0;

    // Wait 100 ns for global reset to finish
    #105;
   Rst=1;
    #10 Rst = 0;         
    // Add stimulus here
    Areal=18'd1;
    Aimag=18'd1;
    Breal=18'd1;
    Bimag=18'd1;
end
always #5 Clk=~Clk;      
endmodule  

No obtengo la salida correcta. ¿Alguien puede decirme dónde estoy cometiendo un error en código / concepto? La salida va a 0 después de 3 clk ciclos & luego 3 ciclos de clk después de restablecer, pasa al estado de alta impedancia

    
pregunta KharoBangdo

1 respuesta

1

Un problema que veo con su código es que carga I y Q en el primer ciclo ( Count == 0 ) desde los registros de la tubería en lugar de directamente desde las entradas. Dado que los registros de la tubería se están cargando en ese mismo reloj, el multiplicador no obtendrá lo que usted espera.

Aquí hay una versión de su módulo con ese problema solucionado, y muchos otros cruces extraños eliminados:

module SS_CM_18x18 (
  Areal,
  Aimag,
  Breal,
  Bimag,
  Clk,
  Rst,
  Preal,
  Pimag
);

  input         Clk, Rst;
  input  [17:0] Areal, Aimag, Breal, Bimag;
  output [47:0] Preal, Pimag;

  reg    [47:0] Preal, Pimag;
  reg    [17:0] Areal_Reg, Aimag_Reg, Breal_Reg, Bimag_Reg;
  reg    [17:0] I, Q;
  wire   [47:0] POut;
  reg    [47:0] POut_Reg1;
  reg     [1:0] Count;
  reg     [6:0] OPMODE;
  reg           Subtract;

  always @(posedge Clk or posedge Rst) begin
    if (Rst) Count <= 2'b11;
    else if (Count<2'b11) Count <= Count+1;
    else Count <= 2'b0;
  end

  always @(posedge Clk or posedge Rst) begin
    if (Rst) begin
      Areal_Reg <= 18'b0;
      Aimag_Reg <= 18'b0;
      Breal_Reg <= 18'b0;
      Aimag_Reg <= 18'b0;
    end else if (Count == 2'b00) begin
      Areal_Reg <= Areal;
      Aimag_Reg <= Aimag;
      Breal_Reg <= Breal;
      Aimag_Reg <= Bimag;
    end
  end

  always @(posedge Clk or posedge Rst) begin
    if (Rst) begin
      I <= 18'b0;
      Q <= 18'b0;
      OPMODE <= 7'b0;
      Subtract <= 1'b0;
    end else begin
      case (Count)

        2'd0: begin
          I <= Areal;           // direct from input
          Q <= Breal;           // direct from input
          OPMODE <= 7'b0000101;
          Subtract <= 1'b0;
        end

        2'd1: begin
          I <= Aimag_Reg;
          Q <= Bimag_Reg;
          OPMODE <= 7'b0100101;
          Subtract <= 1'b1;
        end

        2'd2: begin
          I <= Areal_Reg;
          Q <= Bimag_Reg;
          OPMODE <= 7'b0000101;
          Subtract <= 1'b0;
        end

        2'd3: begin
          I <= Aimag_Reg;
          Q <= Breal_Reg;
          OPMODE <= 7'b0100101;
          Subtract <= 1'b0;
        end
      endcase
    end
  end

  // DSP48: DSP Function Block
  //        Virtex-4
  // Xilinx HDL Language Template, version 13.4

  DSP48 #(
    .AREG(0),           // Number of pipeline registers on the A input, 0, 1 or 2
    .BREG(0),           // Number of pipeline registers on the B input, 0, 1 or 2
    .B_INPUT("DIRECT"), // B input DIRECT from fabric or CASCADE from another DSP48
    .CARRYINREG(0),     // Number of pipeline registers for the CARRYIN input, 0 or 1
    .CARRYINSELREG(0),  // Number of pipeline registers for the CARRYINSEL, 0 or 1
    .CREG(0),           // Number of pipeline registers on the C input, 0 or 1
    .LEGACY_MODE("MULT18X18"), // Backward compatibility, NONE, MULT18X18 or MULT18X18S
    .MREG(0),           // Number of multiplier pipeline registers, 0 or 1
    .OPMODEREG(0),      // Number of pipeline regsiters on OPMODE input, 0 or 1
    .PREG(1),           // Number of pipeline registers on the P output, 0 or 1
    .SUBTRACTREG(0)     // Number of pipeline registers on the SUBTRACT input, 0 or 1
  ) DSP48_inst1 (
    .BCOUT      (),             // 18-bit B cascade output
    .P          (POut),         // 48-bit product output
    .PCOUT      (),             // 48-bit cascade output
    .A          (I),            // 18-bit A data input
    .B          (Q),            // 18-bit B data input
    .BCIN       (18'd0),        // 18-bit B cascade input
    .C          (48'd0),        // 48-bit cascade input
    .CARRYIN    (1'd0),         // Carry input signal
    .CARRYINSEL (2'd0),         // 2-bit carry input select
    .CEA        (1'b1),         // A data clock enable input
    .CEB        (1'b1),         // B data clock enable input
    .CEC        (1'b0),         // C data clock enable input
    .CECARRYIN  (1'b0),         // CARRYIN clock enable input
    .CECINSUB   (1'b1),         // CINSUB clock enable input
    .CECTRL     (1'b1),         // Clock Enable input for CTRL regsiters
    .CEM        (1'b1),         // Clock Enable input for multiplier regsiters
    .CEP        (1'b1),         // Clock Enable input for P regsiters
    .CLK        (Clk),          // Clock input
    .OPMODE     (OPMODE),       // 7-bit operation mode input
    .PCIN       (48'b0),        // 48-bit PCIN input
    .RSTA       (Rst),          // Reset input for A pipeline registers
    .RSTB       (Rst),          // Reset input for B pipeline registers
    .RSTC       (Rst),          // Reset input for C pipeline registers
    .RSTCARRYIN (Rst),          // Reset input for CARRYIN registers
    .RSTCTRL    (Rst),          // Reset input for CTRL registers
    .RSTM       (Rst),          // Reset input for multiplier registers
    .RSTP       (Rst),          // Reset input for P pipeline registers
    .SUBTRACT   (Subtract)      // SUBTRACT input
  );

  // End of DSP48_inst instantiation

  always @(posedge Clk or posedge Rst) begin
    if (Rst) POut_Reg1 <= 48'b0;
    else POut_Reg1 <= POut;
  end

  always @(posedge Clk or posedge Rst) begin
    if (Rst) begin
      Preal <= 48'b0;
      Pimag <= 48'b0;
    end else if (Count == 2'b00) Preal <= POut_Reg1;
    else if (Count == 2'd10) Pimag <= POut_Reg1;
  end

endmodule

Además, no estoy totalmente familiarizado con los detalles de DPS48, pero ¿realmente querías empatar CECTRL bajo? Lo he cambiado a alto.

    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas