diff options
Diffstat (limited to 'techlibs/ice40')
| -rw-r--r-- | techlibs/ice40/cells_sim.v | 221 | ||||
| -rw-r--r-- | techlibs/ice40/synth_ice40.cc | 31 | ||||
| -rw-r--r-- | techlibs/ice40/tests/.gitignore | 13 | ||||
| -rw-r--r-- | techlibs/ice40/tests/test_dsp_map.sh | 107 | ||||
| -rw-r--r-- | techlibs/ice40/tests/test_dsp_model.sh | 11 | ||||
| -rw-r--r-- | techlibs/ice40/tests/test_dsp_model.v | 342 | 
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 | 
