aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/ice40
diff options
context:
space:
mode:
authorEddie Hung <eddieh@ece.ubc.ca>2019-02-21 11:23:00 -0800
committerEddie Hung <eddieh@ece.ubc.ca>2019-02-21 11:23:00 -0800
commita8803a1519ce9191c43cd9a0f09d6c3ae99666e9 (patch)
tree88dcf42e2eb5121441fa95ea9146bc8b217b0160 /techlibs/ice40
parent5994382a20a0b7e890d22d032eecb39b61e0b3ce (diff)
parentd55790909c3b4244889d092c8eae630c7efd1aee (diff)
downloadyosys-a8803a1519ce9191c43cd9a0f09d6c3ae99666e9.tar.gz
yosys-a8803a1519ce9191c43cd9a0f09d6c3ae99666e9.tar.bz2
yosys-a8803a1519ce9191c43cd9a0f09d6c3ae99666e9.zip
Merge remote-tracking branch 'origin/master' into xaig
Diffstat (limited to 'techlibs/ice40')
-rw-r--r--techlibs/ice40/cells_sim.v221
-rw-r--r--techlibs/ice40/synth_ice40.cc31
-rw-r--r--techlibs/ice40/tests/.gitignore13
-rw-r--r--techlibs/ice40/tests/test_dsp_map.sh107
-rw-r--r--techlibs/ice40/tests/test_dsp_model.sh11
-rw-r--r--techlibs/ice40/tests/test_dsp_model.v342
6 files changed, 667 insertions, 58 deletions
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index 38ed45981..2041693cc 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -886,59 +886,6 @@ module SB_WARMBOOT (
);
endmodule
-// UltraPlus feature cells
-(* blackbox *)
-module SB_MAC16 (
- input CLK,
- input CE,
- input [15:0] C,
- input [15:0] A,
- input [15:0] B,
- input [15:0] D,
- input AHOLD,
- input BHOLD,
- input CHOLD,
- input DHOLD,
- input IRSTTOP,
- input IRSTBOT,
- input ORSTTOP,
- input ORSTBOT,
- input OLOADTOP,
- input OLOADBOT,
- input ADDSUBTOP,
- input ADDSUBBOT,
- input OHOLDTOP,
- input OHOLDBOT,
- input CI,
- input ACCUMCI,
- input SIGNEXTIN,
- output [31:0] O,
- output CO,
- output ACCUMCO,
- output SIGNEXTOUT
-);
-parameter NEG_TRIGGER = 1'b0;
-parameter C_REG = 1'b0;
-parameter A_REG = 1'b0;
-parameter B_REG = 1'b0;
-parameter D_REG = 1'b0;
-parameter TOP_8x8_MULT_REG = 1'b0;
-parameter BOT_8x8_MULT_REG = 1'b0;
-parameter PIPELINE_16x16_MULT_REG1 = 1'b0;
-parameter PIPELINE_16x16_MULT_REG2 = 1'b0;
-parameter TOPOUTPUT_SELECT = 2'b00;
-parameter TOPADDSUB_LOWERINPUT = 2'b00;
-parameter TOPADDSUB_UPPERINPUT = 1'b0;
-parameter TOPADDSUB_CARRYSELECT = 2'b00;
-parameter BOTOUTPUT_SELECT = 2'b00;
-parameter BOTADDSUB_LOWERINPUT = 2'b00;
-parameter BOTADDSUB_UPPERINPUT = 1'b0;
-parameter BOTADDSUB_CARRYSELECT = 2'b00;
-parameter MODE_8x8 = 1'b0;
-parameter A_SIGNED = 1'b0;
-parameter B_SIGNED = 1'b0;
-endmodule
-
module SB_SPRAM256KA (
input [13:0] ADDRESS,
input [15:0] DATAIN,
@@ -1273,3 +1220,171 @@ module SB_IO_OD (
endgenerate
`endif
endmodule
+
+module SB_MAC16 (
+ input CLK, CE,
+ input [15:0] C, A, B, D,
+ input AHOLD, BHOLD, CHOLD, DHOLD,
+ input IRSTTOP, IRSTBOT,
+ input ORSTTOP, ORSTBOT,
+ input OLOADTOP, OLOADBOT,
+ input ADDSUBTOP, ADDSUBBOT,
+ input OHOLDTOP, OHOLDBOT,
+ input CI, ACCUMCI, SIGNEXTIN,
+ output [31:0] O,
+ output CO, ACCUMCO, SIGNEXTOUT
+);
+ parameter [0:0] NEG_TRIGGER = 0;
+ parameter [0:0] C_REG = 0;
+ parameter [0:0] A_REG = 0;
+ parameter [0:0] B_REG = 0;
+ parameter [0:0] D_REG = 0;
+ parameter [0:0] TOP_8x8_MULT_REG = 0;
+ parameter [0:0] BOT_8x8_MULT_REG = 0;
+ parameter [0:0] PIPELINE_16x16_MULT_REG1 = 0;
+ parameter [0:0] PIPELINE_16x16_MULT_REG2 = 0;
+ parameter [1:0] TOPOUTPUT_SELECT = 0;
+ parameter [1:0] TOPADDSUB_LOWERINPUT = 0;
+ parameter [0:0] TOPADDSUB_UPPERINPUT = 0;
+ parameter [1:0] TOPADDSUB_CARRYSELECT = 0;
+ parameter [1:0] BOTOUTPUT_SELECT = 0;
+ parameter [1:0] BOTADDSUB_LOWERINPUT = 0;
+ parameter [0:0] BOTADDSUB_UPPERINPUT = 0;
+ parameter [1:0] BOTADDSUB_CARRYSELECT = 0;
+ parameter [0:0] MODE_8x8 = 0;
+ parameter [0:0] A_SIGNED = 0;
+ parameter [0:0] B_SIGNED = 0;
+
+ wire clock = CLK ^ NEG_TRIGGER;
+
+ // internal wires, compare Figure on page 133 of ICE Technology Library 3.0 and Fig 2 on page 2 of Lattice TN1295-DSP
+ // http://www.latticesemi.com/~/media/LatticeSemi/Documents/TechnicalBriefs/SBTICETechnologyLibrary201608.pdf
+ // https://www.latticesemi.com/-/media/LatticeSemi/Documents/ApplicationNotes/AD/DSPFunctionUsageGuideforICE40Devices.ashx
+ wire [15:0] iA, iB, iC, iD;
+ wire [15:0] iF, iJ, iK, iG;
+ wire [31:0] iL, iH;
+ wire [15:0] iW, iX, iP, iQ;
+ wire [15:0] iY, iZ, iR, iS;
+ wire HCI, LCI, LCO;
+
+ // Regs C and A
+ reg [15:0] rC, rA;
+ always @(posedge clock, posedge IRSTTOP) begin
+ if (IRSTTOP) begin
+ rC <= 0;
+ rA <= 0;
+ end else if (CE) begin
+ if (!CHOLD) rC <= C;
+ if (!AHOLD) rA <= A;
+ end
+ end
+ assign iC = C_REG ? rC : C;
+ assign iA = A_REG ? rA : A;
+
+ // Regs B and D
+ reg [15:0] rB, rD;
+ always @(posedge clock, posedge IRSTBOT) begin
+ if (IRSTBOT) begin
+ rB <= 0;
+ rD <= 0;
+ end else if (CE) begin
+ if (!BHOLD) rB <= B;
+ if (!DHOLD) rD <= D;
+ end
+ end
+ assign iB = B_REG ? rB : B;
+ assign iD = D_REG ? rD : D;
+
+ // Multiplier Stage
+ wire [15:0] p_Ah_Bh, p_Al_Bh, p_Ah_Bl, p_Al_Bl;
+ wire [15:0] Ah, Al, Bh, Bl;
+ assign Ah = {A_SIGNED ? {8{iA[15]}} : 8'b0, iA[15: 8]};
+ assign Al = {A_SIGNED ? {8{iA[ 7]}} : 8'b0, iA[ 7: 0]};
+ assign Bh = {B_SIGNED ? {8{iB[15]}} : 8'b0, iB[15: 8]};
+ assign Bl = {B_SIGNED ? {8{iB[ 7]}} : 8'b0, iB[ 7: 0]};
+ assign p_Ah_Bh = Ah * Bh;
+ assign p_Al_Bh = Al * Bh;
+ assign p_Ah_Bl = Ah * Bl;
+ assign p_Al_Bl = Al * Bl;
+
+ // Regs F and J
+ reg [15:0] rF, rJ;
+ always @(posedge clock, posedge IRSTTOP) begin
+ if (IRSTTOP) begin
+ rF <= 0;
+ rJ <= 0;
+ end else if (CE) begin
+ rF <= p_Ah_Bh;
+ if (!MODE_8x8) rJ <= p_Al_Bh;
+ end
+ end
+ assign iF = TOP_8x8_MULT_REG ? rF : p_Ah_Bh;
+ assign iJ = PIPELINE_16x16_MULT_REG1 ? rJ : p_Al_Bh;
+
+ // Regs K and G
+ reg [15:0] rK, rG;
+ always @(posedge clock, posedge IRSTBOT) begin
+ if (IRSTBOT) begin
+ rK <= 0;
+ rG <= 0;
+ end else if (CE) begin
+ if (!MODE_8x8) rK <= p_Ah_Bl;
+ rG <= p_Al_Bl;
+ end
+ end
+ assign iK = PIPELINE_16x16_MULT_REG1 ? rK : p_Ah_Bl;
+ assign iG = BOT_8x8_MULT_REG ? rG : p_Al_Bl;
+
+ // Adder Stage
+ assign iL = iG + (iK << 8) + (iJ << 8) + (iF << 16);
+
+ // Reg H
+ reg [31:0] rH;
+ always @(posedge clock, posedge IRSTBOT) begin
+ if (IRSTBOT) begin
+ rH <= 0;
+ end else if (CE) begin
+ if (!MODE_8x8) rH <= iL;
+ end
+ end
+ assign iH = PIPELINE_16x16_MULT_REG2 ? rH : iL;
+
+ // Hi Output Stage
+ wire [15:0] XW, Oh;
+ reg [15:0] rQ;
+ assign iW = TOPADDSUB_UPPERINPUT ? iC : iQ;
+ assign iX = (TOPADDSUB_LOWERINPUT == 0) ? iA : (TOPADDSUB_LOWERINPUT == 1) ? iF : (TOPADDSUB_LOWERINPUT == 2) ? iH[31:16] : {16{iZ[15]}};
+ assign {ACCUMCO, XW} = iX + (iW ^ {16{ADDSUBTOP}}) + HCI;
+ assign CO = ACCUMCO ^ ADDSUBTOP;
+ assign iP = OLOADTOP ? iC : XW ^ {16{ADDSUBTOP}};
+ always @(posedge clock, posedge ORSTTOP) begin
+ if (ORSTTOP) begin
+ rQ <= 0;
+ end else if (CE) begin
+ if (!OHOLDTOP) rQ <= iP;
+ end
+ end
+ assign iQ = rQ;
+ assign Oh = (TOPOUTPUT_SELECT == 0) ? iP : (TOPOUTPUT_SELECT == 1) ? iQ : (TOPOUTPUT_SELECT == 2) ? iF : iH[31:16];
+ assign HCI = (TOPADDSUB_CARRYSELECT == 0) ? 1'b0 : (TOPADDSUB_CARRYSELECT == 1) ? 1'b1 : (TOPADDSUB_CARRYSELECT == 2) ? LCO : LCO ^ ADDSUBBOT;
+ assign SIGNEXTOUT = iX[15];
+
+ // Lo Output Stage
+ wire [15:0] YZ, Ol;
+ reg [15:0] rS;
+ assign iY = BOTADDSUB_UPPERINPUT ? iD : iS;
+ assign iZ = (BOTADDSUB_LOWERINPUT == 0) ? iB : (BOTADDSUB_LOWERINPUT == 1) ? iG : (BOTADDSUB_LOWERINPUT == 2) ? iH[15:0] : {16{SIGNEXTIN}};
+ assign {LCO, YZ} = iZ + (iY ^ {16{ADDSUBBOT}}) + LCI;
+ assign iR = OLOADBOT ? iD : YZ ^ {16{ADDSUBBOT}};
+ always @(posedge clock, posedge ORSTBOT) begin
+ if (ORSTBOT) begin
+ rS <= 0;
+ end else if (CE) begin
+ if (!OHOLDBOT) rS <= iR;
+ end
+ end
+ assign iS = rS;
+ assign Ol = (BOTOUTPUT_SELECT == 0) ? iR : (BOTOUTPUT_SELECT == 1) ? iS : (BOTOUTPUT_SELECT == 2) ? iG : iH[15:0];
+ assign LCI = (BOTADDSUB_CARRYSELECT == 0) ? 1'b0 : (BOTADDSUB_CARRYSELECT == 1) ? 1'b1 : (BOTADDSUB_CARRYSELECT == 2) ? ACCUMCI : CI;
+ assign O = {Oh, Ol};
+endmodule
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index f77ea7f80..a13a81246 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -79,6 +79,9 @@ struct SynthIce40Pass : public ScriptPass
log(" -nobram\n");
log(" do not use SB_RAM40_4K* cells in output netlist\n");
log("\n");
+ log(" -dsp\n");
+ log(" use iCE40 UltraPlus DSP cells for large arithmetic\n");
+ log("\n");
log(" -noabc\n");
log(" use built-in Yosys LUT techmapping instead of abc\n");
log("\n");
@@ -98,8 +101,9 @@ struct SynthIce40Pass : public ScriptPass
log("\n");
}
+
string top_opt, blif_file, edif_file, json_file, abc;
- bool nocarry, nodffe, nobram, flatten, retime, relut, noabc, abc2, vpr;
+ bool nocarry, nodffe, nobram, dsp, flatten, retime, relut, noabc, abc2, vpr;
int min_ce_use;
void clear_flags() YS_OVERRIDE
@@ -112,6 +116,7 @@ struct SynthIce40Pass : public ScriptPass
nodffe = false;
min_ce_use = -1;
nobram = false;
+ dsp = false;
flatten = true;
retime = false;
relut = false;
@@ -185,6 +190,10 @@ struct SynthIce40Pass : public ScriptPass
nobram = true;
continue;
}
+ if (args[argidx] == "-dsp") {
+ dsp = true;
+ continue;
+ }
if (args[argidx] == "-noabc") {
noabc = true;
continue;
@@ -222,11 +231,11 @@ struct SynthIce40Pass : public ScriptPass
{
run("read_verilog -lib +/ice40/cells_sim.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ run("proc");
}
if (flatten && check_label("flatten", "(unless -noflatten)"))
{
- run("proc");
run("flatten");
run("tribuf -logic");
run("deminout");
@@ -234,7 +243,23 @@ struct SynthIce40Pass : public ScriptPass
if (check_label("coarse"))
{
- run("synth -lut 4 -run coarse");
+ run("opt_expr");
+ run("opt_clean");
+ run("check");
+ run("opt");
+ run("wreduce");
+ run("share");
+ run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
+ run("opt_expr");
+ run("opt_clean");
+ if (help_mode || dsp)
+ run("ice40_dsp", "(if -dsp)");
+ run("alumacc");
+ run("opt");
+ run("fsm");
+ run("opt -fast");
+ run("memory -nomap");
+ run("opt_clean");
}
if (!nobram && check_label("bram", "(skip if -nobram)"))
diff --git a/techlibs/ice40/tests/.gitignore b/techlibs/ice40/tests/.gitignore
index b58f9ad4a..120286550 100644
--- a/techlibs/ice40/tests/.gitignore
+++ b/techlibs/ice40/tests/.gitignore
@@ -1,2 +1,11 @@
-test_ffs_[01][01][01][01][01]_*
-test_bram_[0-9]*
+/test_ffs_[01][01][01][01][01]_*
+/test_bram_[0-9]*
+/test_dsp_model
+/test_dsp_model.vcd
+/test_dsp_model_ref.v
+/test_dsp_model_uut.v
+/test_dsp_map
+/test_dsp_map.vcd
+/test_dsp_map_tb.v
+/test_dsp_map_top.v
+/test_dsp_map_syn.v
diff --git a/techlibs/ice40/tests/test_dsp_map.sh b/techlibs/ice40/tests/test_dsp_map.sh
new file mode 100644
index 000000000..3f7f134e4
--- /dev/null
+++ b/techlibs/ice40/tests/test_dsp_map.sh
@@ -0,0 +1,107 @@
+#!/bin/bash
+set -ex
+
+for iter in {1..100}
+do
+ SZA=$(( 3 + $RANDOM % 13 ))
+ SZB=$(( 3 + $RANDOM % 13 ))
+ SZO=$(( 3 + $RANDOM % 29 ))
+
+ C0=clk$(( $RANDOM & 1))
+ C1=clk$(( $RANDOM & 1))
+ C2=clk$(( $RANDOM & 1))
+ C3=clk$(( $RANDOM & 1))
+
+ E0=$( test $(( $RANDOM & 1 )) -eq 0 && echo posedge || echo negedge )
+ E1=$( test $(( $RANDOM & 1 )) -eq 0 && echo posedge || echo negedge )
+ E2=$( test $(( $RANDOM & 1 )) -eq 0 && echo posedge || echo negedge )
+ E3=$( test $(( $RANDOM & 1 )) -eq 0 && echo posedge || echo negedge )
+
+ SP=$( test $(( $RANDOM & 1 )) -eq 0 && echo S || echo P )
+
+ RC=$( test $(( $RANDOM & 1 )) -eq 0 && echo "reset" || echo "!reset" )
+ RV="32'h$( echo $RANDOM | md5sum | cut -c1-8 )"
+
+ cat > test_dsp_map_top.v << EOT
+module top (
+ input clk0, clk1, reset,
+ input [$SZA:0] A,
+ input [$SZB:0] B,
+ output [$SZO:0] O
+);
+ reg [15:0] AA, BB;
+ reg [31:0] P, S;
+
+ always @($E0 $C0) AA <= A;
+ always @($E1 $C1) BB <= B;
+ always @($E2 $C2) P <= AA * BB;
+ always @($E3 $C3) S <= $RC ? $RV : S + P;
+ assign O = $SP;
+endmodule
+EOT
+
+ cat > test_dsp_map_tb.v << EOT
+\`timescale 1ns / 1ps
+module testbench;
+ reg clk1, clk0, reset;
+ reg [$SZA:0] A;
+ reg [$SZB:0] B;
+
+ wire [$SZO:0] O_top, O_syn;
+
+ top top_inst (.clk0(clk0), .clk1(clk1), .reset(reset), .A(A), .B(B), .O(O_top));
+ syn syn_inst (.clk0(clk0), .clk1(clk1), .reset(reset), .A(A), .B(B), .O(O_syn));
+
+ initial begin
+ // \$dumpfile("test_dsp_map.vcd");
+ // \$dumpvars(0, testbench);
+
+ #2;
+ clk0 = 0;
+ clk1 = 0;
+ reset = 1;
+ reset = $RC;
+ A = 0;
+ B = 0;
+
+ repeat (3) begin
+ #2; clk0 = ~clk0;
+ #2; clk0 = ~clk0;
+ #2; clk1 = ~clk1;
+ #2; clk1 = ~clk1;
+ end
+
+ repeat (100) begin
+ #2;
+ A = \$urandom;
+ B = \$urandom;
+ reset = \$urandom & \$urandom & \$urandom & \$urandom;
+ if (\$urandom & 1) begin
+ #2; clk0 = ~clk0;
+ #2; clk0 = ~clk0;
+ end else begin
+ #2; clk1 = ~clk1;
+ #2; clk1 = ~clk1;
+ end
+ #2;
+ if (O_top !== O_syn) begin
+ \$display("ERROR: O_top=%b O_syn=%b", O_top, O_syn);
+ \$stop;
+ end
+ // \$display("OK O_top=O_syn=%b", O_top);
+ end
+
+ \$display("Test passed.");
+ \$finish;
+ end
+endmodule
+EOT
+
+ ../../../yosys -p 'read_verilog test_dsp_map_top.v; synth_ice40 -dsp; rename top syn; write_verilog test_dsp_map_syn.v'
+ iverilog -o test_dsp_map -s testbench test_dsp_map_tb.v test_dsp_map_top.v test_dsp_map_syn.v ../cells_sim.v
+ vvp -N test_dsp_map
+done
+
+: ""
+: "#### All tests passed. ####"
+: ""
diff --git a/techlibs/ice40/tests/test_dsp_model.sh b/techlibs/ice40/tests/test_dsp_model.sh
new file mode 100644
index 000000000..1bc0cc688
--- /dev/null
+++ b/techlibs/ice40/tests/test_dsp_model.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+set -ex
+sed 's/SB_MAC16/SB_MAC16_UUT/; /SB_MAC16_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp_model_uut.v
+cat /opt/lscc/iCEcube2.2017.01/verilog/sb_ice_syn.v > test_dsp_model_ref.v
+for tb in testbench \
+ testbench_comb_8x8_A testbench_comb_8x8_B testbench_comb_16x16 \
+ testbench_seq_16x16_A testbench_seq_16x16_B
+do
+ iverilog -s $tb -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v
+ vvp -N ./test_dsp_model
+done
diff --git a/techlibs/ice40/tests/test_dsp_model.v b/techlibs/ice40/tests/test_dsp_model.v
new file mode 100644
index 000000000..594bd4ad3
--- /dev/null
+++ b/techlibs/ice40/tests/test_dsp_model.v
@@ -0,0 +1,342 @@
+`timescale 1ns / 1ps
+
+module testbench;
+ parameter [0:0] NEG_TRIGGER = 0;
+ parameter [0:0] C_REG = 0;
+ parameter [0:0] A_REG = 0;
+ parameter [0:0] B_REG = 0;
+ parameter [0:0] D_REG = 0;
+ parameter [0:0] TOP_8x8_MULT_REG = 0;
+ parameter [0:0] BOT_8x8_MULT_REG = 0;
+ parameter [0:0] PIPELINE_16x16_MULT_REG1 = 0;
+ parameter [0:0] PIPELINE_16x16_MULT_REG2 = 0;
+ parameter [1:0] TOPOUTPUT_SELECT = 0;
+ parameter [1:0] TOPADDSUB_LOWERINPUT = 0;
+ parameter [0:0] TOPADDSUB_UPPERINPUT = 1;
+ parameter [1:0] TOPADDSUB_CARRYSELECT = 0;
+ parameter [1:0] BOTOUTPUT_SELECT = 0;
+ parameter [1:0] BOTADDSUB_LOWERINPUT = 0;
+ parameter [0:0] BOTADDSUB_UPPERINPUT = 1;
+ parameter [1:0] BOTADDSUB_CARRYSELECT = 0;
+ parameter [0:0] MODE_8x8 = 0;
+ parameter [0:0] A_SIGNED = 0;
+ parameter [0:0] B_SIGNED = 0;
+
+ reg CLK, CE;
+ reg [15:0] C, A, B, D;
+ reg AHOLD, BHOLD, CHOLD, DHOLD;
+ reg IRSTTOP, IRSTBOT;
+ reg ORSTTOP, ORSTBOT;
+ reg OLOADTOP, OLOADBOT;
+ reg ADDSUBTOP, ADDSUBBOT;
+ reg OHOLDTOP, OHOLDBOT;
+ reg CI, ACCUMCI, SIGNEXTIN;
+
+ output [31:0] REF_O, UUT_O;
+ output REF_CO, REF_ACCUMCO, REF_SIGNEXTOUT;
+ output UUT_CO, UUT_ACCUMCO, UUT_SIGNEXTOUT;
+
+ integer errcount = 0;
+
+ task clkcycle;
+ begin
+ #5;
+ CLK = ~CLK;
+ #10;
+ CLK = ~CLK;
+ #2;
+ if (REF_O !== UUT_O) begin
+ $display("ERROR at %1t: REF_O=%b UUT_O=%b DIFF=%b", $time, REF_O, UUT_O, REF_O ^ UUT_O);
+ errcount = errcount + 1;
+ end
+ if (REF_CO !== UUT_CO) begin
+ $display("ERROR at %1t: REF_CO=%b UUT_CO=%b", $time, REF_CO, UUT_CO);
+ errcount = errcount + 1;
+ end
+ if (REF_ACCUMCO !== UUT_ACCUMCO) begin
+ $display("ERROR at %1t: REF_ACCUMCO=%b UUT_ACCUMCO=%b", $time, REF_ACCUMCO, UUT_ACCUMCO);
+ errcount = errcount + 1;
+ end
+ if (REF_SIGNEXTOUT !== UUT_SIGNEXTOUT) begin
+ $display("ERROR at %1t: REF_SIGNEXTOUT=%b UUT_SIGNEXTOUT=%b", $time, REF_SIGNEXTOUT, UUT_SIGNEXTOUT);
+ errcount = errcount + 1;
+ end
+ #3;
+ end
+ endtask
+
+ initial begin
+ $dumpfile("test_dsp_model.vcd");
+ $dumpvars(0, testbench);
+
+ #2;
+ CLK = NEG_TRIGGER;
+ CE = 1;
+ {C, A, B, D} = 0;
+ {AHOLD, BHOLD, CHOLD, DHOLD} = 0;
+ {OLOADTOP, OLOADBOT} = 0;
+ {ADDSUBTOP, ADDSUBBOT} = 0;
+ {OHOLDTOP, OHOLDBOT} = 0;
+ {CI, ACCUMCI, SIGNEXTIN} = 0;
+
+ {IRSTTOP, IRSTBOT} = ~0;
+ {ORSTTOP, ORSTBOT} = ~0;
+
+ #3;
+ {IRSTTOP, IRSTBOT} = 0;
+ {ORSTTOP, ORSTBOT} = 0;
+
+ repeat (300) begin
+ clkcycle;
+
+ A = $urandom;
+ B = $urandom;
+ C = $urandom;
+ D = $urandom;
+
+ {AHOLD, BHOLD, CHOLD, DHOLD} = $urandom & $urandom & $urandom;
+ {OLOADTOP, OLOADBOT} = $urandom & $urandom & $urandom;
+ {ADDSUBTOP, ADDSUBBOT} = $urandom & $urandom & $urandom;
+ {OHOLDTOP, OHOLDBOT} = $urandom & $urandom & $urandom;
+ {CI, ACCUMCI, SIGNEXTIN} = $urandom & $urandom & $urandom;
+
+ {IRSTTOP, IRSTBOT} = $urandom & $urandom & $urandom;
+ {ORSTTOP, ORSTBOT} = $urandom & $urandom & $urandom;
+ end
+
+ if (errcount == 0) begin
+ $display("All tests passed.");
+ $finish;
+ end else begin
+ $display("Caught %1d errors.", errcount);
+ $stop;
+ end
+ end
+
+ SB_MAC16 #(
+ .NEG_TRIGGER (NEG_TRIGGER ),
+ .C_REG (C_REG ),
+ .A_REG (A_REG ),
+ .B_REG (B_REG ),
+ .D_REG (D_REG ),
+ .TOP_8x8_MULT_REG (TOP_8x8_MULT_REG ),
+ .BOT_8x8_MULT_REG (BOT_8x8_MULT_REG ),
+ .PIPELINE_16x16_MULT_REG1 (PIPELINE_16x16_MULT_REG1),
+ .PIPELINE_16x16_MULT_REG2 (PIPELINE_16x16_MULT_REG2),
+ .TOPOUTPUT_SELECT (TOPOUTPUT_SELECT ),
+ .TOPADDSUB_LOWERINPUT (TOPADDSUB_LOWERINPUT ),
+ .TOPADDSUB_UPPERINPUT (TOPADDSUB_UPPERINPUT ),
+ .TOPADDSUB_CARRYSELECT (TOPADDSUB_CARRYSELECT ),
+ .BOTOUTPUT_SELECT (BOTOUTPUT_SELECT ),
+ .BOTADDSUB_LOWERINPUT (BOTADDSUB_LOWERINPUT ),
+ .BOTADDSUB_UPPERINPUT (BOTADDSUB_UPPERINPUT ),
+ .BOTADDSUB_CARRYSELECT (BOTADDSUB_CARRYSELECT ),
+ .MODE_8x8 (MODE_8x8 ),
+ .A_SIGNED (A_SIGNED ),
+ .B_SIGNED (B_SIGNED )
+ ) ref (
+ .CLK (CLK ),
+ .CE (CE ),
+ .C (C ),
+ .A (A ),
+ .B (B ),
+ .D (D ),
+ .AHOLD (AHOLD ),
+ .BHOLD (BHOLD ),
+ .CHOLD (CHOLD ),
+ .DHOLD (DHOLD ),
+ .IRSTTOP (IRSTTOP ),
+ .IRSTBOT (IRSTBOT ),
+ .ORSTTOP (ORSTTOP ),
+ .ORSTBOT (ORSTBOT ),
+ .OLOADTOP (OLOADTOP ),
+ .OLOADBOT (OLOADBOT ),
+ .ADDSUBTOP (ADDSUBTOP ),
+ .ADDSUBBOT (ADDSUBBOT ),
+ .OHOLDTOP (OHOLDTOP ),
+ .OHOLDBOT (OHOLDBOT ),
+ .CI (CI ),
+ .ACCUMCI (ACCUMCI ),
+ .SIGNEXTIN (SIGNEXTIN ),
+ .O (REF_O ),
+ .CO (REF_CO ),
+ .ACCUMCO (REF_ACCUMCO ),
+ .SIGNEXTOUT (REF_SIGNEXTOUT)
+ );
+
+ SB_MAC16_UUT #(
+ .NEG_TRIGGER (NEG_TRIGGER ),
+ .C_REG (C_REG ),
+ .A_REG (A_REG ),
+ .B_REG (B_REG ),
+ .D_REG (D_REG ),
+ .TOP_8x8_MULT_REG (TOP_8x8_MULT_REG ),
+ .BOT_8x8_MULT_REG (BOT_8x8_MULT_REG ),
+ .PIPELINE_16x16_MULT_REG1 (PIPELINE_16x16_MULT_REG1),
+ .PIPELINE_16x16_MULT_REG2 (PIPELINE_16x16_MULT_REG2),
+ .TOPOUTPUT_SELECT (TOPOUTPUT_SELECT ),
+ .TOPADDSUB_LOWERINPUT (TOPADDSUB_LOWERINPUT ),
+ .TOPADDSUB_UPPERINPUT (TOPADDSUB_UPPERINPUT ),
+ .TOPADDSUB_CARRYSELECT (TOPADDSUB_CARRYSELECT ),
+ .BOTOUTPUT_SELECT (BOTOUTPUT_SELECT ),
+ .BOTADDSUB_LOWERINPUT (BOTADDSUB_LOWERINPUT ),
+ .BOTADDSUB_UPPERINPUT (BOTADDSUB_UPPERINPUT ),
+ .BOTADDSUB_CARRYSELECT (BOTADDSUB_CARRYSELECT ),
+ .MODE_8x8 (MODE_8x8 ),
+ .A_SIGNED (A_SIGNED ),
+ .B_SIGNED (B_SIGNED )
+ ) uut (
+ .CLK (CLK ),
+ .CE (CE ),
+ .C (C ),
+ .A (A ),
+ .B (B ),
+ .D (D ),
+ .AHOLD (AHOLD ),
+ .BHOLD (BHOLD ),
+ .CHOLD (CHOLD ),
+ .DHOLD (DHOLD ),
+ .IRSTTOP (IRSTTOP ),
+ .IRSTBOT (IRSTBOT ),
+ .ORSTTOP (ORSTTOP ),
+ .ORSTBOT (ORSTBOT ),
+ .OLOADTOP (OLOADTOP ),
+ .OLOADBOT (OLOADBOT ),
+ .ADDSUBTOP (ADDSUBTOP ),
+ .ADDSUBBOT (ADDSUBBOT ),
+ .OHOLDTOP (OHOLDTOP ),
+ .OHOLDBOT (OHOLDBOT ),
+ .CI (CI ),
+ .ACCUMCI (ACCUMCI ),
+ .SIGNEXTIN (SIGNEXTIN ),
+ .O (UUT_O ),
+ .CO (UUT_CO ),
+ .ACCUMCO (UUT_ACCUMCO ),
+ .SIGNEXTOUT (UUT_SIGNEXTOUT)
+ );
+endmodule
+
+module testbench_comb_8x8_A;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (2), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (0), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (0), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (2), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (0), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (0), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (0),
+ .B_SIGNED (0)
+ ) testbench ();
+endmodule
+
+module testbench_comb_8x8_B;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (1), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (1), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (0), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (0),
+ .B_SIGNED (0)
+ ) testbench ();
+endmodule
+
+module testbench_comb_16x16;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (0),
+ .A_REG (0),
+ .B_REG (0),
+ .D_REG (0),
+ .TOP_8x8_MULT_REG (0),
+ .BOT_8x8_MULT_REG (0),
+ .PIPELINE_16x16_MULT_REG1 (0),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (0),
+ .B_SIGNED (0)
+ ) testbench ();
+endmodule
+
+module testbench_seq_16x16_A;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (1),
+ .A_REG (1),
+ .B_REG (1),
+ .D_REG (1),
+ .TOP_8x8_MULT_REG (1),
+ .BOT_8x8_MULT_REG (1),
+ .PIPELINE_16x16_MULT_REG1 (1),
+ .PIPELINE_16x16_MULT_REG2 (1),
+ .TOPOUTPUT_SELECT (0), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (1), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (0), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (1), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (0),
+ .B_SIGNED (0)
+ ) testbench ();
+endmodule
+
+module testbench_seq_16x16_B;
+ testbench #(
+ .NEG_TRIGGER (0),
+ .C_REG (1),
+ .A_REG (1),
+ .B_REG (1),
+ .D_REG (1),
+ .TOP_8x8_MULT_REG (1),
+ .BOT_8x8_MULT_REG (1),
+ .PIPELINE_16x16_MULT_REG1 (1),
+ .PIPELINE_16x16_MULT_REG2 (0),
+ .TOPOUTPUT_SELECT (1), // 0=P, 1=Q, 2=8x8, 3=16x16
+ .TOPADDSUB_LOWERINPUT (2), // 0=A, 1=8x8, 2=16x16, 3=S-EXT
+ .TOPADDSUB_UPPERINPUT (0), // 0=Q, 1=C
+ .TOPADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .BOTOUTPUT_SELECT (1), // 0=R, 1=S, 2=8x8, 3=16x16
+ .BOTADDSUB_LOWERINPUT (2), // 0=B, 1=8x8, 2=16x16, 3=S-EXT
+ .BOTADDSUB_UPPERINPUT (0), // 0=S, 1=D
+ .BOTADDSUB_CARRYSELECT (2), // 0=0, 1=1, 2=ACI, 3=CI
+ .MODE_8x8 (0),
+ .A_SIGNED (0),
+ .B_SIGNED (0)
+ ) testbench ();
+endmodule