mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	xilinx: Add simulation model for DSP48 (Virtex 4).
This commit is contained in:
		
							parent
							
								
									7939727d14
								
							
						
					
					
						commit
						7e0e42f907
					
				
					 6 changed files with 534 additions and 45 deletions
				
			
		|  | @ -2155,7 +2155,235 @@ assign PCOUT = P; | |||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| // TODO: DSP48 (Virtex 4). | ||||
| module DSP48 ( | ||||
|     input signed [17:0] A, | ||||
|     input signed [17:0] B, | ||||
|     input signed [47:0] C, | ||||
|     input signed [17:0] BCIN, | ||||
|     input signed [47:0] PCIN, | ||||
|     input CARRYIN, | ||||
|     input [6:0] OPMODE, | ||||
|     input SUBTRACT, | ||||
|     input [1:0] CARRYINSEL, | ||||
|     output signed [47:0] P, | ||||
|     output signed [17:0] BCOUT, | ||||
|     output signed [47:0] PCOUT, | ||||
|     (* clkbuf_sink *) | ||||
|     input CLK, | ||||
|     input CEA, | ||||
|     input CEB, | ||||
|     input CEC, | ||||
|     input CEM, | ||||
|     input CECARRYIN, | ||||
|     input CECINSUB, | ||||
|     input CECTRL, | ||||
|     input CEP, | ||||
|     input RSTA, | ||||
|     input RSTB, | ||||
|     input RSTC, | ||||
|     input RSTM, | ||||
|     input RSTCARRYIN, | ||||
|     input RSTCTRL, | ||||
|     input RSTP | ||||
| ); | ||||
| 
 | ||||
| parameter integer AREG = 1; | ||||
| parameter integer BREG = 1; | ||||
| parameter integer CREG = 1; | ||||
| parameter integer MREG = 1; | ||||
| parameter integer PREG = 1; | ||||
| parameter integer CARRYINREG = 1; | ||||
| parameter integer CARRYINSELREG = 1; | ||||
| parameter integer OPMODEREG = 1; | ||||
| parameter integer SUBTRACTREG = 1; | ||||
| parameter B_INPUT = "DIRECT"; | ||||
| parameter LEGACY_MODE = "MULT18X18S"; | ||||
| 
 | ||||
| wire signed [17:0] A_OUT; | ||||
| wire signed [17:0] B_OUT; | ||||
| wire signed [47:0] C_OUT; | ||||
| wire signed [35:0] M_MULT; | ||||
| wire signed [35:0] M_OUT; | ||||
| wire signed [47:0] P_IN; | ||||
| wire [6:0] OPMODE_OUT; | ||||
| wire [1:0] CARRYINSEL_OUT; | ||||
| wire CARRYIN_OUT; | ||||
| wire SUBTRACT_OUT; | ||||
| reg INT_CARRYIN_XY; | ||||
| reg INT_CARRYIN_Z; | ||||
| reg signed [47:0] XMUX; | ||||
| reg signed [47:0] YMUX; | ||||
| wire signed [47:0] XYMUX; | ||||
| reg signed [47:0] ZMUX; | ||||
| reg CIN; | ||||
| 
 | ||||
| // The B input multiplexer. | ||||
| wire signed [17:0] B_MUX; | ||||
| assign B_MUX = (B_INPUT == "DIRECT") ? B : BCIN; | ||||
| 
 | ||||
| // The cascade output. | ||||
| assign BCOUT = B_OUT; | ||||
| assign PCOUT = P; | ||||
| 
 | ||||
| // The registers. | ||||
| reg signed [17:0] A0_REG; | ||||
| reg signed [17:0] A1_REG; | ||||
| reg signed [17:0] B0_REG; | ||||
| reg signed [17:0] B1_REG; | ||||
| reg signed [47:0] C_REG; | ||||
| reg signed [35:0] M_REG; | ||||
| reg signed [47:0] P_REG; | ||||
| reg [6:0] OPMODE_REG; | ||||
| reg [1:0] CARRYINSEL_REG; | ||||
| reg SUBTRACT_REG; | ||||
| reg CARRYIN_REG; | ||||
| reg INT_CARRYIN_XY_REG; | ||||
| 
 | ||||
