xilinx: Test our DSP48A/DSP48A1 simulation models.
authorMarcin Kościelnicki <mwk@0x04.net>
Sun, 22 Dec 2019 14:30:04 +0000 (14:30 +0000)
committerMarcin Kościelnicki <mwk@0x04.net>
Mon, 23 Dec 2019 19:36:43 +0000 (20:36 +0100)
techlibs/xilinx/cells_sim.v
techlibs/xilinx/tests/.gitignore
techlibs/xilinx/tests/test_dsp48a1_model.sh [new file with mode: 0644]
techlibs/xilinx/tests/test_dsp48a1_model.v [new file with mode: 0644]
techlibs/xilinx/tests/test_dsp_model.sh

index 804c2d70fcd683fcc2b33665b50eafedee9bcd28..3bcbfc9aab014e4ff675960009c7b7dcee7cf498 100644 (file)
@@ -2099,7 +2099,7 @@ always @* begin
                2'b00: XMUX <= 0;
                2'b01: XMUX <= M;
                2'b10: XMUX <= P;
-               2'b11: XMUX <= {D_OUT[11:0], B1_OUT, A1_OUT};
+               2'b11: XMUX <= {D_OUT[11:0], A1_OUT, B1_OUT};
                default: XMUX <= 48'hxxxxxxxxxxxx;
        endcase
 end
@@ -2117,8 +2117,8 @@ end
 // The post-adder.
 wire signed [48:0] X_EXT;
 wire signed [48:0] Z_EXT;
