mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			411 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			Systemverilog
		
	
	
	
	
	
			
		
		
	
	
			411 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			Systemverilog
		
	
	
	
	
	
| // ---------------------------------------
 | |
| 
 | |
| (* abc9_lut=1, lib_whitebox *)
 | |
| module LUT4(input A, B, C, D, output Z);
 | |
|     parameter [15:0] INIT = 16'h0000;
 | |
|     wire [7:0] s3 = D ?     INIT[15:8] :     INIT[7:0];
 | |
|     wire [3:0] s2 = C ?       s3[ 7:4] :       s3[3:0];
 | |
|     wire [1:0] s1 = B ?       s2[ 3:2] :       s2[1:0];
 | |
|     assign Z =      A ?          s1[1] :         s1[0];
 | |
|     specify
 | |
|         (A => Z) = 141;
 | |
|         (B => Z) = 275;
 | |
|         (C => Z) = 379;
 | |
|         (D => Z) = 379;
 | |
|     endspecify
 | |
| endmodule
 | |
| 
 | |
| // This is a placeholder for ABC9 to extract the area/delay
 | |
| //   cost of 5-input LUTs and is not intended to be instantiated
 | |
| // LUT5 = 2x LUT4 + PFUMX
 | |
| (* abc9_lut=2 *)
 | |
| module \$__ABC9_LUT5 (input M0, D, C, B, A, output Z);
 | |
|     specify
 | |
|         (M0 => Z) = 151;
 | |
|         (D => Z) = 239;
 | |
|         (C => Z) = 373;
 | |
|         (B => Z) = 477;
 | |
|         (A => Z) = 477;
 | |
|     endspecify
 | |
| endmodule
 | |
| 
 | |
| // This is a placeholder for ABC9 to extract the area/delay
 | |
| //   of 6-input LUTs and is not intended to be instantiated
 | |
| // LUT6 = 2x LUT5 + MUX2
 | |
| (* abc9_lut=4 *)
 | |
| module \$__ABC9_LUT6 (input M1, M0, D, C, B, A, output Z);
 | |
|     specify
 | |
|         (M1 => Z) = 148;
 | |
|         (M0 => Z) = 292;
 | |
|         (D => Z) = 380;
 | |
|         (C => Z) = 514;
 | |
|         (B => Z) = 618;
 | |
|         (A => Z) = 618;
 | |
|     endspecify
 | |
| endmodule
 | |
| 
 | |
| // This is a placeholder for ABC9 to extract the area/delay
 | |
| //   of 7-input LUTs and is not intended to be instantiated
 | |
| // LUT7 = 2x LUT6 + MUX2
 | |
| (* abc9_lut=8 *)
 | |
| module \$__ABC9_LUT7 (input M2, M1, M0, D, C, B, A, output Z);
 | |
|     specify
 | |
|         (M2 => Z) = 148;
 | |
|         (M1 => Z) = 289;
 | |
|         (M0 => Z) = 433;
 | |
|         (D => Z) = 521;
 | |
|         (C => Z) = 655;
 | |
|         (B => Z) = 759;
 | |
|         (A => Z) = 759;
 | |
|     endspecify
 | |
| endmodule
 | |
| 
 | |
| // ---------------------------------------
 | |
| (* abc9_box, lib_whitebox *)
 | |
| module L6MUX21 (input D0, D1, SD, output Z);
 | |
| 	assign Z = SD ? D1 : D0;
 | |
| 	specify
 | |
| 		(D0 => Z) = 140;
 | |
| 		(D1 => Z) = 141;
 | |
| 		(SD => Z) = 148;
 | |
| 	endspecify
 | |
| endmodule
 | |
| 
 | |
| // ---------------------------------------
 | |
| 
 | |
| module TRELLIS_RAM16X2 (
 | |
| 	input DI0, DI1,
 | |
| 	input WAD0, WAD1, WAD2, WAD3,
 | |
| 	input WRE, WCK,
 | |
| 	input RAD0, RAD1, RAD2, RAD3,
 | |
| 	output DO0, DO1
 | |
| );
 | |
| 	parameter WCKMUX = "WCK";
 | |
| 	parameter WREMUX = "WRE";
 | |
| 	parameter INITVAL_0 = 16'h0000;
 | |
| 	parameter INITVAL_1 = 16'h0000;
 | |
| 
 | |
| 	reg [1:0] mem[15:0];
 | |
| 
 | |
| 	integer i;
 | |
| 	initial begin
 | |
| 		for (i = 0; i < 16; i = i + 1)
 | |
| 			mem[i] <= {INITVAL_1[i], INITVAL_0[i]};
 | |
| 	end
 | |
| 
 | |
| 	wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
 | |
| 
 | |
| 	reg muxwre;
 | |
