mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +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
 | 
					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).
 | 
					// TODO: DSP48E (Virtex 5).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -209,7 +209,7 @@ CELLS = [
 | 
				
			||||||
    # Cell('MULT18X18SIO', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3E
 | 
					    # Cell('MULT18X18SIO', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3E
 | 
				
			||||||
    # Cell('DSP48A', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3A DSP
 | 
					    # Cell('DSP48A', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3A DSP
 | 
				
			||||||
    # Cell('DSP48A1', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 6
 | 
					    # 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('DSP48E', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 5
 | 
				
			||||||
    #Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 6 / Series 7
 | 
					    #Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 6 / Series 7
 | 
				
			||||||
    Cell('DSP48E2', port_attrs={'CLK': ['clkbuf_sink']}), # Ultrascale
 | 
					    Cell('DSP48E2', port_attrs={'CLK': ['clkbuf_sink']}), # Ultrascale
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5476,49 +5476,6 @@ module URAM288_BASE (...);
 | 
				
			||||||
    input SLEEP;
 | 
					    input SLEEP;
 | 
				
			||||||
endmodule
 | 
					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 (...);
 | 
					module DSP48E (...);
 | 
				
			||||||
    parameter SIM_MODE = "SAFE";
 | 
					    parameter SIM_MODE = "SAFE";
 | 
				
			||||||
    parameter integer ACASCREG = 1;
 | 
					    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_ref.v
 | 
				
			||||||
test_dsp48a1_model_uut.v
 | 
					test_dsp48a1_model_uut.v
 | 
				
			||||||
test_dsp48a1_model
 | 
					test_dsp48a1_model
 | 
				
			||||||
 | 
					test_dsp48_model_ref.v
 | 
				
			||||||
 | 
					test_dsp48_model_uut.v
 | 
				
			||||||
 | 
					test_dsp48_model
 | 
				
			||||||
*.vcd
 | 
					*.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