-assign X_EXT = XMUX;
-assign Z_EXT = ZMUX;
+assign X_EXT = {1'b0, XMUX};
+assign Z_EXT = {1'b0, ZMUX};
 assign {CARRYOUT_IN, P_IN} = OPMODE_OUT[7] ? (Z_EXT - (X_EXT + CARRYIN_OUT)) : (Z_EXT + X_EXT + CARRYIN_OUT);
 
 // Cascade outputs.
index ef3699bd20b06f7ca866a92d50fe320e901936c0..848f88d53f860bea7ef2d15efd06d9274e3026ea 100644 (file)
@@ -8,4 +8,8 @@ dsp_work*/
 test_dsp_model_ref.v
 test_dsp_model_uut.v
 test_dsp_model
+test_dsp48a_model_ref.v
+test_dsp48a1_model_ref.v
+test_dsp48a1_model_uut.v
+test_dsp48a1_model
 *.vcd
diff --git a/techlibs/xilinx/tests/test_dsp48a1_model.sh b/techlibs/xilinx/tests/test_dsp48a1_model.sh
new file mode 100644 (file)
index 0000000..a14a78e
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -ex
+if [ -z $ISE_DIR ]; then
+       ISE_DIR=/opt/Xilinx/ISE/14.7
+fi
+sed 's/DSP48A1/MARKER1/; s/DSP48A/DSP48A_UUT/; s/MARKER1/DSP48A1_UUT/; /module DSP48A_UUT/,/endmodule/ p; /module DSP48A1_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp48a1_model_uut.v
+if [ ! -f "test_dsp48a1_model_ref.v" ]; then
+       cp $ISE_DIR/ISE_DS/ISE/verilog/src/unisims/DSP48A1.v test_dsp48a1_model_ref.v
+fi
+if [ ! -f "test_dsp48a_model_ref.v" ]; then
+       cp $ISE_DIR/ISE_DS/ISE/verilog/src/unisims/DSP48A.v test_dsp48a_model_ref.v
+fi
+for tb in mult_allreg mult_noreg mult_inreg
+do
+       iverilog -s $tb -s glbl -o test_dsp48a1_model test_dsp48a1_model.v test_dsp48a1_model_uut.v test_dsp48a1_model_ref.v test_dsp48a_model_ref.v $ISE_DIR/ISE_DS/ISE/verilog/src/glbl.v
+       vvp -N ./test_dsp48a1_model
+done
diff --git a/techlibs/xilinx/tests/test_dsp48a1_model.v b/techlibs/xilinx/tests/test_dsp48a1_model.v
new file mode 100644 (file)
index 0000000..66346b4
--- /dev/null
@@ -0,0 +1,331 @@
+`timescale 1ns / 1ps
+
+module testbench;
+       parameter integer A0REG = 1;
+       parameter integer A1REG = 1;
+       parameter integer B0REG = 1;
+       parameter integer B1REG = 1;
+       parameter integer CREG = 1;
+       parameter integer DREG = 1;
+       parameter integer MREG = 1;
+       parameter integer PREG = 1;
+       parameter integer CARRYINREG = 1;
+       parameter integer CARRYOUTREG = 1;
+       parameter integer OPMODEREG = 1;
+       parameter CARRYINSEL = "OPMODE5";
+       parameter RSTTYPE = "SYNC";
+
+       reg CLK;
+       reg CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE;
+       reg RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE;
+       reg [17:0] A;
+       reg [17:0] B;
+       reg [47:0] C;
+       reg [17:0] D;
+       reg [47:0] PCIN;
+       reg [7:0] OPMODE;
+       reg CARRYIN;
+
+       output CARRYOUTF, REF_CARRYOUTF;
+       output CARRYOUT, REF_CARRYOUT, REF_OLD_CARRYOUT;
+       output [35:0] M, REF_M;
+       output [47:0] P, REF_P, REF_OLD_P;
+       output [17:0] BCOUT, REF_BCOUT, REF_OLD_BCOUT;
+       output [47:0] PCOUT, REF_PCOUT, REF_OLD_PCOUT;
+
+       integer errcount = 0;
+
+       reg ERROR_FLAG = 0;
+
+       task clkcycle;
+               begin
+                       #5;
+                       CLK = ~CLK;
+                       #10;
+                       CLK = ~CLK;
+                       #2;
+                       ERROR_FLAG = 0;
+                       if (REF_BCOUT !== BCOUT || REF_OLD_BCOUT != BCOUT) begin
+                               $display("ERROR at %1t: REF_BCOUT=%b REF_OLD_BCOUT=%b UUT_BCOUT=%b DIFF=%b", $time, REF_BCOUT, REF_OLD_BCOUT, BCOUT, REF_BCOUT ^ BCOUT);
+                               errcount = errcount + 1;
+                               ERROR_FLAG = 1;
+                       end
+                       if (REF_M !== M) begin
+                               $display("ERROR at %1t: REF_M=%b UUT_M=%b DIFF=%b", $time, REF_M, M, REF_M ^ M);
+                               errcount = errcount + 1;
+                               ERROR_FLAG = 1;
+                       end
+                       if (REF_P !== P || REF_OLD_P != P) begin
+                               $display("ERROR at %1t: REF_P=%b REF_OLD_P=%b UUT_P=%b DIFF=%b", $time, REF_P, REF_OLD_P, P, REF_P ^ P);
+                               errcount = errcount + 1;
+                               ERROR_FLAG = 1;
+                       end
+                       if (REF_PCOUT !== PCOUT || REF_OLD_PCOUT != PCOUT) begin
+                               $display("ERROR at %1t: REF_PCOUT=%b REF_OLD_PCOUT=%b UUT_PCOUT=%b DIFF=%b", $time, REF_PCOUT, REF_OLD_PCOUT, PCOUT, REF_PCOUT ^ PCOUT);
+                               errcount = errcount + 1;
+                               ERROR_FLAG = 1;
+                       end
+                       if (REF_CARRYOUT !== CARRYOUT || (REF_OLD_CARRYOUT != CARRYOUT && !CARRYOUTREG)) begin
+                               $display("ERROR at %1t: REF_CARRYOUT=%b REF_OLD_CARRYOUT=%b UUT_CARRYOUT=%b DIFF=%b", $time, REF_CARRYOUT, REF_OLD_CARRYOUT, CARRYOUT, REF_CARRYOUT ^ CARRYOUT);
+                               errcount = errcount + 1;
+                               ERROR_FLAG = 1;
+                       end
+                       if (REF_CARRYOUTF !== CARRYOUTF) begin
+                               $display("ERROR at %1t: REF_CARRYOUTF=%b UUT_CARRYOUTF=%b", $time, REF_CARRYOUTF, CARRYOUTF);
+                               errcount = errcount + 1;
+                               ERROR_FLAG = 1;
+                       end
+                       #3;
+               end
+       endtask
+
+       reg config_valid = 0;
+       task drc;
+               begin
+                       config_valid = 1;
+
+                       if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0;
+                       if (OPMODE[3:2] == 2'b10 && PREG != 1) config_valid = 0;
+               end
+       endtask
+
+       initial begin
+               $dumpfile("test_dsp48a1_model.vcd");
+               $dumpvars(0, testbench);
+
+               #2;
+               CLK = 1'b0;
+               {CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE} = 8'b11111111;
+               {A, B, C, D, PCIN, OPMODE, CARRYIN} = 0;
+               {RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = 8'b11111111;
+               repeat (10) begin
+                       #10;
+                       CLK = 1'b1;
+                       #10;
+                       CLK = 1'b0;
+                       #10;
+                       CLK = 1'b1;
+                       #10;
+                       CLK = 1'b0;
+               end
+               {RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = 0;
+
+               repeat (10000) begin
+                       clkcycle;
+                       config_valid = 0;
+                       while (!config_valid) begin
+                               A = $urandom;
+                               B = $urandom;
+                               C = {$urandom, $urandom};
+                               D = $urandom;
+                               PCIN = {$urandom, $urandom};
+
+                               {CEA, CEB, CEC, CED, CEM, CEP, CECARRYIN, CEOPMODE} = $urandom | $urandom | $urandom;
+                               {RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCARRYIN, RSTOPMODE} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom;
+                               {CARRYIN, OPMODE} = $urandom;
+
+                               drc;
+                       end
+               end
+
+               if (errcount == 0) begin
+                       $display("All tests passed.");
+                       $finish;
+               end else begin
+                       $display("Caught %1d errors.", errcount);
+                       $stop;
+               end
+       end
+
+       DSP48A #(
+               .A0REG              (A0REG),
+               .A1REG              (A1REG),
+               .B0REG              (B0REG),
+               .B1REG              (B1REG),
+               .CREG               (CREG),
+               .DREG               (DREG),
+               .MREG               (MREG),
+               .PREG               (PREG),
+               .CARRYINREG         (CARRYINREG),
+               .OPMODEREG          (OPMODEREG),
+               .CARRYINSEL         (CARRYINSEL),
+               .RSTTYPE            (RSTTYPE)
+       ) ref_old (
+               .A             (A),
+               .B             (B),
+               .C             (C),
+               .D             (D),
+               .PCIN          (PCIN),
+               .CARRYIN       (CARRYIN),
+               .OPMODE        (OPMODE),
+               .BCOUT         (REF_OLD_BCOUT),
+               .CARRYOUT      (REF_OLD_CARRYOUT),
+               .P             (REF_OLD_P),
+               .PCOUT         (REF_OLD_PCOUT),
+               .CEA           (CEA),
+               .CEB           (CEB),
+               .CEC           (CEC),
+               .CED           (CED),
+               .CEM           (CEM),
+               .CEP           (CEP),
+               .CECARRYIN     (CECARRYIN),
+               .CEOPMODE      (CEOPMODE),
+               .CLK           (CLK),
+               .RSTA          (RSTA),
+               .RSTB          (RSTB),
+               .RSTC          (RSTC),
+               .RSTD          (RSTD),
+               .RSTM          (RSTM),
+               .RSTP          (RSTP),
+               .RSTCARRYIN    (RSTCARRYIN),
+               .RSTOPMODE     (RSTOPMODE)
+       );
+
+       DSP48A1 #(
+               .A0REG              (A0REG),
+               .A1REG              (A1REG),
+               .B0REG              (B0REG),
+               .B1REG              (B1REG),
+               .CREG               (CREG),
+               .DREG               (DREG),
+               .MREG               (MREG),
+               .PREG               (PREG),
+               .CARRYINREG         (CARRYINREG),
+               .CARRYOUTREG        (CARRYOUTREG),
+               .OPMODEREG          (OPMODEREG),
+               .CARRYINSEL         (CARRYINSEL),
+               .RSTTYPE            (RSTTYPE)
+       ) ref (
+               .A             (A),
+               .B             (B),
+               .C             (C),
+               .D             (D),
+               .PCIN          (PCIN),
+               .CARRYIN       (CARRYIN),
+               .OPMODE        (OPMODE),
+               .BCOUT         (REF_BCOUT),
+               .CARRYOUTF     (REF_CARRYOUTF),
+               .CARRYOUT      (REF_CARRYOUT),
+               .P             (REF_P),
+               .M             (REF_M),
+               .PCOUT         (REF_PCOUT),
+               .CEA           (CEA),
+               .CEB           (CEB),
+               .CEC           (CEC),
+               .CED           (CED),
+               .CEM           (CEM),
+               .CEP           (CEP),
+               .CECARRYIN     (CECARRYIN),
+               .CEOPMODE      (CEOPMODE),
+               .CLK           (CLK),
+               .RSTA          (RSTA),
+               .RSTB          (RSTB),
+               .RSTC          (RSTC),
+               .RSTD          (RSTD),
+               .RSTM          (RSTM),
+               .RSTP          (RSTP),
+               .RSTCARRYIN    (RSTCARRYIN),
+               .RSTOPMODE     (RSTOPMODE)
+       );
+
+       DSP48A1_UUT #(
+               .A0REG              (A0REG),
+               .A1REG              (A1REG),
+               .B0REG              (B0REG),
+               .B1REG              (B1REG),
+               .CREG               (CREG),
+               .DREG               (DREG),
+               .MREG               (MREG),
+               .PREG               (PREG),
+               .CARRYINREG         (CARRYINREG),
+               .CARRYOUTREG        (CARRYOUTREG),
+               .OPMODEREG          (OPMODEREG),
+               .CARRYINSEL         (CARRYINSEL),
+               .RSTTYPE            (RSTTYPE)
+       ) uut (
+               .A             (A),
+               .B             (B),
+               .C             (C),
+               .D             (D),
+               .PCIN          (PCIN),
+               .CARRYIN       (CARRYIN),
+               .OPMODE        (OPMODE),
+               .BCOUT         (BCOUT),
+               .CARRYOUTF     (CARRYOUTF),
+               .CARRYOUT      (CARRYOUT),
+               .P             (P),
+               .M             (M),
+               .PCOUT         (PCOUT),
+               .CEA           (CEA),
+               .CEB           (CEB),
+               .CEC           (CEC),
+               .CED           (CED),
+               .CEM           (CEM),
+               .CEP           (CEP),
+               .CECARRYIN     (CECARRYIN),
+               .CEOPMODE      (CEOPMODE),
+               .CLK           (CLK),
+               .RSTA          (RSTA),
+               .RSTB          (RSTB),
+               .RSTC          (RSTC),
+               .RSTD          (RSTD),
+               .RSTM          (RSTM),
+               .RSTP          (RSTP),
+               .RSTCARRYIN    (RSTCARRYIN),
+               .RSTOPMODE     (RSTOPMODE)
+       );
+endmodule
+
+module mult_noreg;
+       testbench #(
+               .A0REG              (0),
+               .A1REG              (0),
+               .B0REG              (0),
+               .B1REG              (0),
+               .CREG               (0),
+               .DREG               (0),
+               .MREG               (0),
+               .PREG               (0),
+               .CARRYINREG         (0),
+               .CARRYOUTREG        (0),
+               .OPMODEREG          (0),
+               .CARRYINSEL         ("CARRYIN"),
+               .RSTTYPE            ("SYNC")
+       ) testbench ();
+endmodule
+
+module mult_allreg;
+       testbench #(
+               .A0REG              (1),
+               .A1REG              (1),
+               .B0REG              (1),
+               .B1REG              (1),
+               .CREG               (1),
+               .DREG               (1),
+               .MREG               (1),
+               .PREG               (1),
+               .CARRYINREG         (1),
+               .CARRYOUTREG        (1),
+               .OPMODEREG          (1),
+               .CARRYINSEL         ("OPMODE5"),
+               .RSTTYPE            ("SYNC")
+       ) testbench ();
+endmodule
+
+module mult_inreg;
+       testbench #(
+               .A0REG              (1),
+               .A1REG              (1),
+               .B0REG              (1),
+               .B1REG              (1),
+               .CREG               (1),
+               .DREG               (1),
+               .MREG               (0),
+               .PREG               (0),
+               .CARRYINREG         (1),
+               .CARRYOUTREG        (0),
+               .OPMODEREG          (0),
+               .CARRYINSEL         ("CARRYIN"),
+               .RSTTYPE            ("SYNC")
+       ) testbench ();
+endmodule
index ae925c402186857e434a3a64823c9520e7a7c121..d005cd40c7398b0a55ebdf681f11f5e922a1472d 100644 (file)
@@ -1,14 +1,17 @@
 #!/bin/bash
 set -ex
+if [ -z $VIVADO_DIR ]; then
+       VIVADO_DIR=/opt/Xilinx/Vivado/2019.1
+fi
 sed 's/DSP48E1/DSP48E1_UUT/; /DSP48E1_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp_model_uut.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
+       cp $VIVADO_DIR/data/verilog/src/unisims/DSP48E1.v test_dsp_model_ref.v
 fi
 for tb in macc_overflow_underflow \
-    simd24_preadd_noreg_nocasc simd12_preadd_noreg_nocasc \
-    mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_nocasc  \
+       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
 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
+       iverilog -s $tb -s glbl -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v $VIVADO_DIR/data/verilog/src/glbl.v
        vvp -N ./test_dsp_model
 done