Add pattern detection support for DSP48E1 model, check against vendor
authorEddie Hung <eddie@fpgeh.com>
Wed, 18 Sep 2019 17:45:04 +0000 (10:45 -0700)
committerEddie Hung <eddie@fpgeh.com>
Wed, 18 Sep 2019 17:45:04 +0000 (10:45 -0700)
techlibs/xilinx/cells_sim.v
techlibs/xilinx/tests/test_dsp_model.sh
techlibs/xilinx/tests/test_dsp_model.v

index ed421f85eb543c19a024470abd31791144f013f7..2f586e798741f9b82853a12e9592b8fef86f9cd8 100644 (file)
@@ -498,8 +498,8 @@ module DSP48E1 (
     output reg MULTSIGNOUT,
     output OVERFLOW,
     output reg signed [47:0] P,
-    output PATTERNBDETECT,
-    output PATTERNDETECT,
+    output reg PATTERNBDETECT,
+    output reg PATTERNDETECT,
     output [47:0] PCOUT,
     output UNDERFLOW,
     input signed [29:0] A,
@@ -575,10 +575,8 @@ module DSP48E1 (
     initial begin
 `ifdef __ICARUS__
         if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET 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_PATTERN_DETECT != "NO_PATDET") $fatal(1, "Unsupported USE_PATTERN_DETECT value");
         if (USE_SIMD != "ONE48" && USE_SIMD != "TWO24" && USE_SIMD != "FOUR12")    $fatal(1, "Unsupported USE_SIMD value");
         if (IS_ALUMODE_INVERTED != 4'b0) $fatal(1, "Unsupported IS_ALUMODE_INVERTED value");
         if (IS_CARRYIN_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CARRYIN_INVERTED value");
@@ -897,4 +895,45 @@ module DSP48E1 (
 
     assign PCOUT = P;
 
+    generate
+        wire PATTERNDETECTd, PATTERNBDETECTd;
+
+        if (USE_PATTERN_DETECT == "PATDET") begin
+            // TODO: Support SEL_PATTERN != "PATTERN" and SEL_MASK != "MASK
+            assign PATTERNDETECTd = &(~(Pd ^ PATTERN) | MASK);
+            assign PATTERNBDETECTd = &((Pd ^ PATTERN) | MASK);
+        end else begin
+            assign PATTERNDETECTd = 1'b1;
+            assign PATTERNBDETECTd = 1'b1;
+        end
+
+        if (PREG == 1) begin
+            reg PATTERNDETECTPAST, PATTERNBDETECTPAST;
+            initial PATTERNDETECT = 1'b0;
+            initial PATTERNBDETECT = 1'b0;
+            initial PATTERNDETECTPAST = 1'b0;
+            initial PATTERNBDETECTPAST = 1'b0;
+            always @(posedge CLK)
+                if (RSTP) begin
+                    PATTERNDETECT <= 1'b0;
+                    PATTERNBDETECT <= 1'b0;
+                    PATTERNDETECTPAST <= 1'b0;
+                    PATTERNBDETECTPAST <= 1'b0;
+                end else if (CEP) begin
+                    PATTERNDETECT <= PATTERNDETECTd;
+                    PATTERNBDETECT <= PATTERNBDETECTd;
+                    PATTERNDETECTPAST <= PATTERNDETECT;
+                    PATTERNBDETECTPAST <= PATTERNBDETECT;
+                end
+            assign OVERFLOW = &{PATTERNDETECTPAST, ~PATTERNBDETECT, ~PATTERNDETECT};
+            assign UNDERFLOW = &{PATTERNBDETECTPAST, ~PATTERNBDETECT, ~PATTERNDETECT};
+        end else begin
+            always @* begin
+                PATTERNDETECT = PATTERNDETECTd;
+                PATTERNBDETECT = PATTERNBDETECTd;
+            end
+            assign OVERFLOW = 1'bx, UNDERFLOW = 1'bx;
+        end
+    endgenerate
+
 endmodule
index 2acd97eb47d1c7326d807bb9ebdccffe83492691..ae925c402186857e434a3a64823c9520e7a7c121 100644 (file)
@@ -4,10 +4,10 @@ sed 's/DSP48E1/DSP48E1_UUT/; /DSP48E1_UUT/,/endmodule/ p; d;' < ../cells_sim.v >
 if [ ! -f "test_dsp_model_ref.v" ]; then
        cat /opt/Xilinx/Vivado/2019.1/data/verilog/src/unisims/DSP48E1.v > test_dsp_model_ref.v
 fi
-for tb in simd24_preadd_noreg_nocasc simd12_preadd_noreg_nocasc \
+for tb in macc_overflow_underflow \
+    simd24_preadd_noreg_nocasc simd12_preadd_noreg_nocasc \
     mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_nocasc  \
-       mult_allreg_preadd_nocasc mult_noreg_preadd_nocasc mult_inreg_preadd_nocasc \
-       
+       mult_allreg_preadd_nocasc mult_noreg_preadd_nocasc mult_inreg_preadd_nocasc
 do
        iverilog -s $tb -s glbl -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v /opt/Xilinx/Vivado/2019.1/data/verilog/src/glbl.v
        vvp -N ./test_dsp_model
index 04d5b26ab5b7a30d047e6761ced42f379a119a28..db012f1694fcda541b90e7e916d256c86ad9a40c 100644 (file)
@@ -81,6 +81,26 @@ module testbench;
                                errcount = errcount + 1;
                                ERROR_FLAG = 1;
                        end
+                       if (REF_PATTERNDETECT !== PATTERNDETECT) begin
+                               $display("ERROR at %1t: REF_PATTERNDETECT=%b UUT_PATTERNDETECT=%b DIFF=%b REF_P=%b P=%b", $time, REF_PATTERNDETECT, PATTERNDETECT, REF_PATTERNDETECT ^ PATTERNDETECT, REF_P, P);
+                               errcount = errcount + 1;
+                               ERROR_FLAG = 1;
+                       end
+                       if (REF_PATTERNBDETECT !== PATTERNBDETECT) begin
+                               $display("ERROR at %1t: REF_PATTERNBDETECT=%b UUT_PATTERNBDETECT=%b DIFF=%b", $time, REF_PATTERNBDETECT, PATTERNBDETECT, REF_PATTERNBDETECT ^ PATTERNBDETECT);
+                               errcount = errcount + 1;
+                               ERROR_FLAG = 1;
+                       end
+                       if (REF_OVERFLOW !== OVERFLOW) begin
+                               $display("ERROR at %1t: REF_OVERFLOW=%b UUT_OVERFLOW=%b DIFF=%b", $time, REF_OVERFLOW, OVERFLOW, REF_OVERFLOW ^ OVERFLOW);
+                               errcount = errcount + 1;
+                               ERROR_FLAG = 1;
+                       end
+                       if (REF_UNDERFLOW !== UNDERFLOW) begin
+                               $display("ERROR at %1t: REF_UNDERFLOW=%b UUT_UNDERFLOW=%b DIFF=%b", $time, REF_UNDERFLOW, UNDERFLOW, REF_UNDERFLOW ^ UNDERFLOW);
+                               errcount = errcount + 1;
+                               ERROR_FLAG = 1;
+                       end
                        #3;
                end
        endtask
@@ -594,4 +614,39 @@ module simd24_preadd_noreg_nocasc;
                .IS_INMODE_INVERTED (5'b0),
                .IS_OPMODE_INVERTED (7'b0)
        ) testbench ();
-endmodule
\ No newline at end of file
+endmodule
+
+module macc_overflow_underflow;
+       testbench #(
+               .ACASCREG           (0),
+               .ADREG              (0),
+               .ALUMODEREG         (0),
+               .AREG               (0),
+               .AUTORESET_PATDET   ("NO_RESET"),
+               .A_INPUT            ("DIRECT"),
+               .BCASCREG           (0),
+               .BREG               (0),
+               .B_INPUT            ("DIRECT"),
+               .CARRYINREG         (0),
+               .CARRYINSELREG      (0),
+               .CREG               (0),
+               .DREG               (0),
+               .INMODEREG          (0),
+               .MREG               (0),
+               .OPMODEREG          (0),
+               .PREG               (1),
+               .SEL_MASK           ("MASK"),
+               .SEL_PATTERN        ("PATTERN"),
+               .USE_DPORT          ("FALSE"),
+               .USE_MULT           ("DYNAMIC"),
+               .USE_PATTERN_DETECT ("PATDET"),
+               .USE_SIMD           ("ONE48"),
+               .MASK               (48'h1FFFFFFFFFFF),
+               .PATTERN            (48'h000000000000),
+               .IS_ALUMODE_INVERTED(4'b0),
+               .IS_CARRYIN_INVERTED(1'b0),
+               .IS_CLK_INVERTED    (1'b0),
+               .IS_INMODE_INVERTED (5'b0),
+               .IS_OPMODE_INVERTED (7'b0)
+       ) testbench ();
+endmodule