| 	always @(*)
 | |
| 		case (WREMUX)
 | |
| 			"1": muxwre = 1'b1;
 | |
| 			"0": muxwre = 1'b0;
 | |
| 			"INV": muxwre = ~WRE;
 | |
| 			default: muxwre = WRE;
 | |
| 		endcase
 | |
| 
 | |
| 
 | |
| 	always @(posedge muxwck)
 | |
| 		if (muxwre)
 | |
| 			mem[{WAD3, WAD2, WAD1, WAD0}] <= {DI1, DI0};
 | |
| 
 | |
| 	assign {DO1, DO0} = mem[{RAD3, RAD2, RAD1, RAD0}];
 | |
| endmodule
 | |
| 
 | |
| // ---------------------------------------
 | |
| (* abc9_box, lib_whitebox *)
 | |
| module PFUMX (input ALUT, BLUT, C0, output Z);
 | |
| 	assign Z = C0 ? ALUT : BLUT;
 | |
| 	specify
 | |
| 		(ALUT => Z) = 98;
 | |
| 		(BLUT => Z) = 98;
 | |
| 		(C0 => Z) = 151;
 | |
| 	endspecify
 | |
| endmodule
 | |
| 
 | |
| // ---------------------------------------
 | |
| (* abc9_box, lib_whitebox *)
 | |
| module TRELLIS_DPR16X4 (
 | |
| 	input  [3:0] DI,
 | |
| 	input  [3:0] WAD,
 | |
| 	input        WRE,
 | |
| 	input        WCK,
 | |
| 	input  [3:0] RAD,
 | |
| 	output [3:0] DO
 | |
| );
 | |
| 	parameter WCKMUX = "WCK";
 | |
| 	parameter WREMUX = "WRE";
 | |
| 	parameter [63:0] INITVAL = 64'h0000000000000000;
 | |
| 
 | |
| 	reg [3:0] mem[15:0];
 | |
| 
 | |
| 	integer i;
 | |
| 	initial begin
 | |
| 		for (i = 0; i < 16; i = i + 1)
 | |
| 			mem[i] <= INITVAL[4*i +: 4];
 | |
| 	end
 | |
| 
 | |
| 	wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
 | |
| 
 | |
| 	reg muxwre;
 | |
| 	always @(*)
 | |
| 		case (WREMUX)
 | |
| 			"1": muxwre = 1'b1;
 | |
| 			"0": muxwre = 1'b0;
 | |
| 			"INV": muxwre = ~WRE;
 | |
| 			default: muxwre = WRE;
 | |
| 		endcase
 | |
| 
 | |
| 	always @(posedge muxwck)
 | |
| 		if (muxwre)
 | |
| 			mem[WAD] <= DI;
 | |
| 
 | |
| 	assign DO = mem[RAD];
 | |
| 
 | |
| 	specify
 | |
| 		// TODO
 | |
| 		(RAD *> DO) = 0;
 | |
| 	endspecify
 | |
| endmodule
 | |
| 
 | |
| // ---------------------------------------
 | |
| 
 | |
| (* abc9_box, lib_whitebox *)
 | |
| module DPR16X4C (
 | |
| 		input [3:0] DI,
 | |
| 		input WCK, WRE,
 | |
| 		input [3:0] RAD,
 | |
| 		input [3:0] WAD,
 | |
| 		output [3:0] DO
 | |
| );
 | |
| 	// For legacy Lattice compatibility, INITIVAL is a hex
 | |
| 	// string rather than a numeric parameter
 | |
| 	parameter INITVAL = "0x0000000000000000";
 | |
| 
 | |
| 	function [63:0] convert_initval;
 | |
| 		input [143:0] hex_initval;
 | |
| 		reg done;
 | |
| 		reg [63:0] temp;
 | |
| 		reg [7:0] char;
 | |
| 		integer i;
 | |
| 		begin
 | |
| 			done = 1'b0;
 | |
| 			temp = 0;
 | |
| 			for (i = 0; i < 16; i = i + 1) begin
 | |
| 				if (!done) begin
 | |
| 					char = hex_initval[8*i +: 8];
 | |
| 					if (char == "x") begin
 | |
| 						done = 1'b1;
 | |
| 					end else begin
 | |
| 						if (char >= "0" && char <= "9")
 | |
| 							temp[4*i +: 4] = char - "0";
 | |
| 						else if (char >= "A" && char <= "F")
 | |
| 							temp[4*i +: 4] = 10 + char - "A";
 | |
| 						else if (char >= "a" && char <= "f")
 | |
| 							temp[4*i +: 4] = 10 + char - "a";
 | |
| 					end
 | |
| 				end
 | |
| 			end
 | |
| 			convert_initval = temp;
 | |
| 		end
 | |
| 	endfunction
 | |