| initial begin | ||||
| 	A0_REG = 0; | ||||
| 	A1_REG = 0; | ||||
| 	B0_REG = 0; | ||||
| 	B1_REG = 0; | ||||
| 	C_REG = 0; | ||||
| 	M_REG = 0; | ||||
| 	P_REG = 0; | ||||
| 	OPMODE_REG = 0; | ||||
| 	CARRYINSEL_REG = 0; | ||||
| 	SUBTRACT_REG = 0; | ||||
| 	CARRYIN_REG = 0; | ||||
| 	INT_CARRYIN_XY_REG = 0; | ||||
| end | ||||
| 
 | ||||
| always @(posedge CLK) begin | ||||
| 	if (RSTA) begin | ||||
| 		A0_REG <= 0; | ||||
| 		A1_REG <= 0; | ||||
| 	end else if (CEA) begin | ||||
| 		A0_REG <= A; | ||||
| 		A1_REG <= A0_REG; | ||||
| 	end | ||||
| 	if (RSTB) begin | ||||
| 		B0_REG <= 0; | ||||
| 		B1_REG <= 0; | ||||
| 	end else if (CEB) begin | ||||
| 		B0_REG <= B_MUX; | ||||
| 		B1_REG <= B0_REG; | ||||
| 	end | ||||
| 	if (RSTC) begin | ||||
| 		C_REG <= 0; | ||||
| 	end else if (CEC) begin | ||||
| 		C_REG <= C; | ||||
| 	end | ||||
| 	if (RSTM) begin | ||||
| 		M_REG <= 0; | ||||
| 	end else if (CEM) begin | ||||
| 		M_REG <= M_MULT; | ||||
| 	end | ||||
| 	if (RSTP) begin | ||||
| 		P_REG <= 0; | ||||
| 	end else if (CEP) begin | ||||
| 		P_REG <= P_IN; | ||||
| 	end | ||||
| 	if (RSTCTRL) begin | ||||
| 		OPMODE_REG <= 0; | ||||
| 		CARRYINSEL_REG <= 0; | ||||
| 		SUBTRACT_REG <= 0; | ||||
| 	end else begin | ||||
| 		if (CECTRL) begin | ||||
| 			OPMODE_REG <= OPMODE; | ||||
| 			CARRYINSEL_REG <= CARRYINSEL; | ||||
| 		end | ||||
| 		if (CECINSUB) | ||||
| 			SUBTRACT_REG <= SUBTRACT; | ||||
| 	end | ||||
| 	if (RSTCARRYIN) begin | ||||
| 		CARRYIN_REG <= 0; | ||||
| 		INT_CARRYIN_XY_REG <= 0; | ||||
| 	end else begin | ||||
| 		if (CECINSUB) | ||||
| 			CARRYIN_REG <= CARRYIN; | ||||
| 		if (CECARRYIN) | ||||
| 			INT_CARRYIN_XY_REG <= INT_CARRYIN_XY; | ||||
| 	end | ||||
| end | ||||
| 
 | ||||
| // The register enables. | ||||
| assign A_OUT = (AREG == 2) ? A1_REG : (AREG == 1) ? A0_REG : A; | ||||
| assign B_OUT = (BREG == 2) ? B1_REG : (BREG == 1) ? B0_REG : B_MUX; | ||||
| assign C_OUT = (CREG == 1) ? C_REG : C; | ||||
| assign M_OUT = (MREG == 1) ? M_REG : M_MULT; | ||||
| assign P = (PREG == 1) ? P_REG : P_IN; | ||||
| assign OPMODE_OUT = (OPMODEREG == 1) ? OPMODE_REG : OPMODE; | ||||
| assign SUBTRACT_OUT = (SUBTRACTREG == 1) ? SUBTRACT_REG : SUBTRACT; | ||||
| assign CARRYINSEL_OUT = (CARRYINSELREG == 1) ? CARRYINSEL_REG : CARRYINSEL; | ||||
| assign CARRYIN_OUT = (CARRYINREG == 1) ? CARRYIN_REG : CARRYIN; | ||||
| 
 | ||||
| // The multiplier. | ||||
| assign M_MULT = A_OUT * B_OUT; | ||||
| 
 | ||||
