mirror of
https://github.com/YosysHQ/yosys
synced 2025-08-11 13:40:53 +00:00
synth_nexus: Initial implementation
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
f9ed9786bf
commit
4d584d9319
30 changed files with 12528 additions and 0 deletions
379
techlibs/nexus/cells_sim.v
Normal file
379
techlibs/nexus/cells_sim.v
Normal file
|
@ -0,0 +1,379 @@
|
|||
(* abc9_lut=1, lib_whitebox *)
|
||||
module LUT4(input A, B, C, D, output Z);
|
||||
parameter INIT = "0x0000";
|
||||
`include "parse_init.vh"
|
||||
localparam initp = parse_init(INIT);
|
||||
wire [7:0] s3 = D ? initp[15:8] : initp[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];
|
||||
|
||||
// Per-input delay differences are considered 'interconnect'
|
||||
// so not known yet
|
||||
specify
|
||||
(A => Z) = 233;
|
||||
(B => Z) = 233;
|
||||
(C => Z) = 233;
|
||||
(D => Z) = 233;
|
||||
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
|
||||
(* abc9_lut=2 *)
|
||||
module \$__ABC9_LUT5 (input SEL, D, C, B, A, output Z);
|
||||
specify
|
||||
(SEL => Z) = 171;
|
||||
(D => Z) = 303;
|
||||
(C => Z) = 311;
|
||||
(B => Z) = 309;
|
||||
(A => Z) = 306;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// Two LUT4s and MUX2
|
||||
module WIDEFN9(input A0, B0, C0, D0, A1, B1, C1, D1, SEL, output Z);
|
||||
parameter INIT0 = "0x0000";
|
||||
parameter INIT1 = "0x0000";
|
||||
wire z0, z1;
|
||||
LUT4 #(.INIT(INIT0)) lut4_0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(z0));
|
||||
LUT4 #(.INIT(INIT1)) lut4_1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(z1));
|
||||
assign Z = SEL ? z1 : z0;
|
||||
endmodule
|
||||
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module INV(input A, output Z);
|
||||
assign Z = !A;
|
||||
|
||||
specify
|
||||
(A => Z) = 10;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// Bidirectional IO buffer
|
||||
module BB(input T, I, output O,
|
||||
(* iopad_external_pin *) inout B);
|
||||
assign B = T ? 1'bz : O;
|
||||
assign I = B;
|
||||
endmodule
|
||||
|
||||
// Input buffer
|
||||
module IB(
|
||||
(* iopad_external_pin *) input I,
|
||||
output O);
|
||||
assign O = I;
|
||||
endmodule
|
||||
|
||||
// Output buffer
|
||||
module OB(input I,
|
||||
(* iopad_external_pin *) output O);
|
||||
assign O = I;
|
||||
endmodule
|
||||
|
||||
// Output buffer with tristate
|
||||
module OBZ(input I, T,
|
||||
(* iopad_external_pin *) output O);
|
||||
assign O = T ? 1'bz : I;
|
||||
endmodule
|
||||
|
||||
// Constants
|
||||
module VLO(output Z);
|
||||
assign Z = 1'b0;
|
||||
endmodule
|
||||
|
||||
module VHI(output Z);
|
||||
assign Z = 1'b1;
|
||||
endmodule
|
||||
|
||||
// Vendor flipflops
|
||||
// (all have active high clock, enable and set/reset - use INV to invert)
|
||||
|
||||
// Async preset
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module FD1P3BX(input D, CK, SP, PD, output reg Q);
|
||||
parameter GSR = "DISABLED";
|
||||
initial Q = 1'b1;
|
||||
always @(posedge CK or posedge PD)
|
||||
if (PD)
|
||||
Q <= 1'b1;
|
||||
else if (SP)
|
||||
Q <= D;
|
||||
specify
|
||||
$setup(D, posedge CK, 0);
|
||||
$setup(SP, posedge CK, 212);
|
||||
$setup(PD, posedge CK, 224);
|
||||
`ifndef YOSYS
|
||||
if (PD) (posedge CLK => (Q : 1)) = 0;
|
||||
`else
|
||||
if (PD) (PD => 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 (!PD && SP) (posedge CK => (Q : D)) = 336;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// Async clear
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module FD1P3DX(input D, CK, SP, CD, output reg Q);
|
||||
parameter GSR = "DISABLED";
|
||||
initial Q = 1'b0;
|
||||
always @(posedge CK or posedge CD)
|
||||
if (CD)
|
||||
Q <= 1'b0;
|
||||
else if (SP)
|
||||
Q <= D;
|
||||
specify
|
||||
$setup(D, posedge CK, 0);
|
||||
$setup(SP, posedge CK, 212);
|
||||
$setup(CD, posedge CK, 224);
|
||||
`ifndef YOSYS
|
||||
if (CD) (posedge CLK => (Q : 0)) = 0;
|
||||
`else
|
||||
if (CD) (CD => 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 (!CD && SP) (posedge CK => (Q : D)) = 336;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// Sync clear
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module FD1P3IX(input D, CK, SP, CD, output reg Q);
|
||||
parameter GSR = "DISABLED";
|
||||
initial Q = 1'b0;
|
||||
always @(posedge CK)
|
||||
if (CD)
|
||||
Q <= 1'b0;
|
||||
else if (SP)
|
||||
Q <= D;
|
||||
specify
|
||||
$setup(D, posedge CK, 0);
|
||||
$setup(SP, posedge CK, 212);
|
||||
$setup(CD, posedge CK, 224);
|
||||
if (!CD && SP) (posedge CK => (Q : D)) = 336;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// Sync preset
|
||||
(* abc9_flop, lib_whitebox *)
|
||||
module FD1P3JX(input D, CK, SP, PD, output reg Q);
|
||||
parameter GSR = "DISABLED";
|
||||
initial Q = 1'b1;
|
||||
always @(posedge CK)
|
||||
if (PD)
|
||||
Q <= 1'b1;
|
||||
else if (SP)
|
||||
Q <= D;
|
||||
specify
|
||||
$setup(D, posedge CK, 0);
|
||||
$setup(SP, posedge CK, 212);
|
||||
$setup(PD, posedge CK, 224);
|
||||
if (!PD && SP) (posedge CK => (Q : D)) = 336;
|
||||
endspecify
|
||||
endmodule
|
||||
|
||||
// LUT4 with LUT3 tap for CCU2 use only
|
||||
(* lib_whitebox *)
|
||||
module LUT4_3(input A, B, C, D, output Z, Z3);
|
||||
parameter INIT = "0x0000";
|
||||
`include "parse_init.vh"
|
||||
localparam initp = parse_init(INIT);
|
||||
wire [7:0] s3 = D ? initp[15:8] : initp[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];
|
||||
|
||||
wire [3:0] s2_3 = C ? initp[ 7:4] : initp[3:0];
|
||||
wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
|
||||
assign Z3 = A ? s1_3[1] : s1_3[0];
|
||||
|
||||
endmodule
|
||||
|
||||
// Carry primitive (incoporating two LUTs)
|
||||
(* abc9_box, lib_whitebox *)
|
||||
module CCU2(
|
||||
(* abc9_carry *) input CIN,
|
||||
input A1, B1, C1, D1, A0, B0, C0, D0,
|
||||
output S1, S0,
|
||||
(* abc9_carry *) output COUT);
|
||||
parameter INJECT = "YES";
|
||||
parameter INIT0 = "0x0000";
|
||||
parameter INIT1 = "0x1111";
|
||||
|
||||
localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
|
||||
|
||||
wire LUT3_0, LUT4_0, LUT3_1, LUT4_1, carry_0;
|
||||
LUT4_3 #(.INIT(INIT0)) lut0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0), .Z3(LUT3_0));
|
||||
LUT4_3 #(.INIT(INIT1)) lut1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1), .Z3(LUT3_1));
|
||||
|
||||
assign S0 = LUT4_0 ^ (CIN & ~inject_p);
|
||||
assign carry_0 = LUT4_0 ? CIN : (LUT3_0 & ~inject_p);
|
||||
assign S1 = LUT4_1 ^ (carry_0 & ~inject_p);
|
||||
assign COUT = LUT4_1 ? carry_0 : (LUT3_1 & ~inject_p);
|
||||
|
||||
specify
|
||||
(A0 => S0) = 233;
|
||||
(B0 => S0) = 233;
|
||||
(C0 => S0) = 233;
|
||||
(D0 => S0) = 233;
|
||||
(CIN => S0) = 228;
|
||||
(A0 => S1) = 481;
|
||||
(B0 => S1) = 481;
|
||||
(C0 => S1) = 481;
|
||||
(D0 => S1) = 481;
|
||||
(A1 => S1) = 233;
|
||||
(B1 => S1) = 233;
|
||||
(C1 => S1) = 233;
|
||||
(D1 => S1) = 233;
|
||||
(CIN => S1) = 307;
|
||||
(A0 => COUT) = 347;
|
||||
(B0 => COUT) = 347;
|
||||
(C0 => COUT) = 347;
|
||||
(D0 => COUT) = 347;
|
||||
(A1 => COUT) = 347;
|
||||
(B1 => COUT) = 347;
|
||||
(C1 => COUT) = 347;
|
||||
(D1 => COUT) = 347;
|
||||
(CIN => COUT) = 59;
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
|
||||
// Packed flipflop
|
||||
module OXIDE_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 REGDDR = "DISABLED";
|
||||
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 (REGDDR == "ENABLED") begin
|
||||
if (SRMODE == "ASYNC") begin
|
||||
always @(posedge muxclk, negedge muxclk, posedge muxlsr)
|
||||
if (muxlsr)
|
||||
Q <= srval;
|
||||
else if (muxce)
|
||||
Q <= DI;
|
||||
end else begin
|
||||
always @(posedge muxclk, negedge muxclk)
|
||||
if (muxlsr)
|
||||
Q <= srval;
|
||||
else if (muxce)
|
||||
Q <= DI;
|
||||
end
|
||||
end else begin
|
||||
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
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
|
||||
// Packed combinational logic (for post-pnr sim)
|
||||
module OXIDE_COMB(
|
||||
input A, B, C, D, // LUT inputs
|
||||
input SEL, // mux select input
|
||||
input F1, // output from LUT 1 for mux
|
||||
input FCI, // carry input
|
||||
input WAD0, WAD1, WAD2, WAD3, // LUTRAM write address inputs
|
||||
input WD, // LUTRAM write data input
|
||||
input WCK, WRE, // LUTRAM write clock and enable
|
||||
output F, // LUT/carry output
|
||||
output OFX // mux output
|
||||
);
|
||||
parameter MODE = "LOGIC"; // LOGIC, CCU2, DPRAM
|
||||
parameter [15:0] INIT = 16'h0000;
|
||||
parameter INJECT = "YES";
|
||||
|
||||
localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
|
||||
|
||||
reg [15:0] lut = INIT;
|
||||
|
||||
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];
|
||||
wire Z = A ? s1[1] : s1[0];
|
||||
|
||||
wire [3:0] s2_3 = C ? INIT[ 7:4] : INIT[3:0];
|
||||
wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
|
||||
wire Z3 = A ? s1_3[1] : s1_3[0];
|
||||
|
||||
generate
|
||||
if (MODE == "DPRAM") begin
|
||||
always @(posedge WCK)
|
||||
if (WRE)
|
||||
lut[{WAD3, WAD2, WAD1, WAD0}] <= WD;
|
||||
end
|
||||
if (MODE == "CCU2") begin
|
||||
assign F = Z ^ (FCI & ~inject_p);
|
||||
assign FCO = Z ? FCI : (Z3 & ~inject_p);
|
||||
end else begin
|
||||
assign F = Z;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign OFX = SEL ? F1 : F;
|
||||
|
||||
endmodule
|
||||
|
||||
// LUTRAM
|
||||
module DPR16X4(
|
||||
input [3:0] RAD, DI, WAD,
|
||||
input WRE, WCK,
|
||||
output [3:0] DO
|
||||
);
|
||||
parameter INITVAL = "0x0000000000000000";
|
||||
`include "parse_init.vh"
|
||||
localparam [63:0] parsed_init = parse_init_64(INITVAL);
|
||||
|
||||
reg [3:0] mem[0:15];
|
||||
integer i;
|
||||
initial begin
|
||||
for (i = 0; i < 15; i++)
|
||||
mem[i] = parsed_init[i * 4 +: 4];
|
||||
end
|
||||
|
||||
always @(posedge WCK)
|
||||
if (WRE)
|
||||
mem[WAD] <= DI;
|
||||
assign DO = mem[RAD];
|
||||
endmodule
|
Loading…
Add table
Add a link
Reference in a new issue