[wip] sim model testing
authorDavid Shah <dave@ds0.me>
Thu, 8 Aug 2019 08:31:34 +0000 (09:31 +0100)
committerDavid Shah <dave@ds0.me>
Thu, 8 Aug 2019 08:31:34 +0000 (09:31 +0100)
Signed-off-by: David Shah <dave@ds0.me>
techlibs/xilinx/cells_sim.v
techlibs/xilinx/tests/.gitignore
techlibs/xilinx/tests/test_dsp_model.v [new file with mode: 0644]

index 7e7199f0b202c38d329aa93a33af8828e9d5d1fe..a6ab989267b6fd177b412ab7147c55a8f1fc40c3 100644 (file)
@@ -463,27 +463,10 @@ module DSP48E1 (
 
     initial begin
 `ifdef __ICARUS__
-        if (ACASCREG != 0)          $fatal(1, "Unsupported ACASCREG value");
-        if (ADREG != 0)             $fatal(1, "Unsupported ADREG value");
-        if (ALUMODEREG != 0)        $fatal(1, "Unsupported ALUMODEREG value");
-        if (AREG == 2)              $fatal(1, "Unsupported AREG value");
         if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value");
-        if (A_INPUT != "DIRECT")    $fatal(1, "Unsupported A_INPUT value");
-        if (BCASCREG != 0)          $fatal(1, "Unsupported BCASCREG value");
-        if (BREG == 2)              $fatal(1, "Unsupported BREG value");
-        if (B_INPUT != "DIRECT")    $fatal(1, "Unsupported B_INPUT value");
-        if (CARRYINREG != 0)        $fatal(1, "Unsupported CARRYINREG value");
-        if (CARRYINSELREG != 0)     $fatal(1, "Unsupported CARRYINSELREG value");
-        if (CREG != 0)              $fatal(1, "Unsupported CREG value");
-        if (DREG != 0)              $fatal(1, "Unsupported DREG value");
-        if (INMODEREG != 0)         $fatal(1, "Unsupported INMODEREG value");
-        if (MREG != 0)              $fatal(1, "Unsupported MREG value");
-        if (OPMODEREG != 0)         $fatal(1, "Unsupported OPMODEREG value");
         //if (PREG != 0)              $fatal(1, "Unsupported PREG value");
         if (SEL_MASK != "MASK")     $fatal(1, "Unsupported SEL_MASK value");
         if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value");
-        if (USE_DPORT != "FALSE")   $fatal(1, "Unsupported USE_DPORT value");
-        if (USE_MULT != "MULTIPLY") $fatal(1, "Unsupported USE_MULT value");
         if (USE_PATTERN_DETECT != "NO_PATDET") $fatal(1, "Unsupported USE_PATTERN_DETECT value");
         if (USE_SIMD != "ONE48")    $fatal(1, "Unsupported USE_SIMD value");
         if (IS_ALUMODE_INVERTED != 4'b0) $fatal(1, "Unsupported IS_ALUMODE_INVERTED value");
@@ -505,14 +488,14 @@ module DSP48E1 (
         else assign B_muxed = B;
     endgenerate
 
-    reg signed [29:0] Ar1, Ar2;
-    reg signed [24:0] Dr;
-    reg signed [17:0] Br1, Br2;
-    reg signed [47:0] Cr;
-    reg        [4:0]  INMODEr;
-    reg        [6:0]  OPMODEr;
-    reg        [3:0]  ALUMODEr;
-    reg        [2:0]  CARRYINSELr;
+    reg signed [29:0] Ar1 = 30'b0, Ar2 = 30'b0;
+    reg signed [24:0] Dr = 25'b0;
+    reg signed [17:0] Br1 = 18'b0, Br2 = 18'b0;
+    reg signed [47:0] Cr = 48'b0;
+    reg        [4:0]  INMODEr = 5'b0;
+    reg        [6:0]  OPMODEr = 7'b0;
+    reg        [3:0]  ALUMODEr = 4'b0;
+    reg        [2:0]  CARRYINSELr = 3'b0;
 
     generate
         // Configurable A register
@@ -594,7 +577,7 @@ module DSP48E1 (
     wire signed [24:0] Ar12_gated = INMODEr[1] ? 25'b0 : Ar12_muxed;
     wire signed [24:0] Dr_gated   = INMODEr[2] ? Dr : 25'b0;
     wire signed [24:0] AD_result  = INMODEr[3] ? (Dr_gated - Ar12_gated) : (Dr_gated + Ar12_gated);
-    reg  signed [24:0] ADr;
+    reg  signed [24:0] ADr = 25'b0;
 
     generate
         if (ADREG == 1) begin always @(posedge CLK) if (RSTD) ADr <= 25'b0; else if (CEAD) ADr <= AD_result; end
@@ -610,7 +593,7 @@ module DSP48E1 (
     endgenerate
 
     wire signed [42:0] M = A_MULT * B_MULT;
-    reg  signed [42:0] Mr;
+    reg  signed [42:0] Mr = 43'b0;
 
     // Multiplier result register
     generate
@@ -625,14 +608,16 @@ module DSP48E1 (
         // X multiplexer
         case (OPMODEr[1:0])
             2'b00: X = 48'b0;
-            2'b01: X = $signed(M);
+            2'b01: begin X = $signed(M);
 `ifdef __ICARUS__
                 if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01");
 `endif
-            2'b10: X = P;
+            end
+            2'b10: begin X = P;
 `ifdef __ICARUS__
                 if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10");
 `endif
+            end
             2'b11: X = $signed({Ar2, Br2});
             default: X = 48'bx;
         endcase
@@ -640,10 +625,11 @@ module DSP48E1 (
         // Y multiplexer
         case (OPMODEr[3:2])
             2'b00: Y = 48'b0;
-            2'b01: Y = 48'b0; // FIXME: more accurate partial product modelling?
+            2'b01: begin Y = 48'b0; // FIXME: more accurate partial product modelling?
 `ifdef __ICARUS__
                 if (OPMODEr[1:0] != 2'b01) $fatal(1, "OPMODEr[1:0] must be 2'b01 when OPMODEr[3:2] is 2'b01");
 `endif
+            end
             2'b10: Y = {48{1'b1}};
             2'b11: Y = C;
             default: Y = 48'bx;
@@ -653,26 +639,54 @@ module DSP48E1 (
         case (OPMODEr[6:4])
             3'b000: Z = 48'b0;
             3'b001: Z = PCIN;
-            3'b010: Z = P;
+            3'b010: begin Z = P;
 `ifdef __ICARUS__
                 if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010");
 `endif
+            end
             3'b011: Z = C;
-            3'b100: Z = P;
+            3'b100: begin Z = P;
 `ifdef __ICARUS__
                 if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100");
                 if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100");
 `endif
+            end
             3'b101: Z = $signed(PCIN[47:17]);
             3'b110: Z = $signed(P[47:17]);
             default: Z = 48'bx;
         endcase
     end
 
-    // ALU core
+    // Carry in
+    wire A24_xnor_B17d = A_MULT[24] ~^ B_MULT[17];
+    reg CARRYINr, A24_xnor_B17;
+    generate
+        if (CARRYINREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) CARRYINr <= 1'b0; else if (CECARRYIN) CARRYINr <= CARRYIN; end
+        else                 always @* CARRYINr = CARRYIN;
+
+        if (MREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) A24_xnor_B17 <= 1'b0; else if (CECARRYIN) A24_xnor_B17 <= A24_xnor_B17d; end
+        else                 always @* A24_xnor_B17 = A24_xnor_B17d;
+    endgenerate
 
-    wire alu_cin = 1'b0; // FIXME*
+    reg cin_muxed;
+
+    always @(*) begin
+        case (CARRYINSELr)
+            3'b000: cin_muxed = CARRYINr;
+            3'b001: cin_muxed = ~PCIN[47];
+            3'b010: cin_muxed = CARRYCASCIN;
+            3'b011: cin_muxed = PCIN[47];
+            3'b100: cin_muxed = CARRYCASCOUT;
+            3'b101: cin_muxed = ~P[47];
+            3'b110: cin_muxed = A24_xnor_B17;
+            3'b111: cin_muxed = P[47];
+            default: cin_muxed = 1'bx;
+        endcase
+    end
+
+    wire alu_cin = (ALUMODEr[3] || ALUMODEr[2]) ? 1'b0 : cin_muxed;
 
+    // ALU core
     wire [47:0] Z_muxinv = ALUMODEr[0] ? ~Z : Z;
     wire [47:0] xor_xyz = X ^ Y ^ Z_muxinv;
     wire [47:0] maj_xyz = (X & Y) | (X & Z) | (X & Y);
@@ -730,16 +744,11 @@ module DSP48E1 (
     endgenerate
 
     wire signed [47:0] Pd = ALUMODEr[1] ? ~alu_sum : alu_sum;
+    initial P = 48'b0;
     wire [3:0] CARRYOUTd = (ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out;
     wire CARRYCASCOUTd = ext_carry_out[3];
     wire MULTSIGNOUTd = Mr[42];
 
-    always @* begin
-`ifdef __ICARUS__
-        if (CARRYINSEL != 3'b000)   $fatal(1, "Unsupported CARRYINSEL value");
-`endif
-    end
-
     generate
         if (PREG == 1) begin
             always @(posedge CLK)
index 496b87461a7082c50b0f882f75ec5935c5ba3e8a..40d61cccec5a0c1c5f7661cc0955288d22d3f612 100644 (file)
@@ -4,3 +4,4 @@ bram1_[0-9]*/
 bram2.log
 bram2_syn.v
 bram2_tb
+dsp_work*/
\ No newline at end of file
diff --git a/techlibs/xilinx/tests/test_dsp_model.v b/techlibs/xilinx/tests/test_dsp_model.v
new file mode 100644 (file)
index 0000000..2ecaabf
--- /dev/null
@@ -0,0 +1,310 @@
+`timescale 1ns / 1ps
+
+module testbench;
+    parameter integer ACASCREG = 1;
+    parameter integer ADREG = 1;
+    parameter integer ALUMODEREG = 1;
+    parameter integer AREG = 1;
+    parameter AUTORESET_PATDET = "NO_RESET";
+    parameter A_INPUT = "DIRECT";
+    parameter integer BCASCREG = 1;
+    parameter integer BREG = 1;
+    parameter B_INPUT = "DIRECT";
+    parameter integer CARRYINREG = 1;
+    parameter integer CARRYINSELREG = 1;
+    parameter integer CREG = 1;
+    parameter integer DREG = 1;
+    parameter integer INMODEREG = 1;
+    parameter integer MREG = 1;
+    parameter integer OPMODEREG = 1;
+    parameter integer PREG = 1;
+    parameter SEL_MASK = "MASK";
+    parameter SEL_PATTERN = "PATTERN";
+    parameter USE_DPORT = "FALSE";
+    parameter USE_MULT = "MULTIPLY";
+    parameter USE_PATTERN_DETECT = "NO_PATDET";
+    parameter USE_SIMD = "ONE48";
+    parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
+    parameter [47:0] PATTERN = 48'h000000000000;
+    parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
+    parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
+    parameter [0:0] IS_CLK_INVERTED = 1'b0;
+    parameter [4:0] IS_INMODE_INVERTED = 5'b0;
+    parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
+
+       reg CLK;
+       reg CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL;
+       reg CED, CEINMODE, CEM, CEP;
+       reg RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP;
+       reg [29:0] A, ACIN;
+       reg [17:0] B, BCIN;
+       reg [47:0] C;
+       reg [24:0] D;
+       reg [47:0] PCIN;
+       reg [3:0] ALUMODE;
+       reg [2:0] CARRYINSEL;
+       reg [4:0] INMODE;
+       reg [6:0] OPMODE;
+       reg CARRYCASCIN, CARRYIN, MULTSIGNIN;
+
+    output [29:0] ACOUT, REF_ACOUT;
+    output [17:0] BCOUT, REF_BCOUT;
+    output CARRYCASCOUT, REF_CARRYCASCOUT;
+    output [3:0] CARRYOUT, REF_CARRYOUT;
+    output MULTSIGNOUT, REF_MULTSIGNOUT;
+    output OVERFLOW, REF_OVERFLOW;
+    output [47:0] P, REF_P;
+    output PATTERNBDETECT, REF_PATTERNBDETECT;
+    output PATTERNDETECT, REF_PATTERNDETECT;
+    output [47:0] PCOUT, REF_PCOUT;
+    output UNDERFLOW, REF_UNDERFLOW;
+
+       integer errcount = 0;
+
+       task clkcycle;
+               begin
+                       #5;
+                       CLK = ~CLK;
+                       #10;
+                       CLK = ~CLK;
+                       #2;
+
+                       if (REF_P !== P) begin
+                               $display("ERROR at %1t: REF_P=%b UUT_P=%b DIFF=%b", $time, REF_P, P, REF_P ^ P);
+                               errcount = errcount + 1;
+                       end
+                       if (REF_CARRYOUT !== CARRYOUT) begin
+                               $display("ERROR at %1t: REF_CARRYOUT=%b UUT_CARRYOUT=%b", $time, REF_CARRYOUT, CARRYOUT);
+                               errcount = errcount + 1;
+                       end
+                       #3;
+               end
+       endtask
+
+       reg config_valid = 0;
+       task drc;
+               config_valid = 1;
+               if (AREG != 2 && INMODE[0]) config_valid = 0;
+               if (BREG != 2 && INMODE[4]) config_valid = 0;
+               if ((OPMODE[3:2] == 2'b01) ^ (OPMODE[1:0] == 2'b01) == 1'b1) config_valid = 0;
+               if ((OPMODE[6:4] == 3'b010) && PREG != 1) config_valid = 0;
+               if ((OPMODE[6:4] == 3'b010) && (PREG != 1 || OPMODE[3:0] != 4'b1000)) config_valid = 0;
+       endtask
+
+       initial begin
+               $dumpfile("test_dsp_model.vcd");
+               $dumpvars(0, testbench);
+
+               #2;
+               CLK = 1'b0;
+               {CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL} = 9'b111111111;
+               {CED, CEINMODE, CEM, CEP} = 4'b1111;
+
+               {A, B, C, D} = 0;
+               {ACIN, BCIN, PCIN} = 0;
+               {ALUMODE, CARRYINSEL, INMODE} = 0;
+               {OPMODE, CARRYCASCIN, CARRYIN, MULTSIGNIN} = 0;
+
+               {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP} = ~0;
+               #5;
+               CLK = 1'b1;
+               #10;
+               CLK = 1'b0
+               #5;
+               CLK = 1'b1;
+               #10;
+               CLK = 1'b0;
+               {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP} = 0;
+
+               repeat (300) begin
+                       clkcycle;
+                       do begin
+                               A = $urandom;
+                               ACIN = $urandom;
+                               B = $urandom;
+                               BCIN = $urandom;
+                               C = {$urandom, $urandom};
+                               D = $urandom;
+                               PCIN = {$urandom, $urandom};
+
+                               {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTD, RSTINMODE, RSTM, RSTP} = $urandom & $urandom & $urandom;
+                               {ALUMODE, CARRYINSEL, INMODE} = $urandom & $urandom & $urandom;
+                               OPMODE = $urandom;
+                               {CARRYCASCIN, CARRYIN, MULTSIGNIN} = $urandom;
+                               drc;
+                       end while (!config_valid);
+               end
+
+               if (errcount == 0) begin
+                       $display("All tests passed.");
+                       $finish;
+               end else begin
+                       $display("Caught %1d errors.", errcount);
+                       $stop;
+               end
+       end
+
+       DSP48E1 #(
+               .ACASCREG           (ACASCREG),
+               .ADREG              (ADREG),
+               .ALUMODEREG         (ALUMODEREG),
+               .AREG               (AREG),
+               .AUTORESET_PATDET   (AUTORESET_PATDET),
+               .A_INPUT            (A_INPUT),
+               .BCASCREG           (BCASCREG),
+               .BREG               (BREG),
+               .B_INPUT            (B_INPUT),
+               .CARRYINREG         (CARRYINREG),
+               .CARRYINSELREG      (CARRYINSELREG),
+               .CREG               (CREG),
+               .DREG               (DREG),
+               .INMODEREG          (INMODEREG),
+               .MREG               (MREG),
+               .OPMODEREG          (OPMODEREG),
+               .PREG               (PREG),
+               .SEL_MASK           (SEL_MASK),
+               .SEL_PATTERN        (SEL_PATTERN),
+               .USE_DPORT          (USE_DPORT),
+               .USE_MULT           (USE_MULT),
+               .USE_PATTERN_DETECT (USE_PATTERN_DETECT),
+               .USE_SIMD           (USE_SIMD),
+               .MASK               (MASK),
+               .PATTERN            (PATTERN),
+               .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED),
+               .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED),
+               .IS_CLK_INVERTED    (IS_CLK_INVERTED),
+               .IS_INMODE_INVERTED (IS_INMODE_INVERTED),
+               .IS_OPMODE_INVERTED (IS_OPMODE_INVERTED)
+       ) ref (
+               .ACOUT         (REF_ACOUT),
+               .BCOUT         (REF_BCOUT),
+               .CARRYCASCOUT  (REF_CARRYCASCOUT),
+               .CARRYOUT      (REF_CARRYOUT),
+               .MULTSIGNOUT   (REF_MULTSIGNOUT),
+               .OVERFLOW      (REF_OVERFLOW),
+               .P             (REF_P),
+               .PATTERNBDETECT(REF_PATTERNBDETECT),
+               .PATTERNDETECT (REF_PATTERNDETECT),
+               .PCOUT         (REF_PCOUT),
+               .UNDERFLOW     (REF_UNDERFLOW),
+               .A             (A),
+               .ACIN          (ACIN),
+               .ALUMODE       (ALUMODE),
+               .B             (B),
+               .BCIN          (BCIN),
+               .C             (C),
+               .CARRYCASCIN   (CARRYCASCIN),
+               .CEA1          (CEA1),
+               .CEA2          (CEA2),
+               .CEAD          (CEAD),
+               .CEALUMODE     (CEALUMODE),
+               .CEB1          (CEB1),
+               .CEB2          (CEB2),
+               .CEC           (CEC),
+               .CECARRYIN     (CECARRYIN),
+               .CECTRL        (CECTRL),
+               .CED           (CED),
+               .CEINMODE      (CEINMODE),
+               .CEM           (CEM),
+               .CEP           (CEP),
+               .CLK           (CLK),
+               .D             (D),
+               .INMODE        (INMODE),
+               .MULTSIGNIN    (MULTSIGNIN),
+               .OPMODE        (OPMODE),
+               .PCIN          (PCIN),
+               .RSTA          (RSTA),
+               .RSTALLCARRYIN (RSTALLCARRYIN),
+               .RSTALUMODE    (RSTALUMODE),
+               .RSTB          (RSTB),
+               .RSTC          (RSTC),
+               .RSTCTRL       (RSTCTRL),
+               .RSTD          (RSTD),
+               .RSTINMODE     (RSTINMODE),
+               .RSTM          (RSTM),
+               .RSTP          (RSTP)
+       );
+
+       DSP48E1_UUT #(
+               .ACASCREG           (ACASCREG),
+               .ADREG              (ADREG),
+               .ALUMODEREG         (ALUMODEREG),
+               .AREG               (AREG),
+               .AUTORESET_PATDET   (AUTORESET_PATDET),
+               .A_INPUT            (A_INPUT),
+               .BCASCREG           (BCASCREG),
+               .BREG               (BREG),
+               .B_INPUT            (B_INPUT),
+               .CARRYINREG         (CARRYINREG),
+               .CARRYINSELREG      (CARRYINSELREG),
+               .CREG               (CREG),
+               .DREG               (DREG),
+               .INMODEREG          (INMODEREG),
+               .MREG               (MREG),
+               .OPMODEREG          (OPMODEREG),
+               .PREG               (PREG),
+               .SEL_MASK           (SEL_MASK),
+               .SEL_PATTERN        (SEL_PATTERN),
+               .USE_DPORT          (USE_DPORT),
+               .USE_MULT           (USE_MULT),
+               .USE_PATTERN_DETECT (USE_PATTERN_DETECT),
+               .USE_SIMD           (USE_SIMD),
+               .MASK               (MASK),
+               .PATTERN            (PATTERN),
+               .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED),
+               .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED),
+               .IS_CLK_INVERTED    (IS_CLK_INVERTED),
+               .IS_INMODE_INVERTED (IS_INMODE_INVERTED),
+               .IS_OPMODE_INVERTED (IS_OPMODE_INVERTED)
+       ) uut (
+               .ACOUT         (ACOUT),
+               .BCOUT         (BCOUT),
+               .CARRYCASCOUT  (CARRYCASCOUT),
+               .CARRYOUT      (CARRYOUT),
+               .MULTSIGNOUT   (MULTSIGNOUT),
+               .OVERFLOW      (OVERFLOW),
+               .P             (P),
+               .PATTERNBDETECT(PATTERNBDETECT),
+               .PATTERNDETECT (PATTERNDETECT),
+               .PCOUT         (PCOUT),
+               .UNDERFLOW     (UNDERFLOW),
+               .A             (A),
+               .ACIN          (ACIN),
+               .ALUMODE       (ALUMODE),
+               .B             (B),
+               .BCIN          (BCIN),
+               .C             (C),
+               .CARRYCASCIN   (CARRYCASCIN),
+               .CEA1          (CEA1),
+               .CEA2          (CEA2),
+               .CEAD          (CEAD),
+               .CEALUMODE     (CEALUMODE),
+               .CEB1          (CEB1),
+               .CEB2          (CEB2),
+               .CEC           (CEC),
+               .CECARRYIN     (CECARRYIN),
+               .CECTRL        (CECTRL),
+               .CED           (CED),
+               .CEINMODE      (CEINMODE),
+               .CEM           (CEM),
+               .CEP           (CEP),
+               .CLK           (CLK),
+               .D             (D),
+               .INMODE        (INMODE),
+               .MULTSIGNIN    (MULTSIGNIN),
+               .OPMODE        (OPMODE),
+               .PCIN          (PCIN),
+               .RSTA          (RSTA),
+               .RSTALLCARRYIN (RSTALLCARRYIN),
+               .RSTALUMODE    (RSTALUMODE),
+               .RSTB          (RSTB),
+               .RSTC          (RSTC),
+               .RSTCTRL       (RSTCTRL),
+               .RSTD          (RSTD),
+               .RSTINMODE     (RSTINMODE),
+               .RSTM          (RSTM),
+               .RSTP          (RSTP)
+       );
+
+
+endmodule