xilinx: Test our DSP48A/DSP48A1 simulation models.

This commit is contained in:
Marcin Kościelnicki 2019-12-22 14:30:04 +00:00
parent aa1adb0f1e
commit dadaf7ed78
5 changed files with 362 additions and 7 deletions

View 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.

View 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

View File

@ -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

View File

@ -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

View 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