| 
 | |
| 	localparam conv_initval = convert_initval(INITVAL);
 | |
| 
 | |
| 	reg [3:0] ram[0:15];
 | |
| 	integer i;
 | |
| 	initial begin
 | |
| 		for (i = 0; i < 15; i = i + 1) begin
 | |
| 			ram[i] <= conv_initval[4*i +: 4];
 | |
| 		end
 | |
| 	end
 | |
| 
 | |
| 	always @(posedge WCK)
 | |
| 		if (WRE)
 | |
| 			ram[WAD] <= DI;
 | |
| 
 | |
| 	assign DO = ram[RAD];
 | |
| 
 | |
| 	specify
 | |
| 		// TODO
 | |
| 		(RAD *> DO) = 0;
 | |
| 	endspecify
 | |
| endmodule
 | |
| 
 | |
| // ---------------------------------------
 | |
| 
 | |
| (* lib_whitebox *)
 | |
| module LUT2(input A, B, output Z);
 | |
|     parameter [3:0] INIT = 4'h0;
 | |
|     wire [1:0] s1 = B ?     INIT[ 3:2] :     INIT[1:0];
 | |
|     assign Z =      A ?          s1[1] :         s1[0];
 | |
| endmodule
 | |
| 
 | |
| // ---------------------------------------
 | |
| 
 | |
| `ifdef YOSYS
 | |
| (* abc9_flop=(SRMODE != "ASYNC"), abc9_box=(SRMODE == "ASYNC"), lib_whitebox *)
 | |
| `endif
 | |
| module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
 | |
| 	parameter GSR = "ENABLED";
 | |
| 	parameter [127:0] CEMUX = "1";
 | |
| 	parameter CLKMUX = "CLK";
 | |
| 	parameter LSRMUX = "LSR";
 | |
| 	parameter SRMODE = "LSR_OVER_CE";
 | |
| 	parameter REGSET = "RESET";
 | |
| 	parameter [127:0] LSRMODE = "LSR";
 | |
| 
 | |
| 	wire muxce;
 | |
| 	generate
 | |
| 		case (CEMUX)
 | |
| 			"1": assign muxce = 1'b1;
 | |
| 			"0": assign muxce = 1'b0;
 | |
| 			"INV": assign muxce = ~CE;
 | |
| 			default: assign muxce = CE;
 | |
| 		endcase
 | |
| 	endgenerate
 | |
| 
 | |
| 	wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
 | |
| 	wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
 | |
| 	wire srval;
 | |
| 	generate
 | |
| 		if (LSRMODE == "PRLD")
 | |
| 			assign srval = M;
 | |
| 		else
 | |
| 			assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
 | |
| 	endgenerate
 | |
| 
 | |
| 	initial Q = srval;
 | |
| 
 | |
| 	generate
 | |
| 		if (SRMODE == "ASYNC") begin
 | |
| 			always @(posedge muxclk, posedge muxlsr)
 | |
| 				if (muxlsr)
 | |
| 					Q <= srval;
 | |
| 				else if (muxce)
 | |
| 					Q <= DI;
 | |
| 		end else begin
 | |
| 			always @(posedge muxclk)
 | |
| 				if (muxlsr)
 | |
| 					Q <= srval;
 | |
| 				else if (muxce)
 | |
| 					Q <= DI;
 | |
| 		end
 | |
| 	endgenerate
 | |
| 
 | |
| 	specify
 | |
| 		$setup(DI, negedge CLK &&& CLKMUX == "INV", 0);
 | |
| 		$setup(CE, negedge CLK &&& CLKMUX == "INV", 0);
 | |
| 		$setup(LSR, negedge CLK &&& CLKMUX == "INV", 0);
 | |
| 		$setup(DI, posedge CLK &&& CLKMUX != "INV", 0);
 | |
| 		$setup(CE, posedge CLK &&& CLKMUX != "INV", 0);
 | |
| 		$setup(LSR, posedge CLK &&& CLKMUX != "INV", 0);
 | |
| `ifndef YOSYS
 | |
| 		if (SRMODE == "ASYNC" && muxlsr && CLKMUX == "INV") (negedge CLK => (Q : srval)) = 0;
 | |
| 		if (SRMODE == "ASYNC" && muxlsr && CLKMUX != "INV") (posedge CLK => (Q : srval)) = 0;
 | |
| `else
 | |
| 		if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; 	// Technically, this should be an edge sensitive path
 | |
| 									// but for facilitating a bypass box, let's pretend it's
 | |
| 									// a simple path
 | |