| // The post-adder inputs. | ||||
| always @* begin | ||||
| 	case (OPMODE_OUT[1:0]) | ||||
| 		2'b00: XMUX <= 0; | ||||
| 		2'b10: XMUX <= P; | ||||
| 		2'b11: XMUX <= {{12{A_OUT[17]}}, A_OUT, B_OUT}; | ||||
| 		default: XMUX <= 48'hxxxxxxxxxxxx; | ||||
| 	endcase | ||||
| 	case (OPMODE_OUT[1:0]) | ||||
| 		2'b01: INT_CARRYIN_XY <= A_OUT[17] ~^ B_OUT[17]; | ||||
| 		2'b11: INT_CARRYIN_XY <= ~A_OUT[17]; | ||||
| 		// TODO: not tested in hardware. | ||||
| 		default: INT_CARRYIN_XY <= A_OUT[17] ~^ B_OUT[17]; | ||||
| 	endcase | ||||
| end | ||||
| 
 | ||||
| always @* begin | ||||
| 	case (OPMODE_OUT[3:2]) | ||||
| 		2'b00: YMUX <= 0; | ||||
| 		2'b11: YMUX <= C_OUT; | ||||
| 		default: YMUX <= 48'hxxxxxxxxxxxx; | ||||
| 	endcase | ||||
| end | ||||
| 
 | ||||
