aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/nexus/cells_sim.v
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2020-10-01 11:15:54 +0100
committerDavid Shah <dave@ds0.me>2020-10-15 08:52:15 +0100
commit4d584d9319e87023f3aee9f9bc86a036f670478c (patch)
tree6c80347ec72c1dc36f5d77f0ce5b204a910bbfb7 /techlibs/nexus/cells_sim.v
parentf9ed9786bf8743e96aafb42838cfef5e18e35f29 (diff)
downloadyosys-4d584d9319e87023f3aee9f9bc86a036f670478c.tar.gz
yosys-4d584d9319e87023f3aee9f9bc86a036f670478c.tar.bz2
yosys-4d584d9319e87023f3aee9f9bc86a036f670478c.zip
synth_nexus: Initial implementation
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'techlibs/nexus/cells_sim.v')
-rw-r--r--techlibs/nexus/cells_sim.v379
1 files changed, 379 insertions, 0 deletions
diff --git a/techlibs/nexus/cells_sim.v b/techlibs/nexus/cells_sim.v
new file mode 100644
index 000000000..41c8a3c73
--- /dev/null
+++ b/techlibs/nexus/cells_sim.v
@@ -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