| `endif
 | |
| 		if (!muxlsr && muxce && CLKMUX == "INV") (negedge CLK => (Q : DI)) = 0;
 | |
| 		if (!muxlsr && muxce && CLKMUX != "INV") (posedge CLK => (Q : DI)) = 0;
 | |
| 	endspecify
 | |
| endmodule
 | |
| 
 | |
| // ---------------------------------------
 | |
| (* keep *)
 | |
| module TRELLIS_IO(
 | |
| 	(* iopad_external_pin *)
 | |
| 	inout B,
 | |
| 	input I,
 | |
| 	input T,
 | |
| 	output O
 | |
| );
 | |
| 	parameter DIR = "INPUT";
 | |
| 	reg T_pd;
 | |
| 	always @(*) if (T === 1'bz) T_pd <= 1'b0; else T_pd <= T;
 | |
| 
 | |
| 	generate
 | |
| 		if (DIR == "INPUT") begin
 | |
| 			assign B = 1'bz;
 | |
| 			assign O = B;
 | |
| 		end else if (DIR == "OUTPUT") begin
 | |
| 			assign B = T_pd ? 1'bz : I;
 | |
| 			assign O = 1'bx;
 | |
| 		end else if (DIR == "BIDIR") begin
 | |
| 			assign B = T_pd ? 1'bz : I;
 | |
| 			assign O = B;
 | |
| 		end else begin
 | |
| 			ERROR_UNKNOWN_IO_MODE error();
 | |
| 		end
 | |
| 	endgenerate
 | |
| 
 | |
| endmodule
 | |
| 
 | |
| // ---------------------------------------
 | |
| 
 | |
| module INV(input A, output Z);
 | |
| 	assign Z = !A;
 | |
| endmodule
 | |
| 
 | |
| // ---------------------------------------
 | |
| 
 | |
| module TRELLIS_COMB(
 | |
| 	input A, B, C, D, M,
 | |
| 	input FCI, F1, FXA, FXB,
 | |
| 	input WD,
 | |
| 	input WAD0, WAD1, WAD2, WAD3,
 | |
| 	input WRE, WCK,
 | |
| 	output F, FCO, OFX
 | |
| );
 | |
| 	parameter MODE = "LOGIC";
 | |
| 	parameter INITVAL = 16'h0;
 | |
| 	parameter CCU2_INJECT1 = "NO";
 | |
| 	parameter WREMUX = "WRE";
 | |
| 	parameter IS_Z1 = 1'b0;
 | |
| 
 | |
| 	generate
 | |
| 		if (MODE == "LOGIC") begin: mode_logic
 | |
| 			LUT4 #(.INIT(INITVAL)) lut4 (.A(A), .B(B), .C(C), .D(D), .Z(F));
 | |
| 		end else if (MODE == "CCU2") begin: mode_ccu2
 | |
| 			wire l4o, l2o;
 | |
| 			LUT4 #(.INIT(INITVAL)) lut4_0(.A(A), .B(B), .C(C), .D(D), .Z(l4o));
 | |
| 			LUT2 #(.INIT(INITVAL[3:0])) lut2_0(.A(A), .B(B), .Z(l2o));
 | |
| 			wire gated_cin_0 = (CCU2_INJECT1 == "YES") ? 1'b0 : FCI;
 | |
| 			assign F = l4o ^ gated_cin_0;
 | |
| 			wire gated_lut2_0 = (CCU2_INJECT1 == "YES") ? 1'b0 : l2o;
 | |
| 			wire FCO = (~l4o & gated_lut2_0) | (l4o & FCI);
 | |
| 		end else if (MODE == "DPRAM") begin: mode_dpram
 | |
| 			reg [15:0] ram = INITVAL;
 | |
| 			always @(posedge WCK)
 | |
| 				if (WRE)
 | |
| 					ram[{WAD3, WAD2, WAD1, WAD0}] <= WD;
 | |
| 			assign F = ram[{A, C, B, D}];
 | |
| 		end else begin
 | |
| 			$error("unsupported COMB mode %s", MODE);
 | |
| 		end
 | |
| 
 | |
|  		if (IS_Z1)
 | |
| 			L6MUX21 lutx_mux (.D0(FXA), .D1(FXB), .SD(M), .Z(OFX));
 | |
| 		else
 | |
| 			PFUMX lut5_mux (.ALUT(F1), .BLUT(F), .C0(M), .Z(OFX));
 | |
| 	endgenerate
 | |
| 
 | |
| endmodule
 | |
| 
 | |
| // Constants
 | |
| module VLO(output Z);
 | |
| 	assign Z = 1'b0;
 | |
| endmodule
 | |
| 
 | |
| module VHI(output Z);
 | |
| 	assign Z = 1'b1;
 | |
| endmodule
 | |
| 
 | |
| `ifndef NO_INCLUDES
 | |
| 
 | |
| `include "cells_ff.vh"
 | |
| `include "cells_io.vh"
 | |
| 
 | |
| `endif
 |