| assign XYMUX = (OPMODE_OUT[3:0] == 4'b0101) ? M_OUT : (XMUX + YMUX); | ||||
| 
 | ||||
| always @* begin | ||||
| 	case (OPMODE_OUT[6:4]) | ||||
| 		3'b000: ZMUX <= 0; | ||||
| 		3'b001: ZMUX <= PCIN; | ||||
| 		3'b010: ZMUX <= P; | ||||
| 		3'b011: ZMUX <= C_OUT; | ||||
| 		3'b101: ZMUX <= {{17{PCIN[47]}}, PCIN[47:17]}; | ||||
| 		3'b110: ZMUX <= {{17{P[47]}}, P[47:17]}; | ||||
| 		default: ZMUX <= 48'hxxxxxxxxxxxx; | ||||
| 	endcase | ||||
| 	// TODO: check how all this works on actual hw. | ||||
| 	if (OPMODE_OUT[1:0] == 2'b10) | ||||
| 		INT_CARRYIN_Z <= ~P[47]; | ||||
| 	else | ||||
| 		case (OPMODE_OUT[6:4]) | ||||
| 			3'b001: INT_CARRYIN_Z <= ~PCIN[47]; | ||||
| 			3'b010: INT_CARRYIN_Z <= ~P[47]; | ||||
| 			3'b101: INT_CARRYIN_Z <= ~PCIN[47]; | ||||
| 			3'b110: INT_CARRYIN_Z <= ~P[47]; | ||||
| 			default: INT_CARRYIN_Z <= 1'bx; | ||||
| 		endcase | ||||
| end | ||||
| 
 | ||||
| always @* begin | ||||
| 	case (CARRYINSEL_OUT) | ||||
| 		2'b00: CIN <= CARRYIN_OUT; | ||||
| 		2'b01: CIN <= INT_CARRYIN_Z; | ||||
| 		2'b10: CIN <= INT_CARRYIN_XY; | ||||
| 		2'b11: CIN <= INT_CARRYIN_XY_REG; | ||||
| 		default: CIN <= 1'bx; | ||||
| 	endcase | ||||
| end | ||||
| 
 | ||||
| // The post-adder. | ||||
| assign P_IN = SUBTRACT_OUT ? (ZMUX - (XYMUX + CIN)) : (ZMUX + XYMUX + CIN); | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| // TODO: DSP48E (Virtex 5). | ||||
| 
 | ||||
|  |  | |||
|  | @ -209,7 +209,7 @@ CELLS = [ | |||
|     # Cell('MULT18X18SIO', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3E | ||||
|     # Cell('DSP48A', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3A DSP | ||||
|     # Cell('DSP48A1', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 6 | ||||
|     Cell('DSP48', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 4 | ||||
|     # Cell('DSP48', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 4 | ||||
|     Cell('DSP48E', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 5 | ||||
|     #Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 6 / Series 7 | ||||
|     Cell('DSP48E2', port_attrs={'CLK': ['clkbuf_sink']}), # Ultrascale | ||||
|  |  | |||
|  | @ -5476,49 +5476,6 @@ module URAM288_BASE (...); | |||
|     input SLEEP; | ||||
| endmodule | ||||
| 
 | ||||
| module DSP48 (...); | ||||
|     parameter integer AREG = 1; | ||||
|     parameter integer BREG = 1; | ||||
|     parameter B_INPUT = "DIRECT"; | ||||
|     parameter integer CARRYINREG = 1; | ||||
|     parameter integer CARRYINSELREG = 1; | ||||
|     parameter integer CREG = 1; | ||||
|     parameter LEGACY_MODE = "MULT18X18S"; | ||||
|     parameter integer MREG = 1; | ||||
|     parameter integer OPMODEREG = 1; | ||||
|     parameter integer PREG = 1; | ||||
|     parameter integer SUBTRACTREG = 1; | ||||
|     output [17:0] BCOUT; | ||||
|     output [47:0] P; | ||||
|     output [47:0] PCOUT; | ||||
|     input [17:0] A; | ||||
|     input [17:0] B; | ||||
|     input [17:0] BCIN; | ||||
|     input [47:0] C; | ||||
|     input CARRYIN; | ||||
|     input [1:0] CARRYINSEL; | ||||
|     input CEA; | ||||
|     input CEB; | ||||
|     input CEC; | ||||
|     input CECARRYIN; | ||||
|     input CECINSUB; | ||||
|     input CECTRL; | ||||
|     input CEM; | ||||
|     input CEP; | ||||
|     (* clkbuf_sink *) | ||||
|     input CLK; | ||||
|     input [6:0] OPMODE; | ||||
|     input [47:0] PCIN; | ||||
|     input RSTA; | ||||
|     input RSTB; | ||||
|     input RSTC; | ||||
|     input RSTCARRYIN; | ||||
|     input RSTCTRL; | ||||
|     input RSTM; | ||||
|     input RSTP; | ||||
|     input SUBTRACT; | ||||
| endmodule | ||||
| 
 | ||||
| module DSP48E (...); | ||||
|     parameter SIM_MODE = "SAFE"; | ||||
|     parameter integer ACASCREG = 1; | ||||
|  |  | |||
							
								
								
									
										3
									
								
								techlibs/xilinx/tests/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								techlibs/xilinx/tests/.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -12,4 +12,7 @@ test_dsp48a_model_ref.v | |||
| test_dsp48a1_model_ref.v | ||||
| test_dsp48a1_model_uut.v | ||||
| test_dsp48a1_model | ||||
| test_dsp48_model_ref.v | ||||
| test_dsp48_model_uut.v | ||||
| test_dsp48_model | ||||
| *.vcd | ||||
|  |  | |||
							
								
								
									
										14
									
								
								techlibs/xilinx/tests/test_dsp48_model.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								techlibs/xilinx/tests/test_dsp48_model.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| #!/bin/bash | ||||
| set -ex | ||||
| if [ -z $ISE_DIR ]; then | ||||
| 	ISE_DIR=/opt/Xilinx/ISE/14.7 | ||||
| fi | ||||
| sed 's/DSP48 /DSP48_UUT /; /DSP48_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp48_model_uut.v | ||||
| if [ ! -f "test_dsp48_model_ref.v" ]; then | ||||
| 	cp $ISE_DIR/ISE_DS/ISE/verilog/src/unisims/DSP48.v test_dsp48_model_ref.v | ||||
| fi | ||||
| for tb in mult_allreg mult_noreg mult_inreg | ||||
| do | ||||
| 	iverilog -s $tb -s glbl -o test_dsp48_model test_dsp48_model.v test_dsp48_model_uut.v test_dsp48_model_ref.v $ISE_DIR/ISE_DS/ISE/verilog/src/glbl.v | ||||
| 	vvp -N ./test_dsp48_model | ||||
| done | ||||
							
								
								
									
										287
									
								
								techlibs/xilinx/tests/test_dsp48_model.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										287
									
								
								techlibs/xilinx/tests/test_dsp48_model.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,287 @@ | |||
| `timescale 1ns / 1ps | ||||
| 
 | ||||
| module testbench; | ||||
| 	parameter integer AREG = 1; | ||||
| 	parameter integer BREG = 1; | ||||
| 	parameter integer CREG = 1; | ||||
| 	parameter integer MREG = 1; | ||||
| 	parameter integer PREG = 1; | ||||
| 	parameter integer CARRYINREG = 1; | ||||
| 	parameter integer CARRYINSELREG = 1; | ||||
| 	parameter integer OPMODEREG = 1; | ||||
| 	parameter integer SUBTRACTREG = 1; | ||||
| 	parameter B_INPUT = "DIRECT"; | ||||
| 	parameter LEGACY_MODE = "NONE"; | ||||
| 
 | ||||
| 	reg CLK; | ||||
| 	reg CEA, CEB, CEC, CEM, CEP, CECARRYIN, CECINSUB, CECTRL; | ||||
| 	reg RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL; | ||||
| 	reg [17:0] A; | ||||
| 	reg [17:0] B; | ||||
| 	reg [47:0] C; | ||||
| 	reg [17:0] BCIN; | ||||
| 	reg [47:0] PCIN; | ||||
| 	reg CARRYIN; | ||||
| 	reg [6:0] OPMODE; | ||||
| 	reg SUBTRACT; | ||||
| 	reg [1:0] CARRYINSEL; | ||||
| 
 | ||||
| 	output [47:0] P, REF_P; | ||||
| 	output [17:0] BCOUT, REF_BCOUT; | ||||
| 	output [47:0] PCOUT, REF_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) begin | ||||
| 				$display("ERROR at %1t: REF_BCOUT=%b UUT_BCOUT=%b DIFF=%b", $time, REF_BCOUT, BCOUT, REF_BCOUT ^ BCOUT); | ||||
| 				errcount = errcount + 1; | ||||
| 				ERROR_FLAG = 1; | ||||
| 			end | ||||
| 			if (REF_P !== P) begin | ||||
| 				$display("ERROR at %1t: REF_P=%b UUT_P=%b DIFF=%b", $time, REF_P, P, REF_P ^ P); | ||||
| 				errcount = errcount + 1; | ||||
| 				ERROR_FLAG = 1; | ||||
| 			end | ||||
| 			if (REF_PCOUT !== PCOUT) begin | ||||
| 				$display("ERROR at %1t: REF_PCOUT=%b UUT_PCOUT=%b DIFF=%b", $time, REF_PCOUT, PCOUT, REF_PCOUT ^ PCOUT); | ||||
| 				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[1:0] == 2'b00 && CARRYINSEL == 2'b10) config_valid = 0; | ||||
| 			if (OPMODE[1:0] == 2'b10 && CARRYINSEL == 2'b10) config_valid = 0; | ||||
| 			if (OPMODE[1:0] == 2'b00 && CARRYINSEL == 2'b11) config_valid = 0; | ||||
| 			if (OPMODE[1:0] == 2'b10 && CARRYINSEL == 2'b11) config_valid = 0; | ||||
| 			if (OPMODE[3:2] == 2'b10) config_valid = 0; | ||||
| 			if ((OPMODE[3:2] == 2'b01) ^ (OPMODE[1:0] == 2'b01) == 1'b1) config_valid = 0; | ||||
| 			if ((OPMODE[6:4] == 3'b010 || OPMODE[6:4] == 3'b110) && PREG != 1) config_valid = 0; | ||||
| 			if (OPMODE[6:4] == 3'b100) config_valid = 0; | ||||
| 			if (OPMODE[6:4] == 3'b111) config_valid = 0; | ||||
| 			if (OPMODE[6:4] == 3'b000 && CARRYINSEL == 2'b01) config_valid = 0; | ||||
| 			if (OPMODE[6:4] == 3'b011 && CARRYINSEL == 2'b01) config_valid = 0; | ||||
| 
 | ||||
| 			// Xilinx models consider these combinations invalid for an unknown reason. | ||||
| 			if (CARRYINSEL == 2'b01 && OPMODE[3:2] == 2'b00) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b10 && OPMODE == 7'b0000011) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b10 && OPMODE == 7'b0000101) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b10 && OPMODE == 7'b0100011) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b10 && OPMODE == 7'b0111111) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b10 && OPMODE == 7'b1100011) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b0000011) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b0000101) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b0011111) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b0010011) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b0100011) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b0100101) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b0101111) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b0110011) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b0111111) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b1010011) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b1011111) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b1100011) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b1100101) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE == 7'b1101111) config_valid = 0; | ||||
| 
 | ||||
| 			if (CARRYINSEL == 2'b10 && OPMODE[3:0] == 4'b0101 && MREG == 1) config_valid = 0; | ||||
| 			if (CARRYINSEL == 2'b11 && OPMODE[3:0] == 4'b0101 && MREG == 0) config_valid = 0; | ||||
| 		end | ||||
| 	endtask | ||||
| 
 | ||||
| 	initial begin | ||||
| 		$dumpfile("test_dsp48_model.vcd"); | ||||
| 		$dumpvars(0, testbench); | ||||
| 
 | ||||
| 		#2; | ||||
| 		CLK = 1'b0; | ||||
| 		{CEA, CEB, CEC, CEM, CEP, CECARRYIN, CECINSUB, CECTRL} = 8'b11111111; | ||||
| 		{A, B, C, PCIN, OPMODE, SUBTRACT, CARRYIN, CARRYINSEL} = 0; | ||||
| 		{RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL} = 7'b1111111; | ||||
| 		repeat (10) begin | ||||
| 			#10; | ||||
| 			CLK = 1'b1; | ||||
| 			#10; | ||||
| 			CLK = 1'b0; | ||||
| 			#10; | ||||
| 			CLK = 1'b1; | ||||
| 			#10; | ||||
| 			CLK = 1'b0; | ||||
| 		end | ||||
| 		{RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL} = 0; | ||||
| 
 | ||||
| 		repeat (100000) begin | ||||
| 			clkcycle; | ||||
| 			config_valid = 0; | ||||
| 			while (!config_valid) begin | ||||
| 				A = $urandom; | ||||
| 				B = $urandom; | ||||
| 				C = {$urandom, $urandom}; | ||||
| 				BCIN = $urandom; | ||||
| 				PCIN = {$urandom, $urandom}; | ||||
| 
 | ||||
| 				{CEA, CEB, CEC, CEM, CEP, CECARRYIN, CECINSUB, CECTRL} = $urandom | $urandom | $urandom; | ||||
| 				{RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom; | ||||
| 				{CARRYIN, CARRYINSEL, OPMODE, SUBTRACT} = $urandom; | ||||
| 
 | ||||
| 				drc; | ||||
| 			end | ||||
| 		end | ||||
| 
 | ||||
| 		if (errcount == 0) begin | ||||
| 			$display("All tests passed."); | ||||
| 			$finish; | ||||
| 		end else begin | ||||
| 			$display("Caught %1d errors.", errcount); | ||||
| 			$stop; | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	DSP48 #( | ||||
| 		.AREG               (AREG), | ||||
| 		.BREG               (BREG), | ||||
| 		.CREG               (CREG), | ||||
| 		.MREG               (MREG), | ||||
| 		.PREG               (PREG), | ||||
| 		.CARRYINREG         (CARRYINREG), | ||||
| 		.CARRYINSELREG      (CARRYINSELREG), | ||||
| 		.OPMODEREG          (OPMODEREG), | ||||
| 		.SUBTRACTREG        (SUBTRACTREG), | ||||
| 		.B_INPUT            (B_INPUT), | ||||
| 		.LEGACY_MODE        (LEGACY_MODE) | ||||
| 	) ref ( | ||||
| 		.A             (A), | ||||
| 		.B             (B), | ||||
| 		.C             (C), | ||||
| 		.BCIN          (BCIN), | ||||
| 		.PCIN          (PCIN), | ||||
| 		.CARRYIN       (CARRYIN), | ||||
| 		.OPMODE        (OPMODE), | ||||
| 		.SUBTRACT      (SUBTRACT), | ||||
| 		.CARRYINSEL    (CARRYINSEL), | ||||
| 		.BCOUT         (REF_BCOUT), | ||||
| 		.P             (REF_P), | ||||
| 		.PCOUT         (REF_PCOUT), | ||||
| 		.CEA           (CEA), | ||||
| 		.CEB           (CEB), | ||||
| 		.CEC           (CEC), | ||||
| 		.CEM           (CEM), | ||||
| 		.CEP           (CEP), | ||||
| 		.CECARRYIN     (CECARRYIN), | ||||
| 		.CECINSUB       (CECINSUB), | ||||
| 		.CECTRL        (CECTRL), | ||||
| 		.CLK           (CLK), | ||||
| 		.RSTA          (RSTA), | ||||
| 		.RSTB          (RSTB), | ||||
| 		.RSTC          (RSTC), | ||||
| 		.RSTM          (RSTM), | ||||
| 		.RSTP          (RSTP), | ||||
| 		.RSTCARRYIN    (RSTCARRYIN), | ||||
| 		.RSTCTRL       (RSTCTRL) | ||||
| 	); | ||||
| 
 | ||||
| 	DSP48_UUT #( | ||||
| 		.AREG               (AREG), | ||||
| 		.BREG               (BREG), | ||||
| 		.CREG               (CREG), | ||||
| 		.MREG               (MREG), | ||||
| 		.PREG               (PREG), | ||||
| 		.CARRYINREG         (CARRYINREG), | ||||
| 		.CARRYINSELREG      (CARRYINSELREG), | ||||
| 		.OPMODEREG          (OPMODEREG), | ||||
| 		.SUBTRACTREG        (SUBTRACTREG), | ||||
| 		.B_INPUT            (B_INPUT), | ||||
| 		.LEGACY_MODE        (LEGACY_MODE) | ||||
| 	) uut ( | ||||
| 		.A             (A), | ||||
| 		.B             (B), | ||||
| 		.C             (C), | ||||
| 		.BCIN          (BCIN), | ||||
| 		.PCIN          (PCIN), | ||||
| 		.CARRYIN       (CARRYIN), | ||||
| 		.OPMODE        (OPMODE), | ||||
| 		.SUBTRACT      (SUBTRACT), | ||||
| 		.CARRYINSEL    (CARRYINSEL), | ||||
| 		.BCOUT         (BCOUT), | ||||
| 		.P             (P), | ||||
| 		.PCOUT         (PCOUT), | ||||
| 		.CEA           (CEA), | ||||
| 		.CEB           (CEB), | ||||
| 		.CEC           (CEC), | ||||
| 		.CEM           (CEM), | ||||
| 		.CEP           (CEP), | ||||
| 		.CECARRYIN     (CECARRYIN), | ||||
| 		.CECINSUB       (CECINSUB), | ||||
| 		.CECTRL        (CECTRL), | ||||
| 		.CLK           (CLK), | ||||
| 		.RSTA          (RSTA), | ||||
| 		.RSTB          (RSTB), | ||||
| 		.RSTC          (RSTC), | ||||
| 		.RSTM          (RSTM), | ||||
| 		.RSTP          (RSTP), | ||||
| 		.RSTCARRYIN    (RSTCARRYIN), | ||||
| 		.RSTCTRL       (RSTCTRL) | ||||
| 	); | ||||
| endmodule | ||||
| 
 | ||||
| module mult_noreg; | ||||
| 	testbench #( | ||||
| 		.AREG               (0), | ||||
| 		.BREG               (0), | ||||
| 		.CREG               (0), | ||||
| 		.MREG               (0), | ||||
| 		.PREG               (0), | ||||
| 		.CARRYINREG         (0), | ||||
| 		.CARRYINSELREG      (0), | ||||
| 		.OPMODEREG          (0), | ||||
| 		.SUBTRACTREG        (0), | ||||
| 		.B_INPUT            ("DIRECT") | ||||
| 	) testbench (); | ||||
| endmodule | ||||
| 
 | ||||
| module mult_allreg; | ||||
| 	testbench #( | ||||
| 		.AREG               (1), | ||||
| 		.BREG               (1), | ||||
| 		.CREG               (1), | ||||
| 		.MREG               (1), | ||||
| 		.PREG               (1), | ||||
| 		.CARRYINREG         (1), | ||||
| 		.CARRYINSELREG      (1), | ||||
| 		.OPMODEREG          (1), | ||||
| 		.SUBTRACTREG        (1), | ||||
| 		.B_INPUT            ("CASCADE") | ||||
| 	) testbench (); | ||||
| endmodule | ||||
| 
 | ||||
| module mult_inreg; | ||||
| 	testbench #( | ||||
| 		.AREG               (1), | ||||
| 		.BREG               (1), | ||||
| 		.CREG               (1), | ||||
| 		.MREG               (0), | ||||
| 		.PREG               (0), | ||||
| 		.CARRYINREG         (1), | ||||
| 		.CARRYINSELREG      (0), | ||||
| 		.OPMODEREG          (0), | ||||
| 		.SUBTRACTREG        (0), | ||||
| 		.B_INPUT            ("DIRECT") | ||||
| 	) testbench (); | ||||
| endmodule | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue