Merge pull request #2403 from nakengelhardt/sim_timescale
[yosys.git] / techlibs / nexus / cells_sim.v
1 (* abc9_lut=1, lib_whitebox *)
2 module LUT4(input A, B, C, D, output Z);
3 parameter INIT = "0x0000";
4 `include "parse_init.vh"
5 localparam initp = parse_init(INIT);
6 wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
7 wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
8 wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
9 assign Z = A ? s1[1] : s1[0];
10
11 // Per-input delay differences are considered 'interconnect'
12 // so not known yet
13 specify
14 (A => Z) = 233;
15 (B => Z) = 233;
16 (C => Z) = 233;
17 (D => Z) = 233;
18 endspecify
19
20 endmodule
21
22 // This is a placeholder for ABC9 to extract the area/delay
23 // cost of 5-input LUTs and is not intended to be instantiated
24 (* abc9_lut=2 *)
25 module \$__ABC9_LUT5 (input SEL, D, C, B, A, output Z);
26 specify
27 (SEL => Z) = 171;
28 (D => Z) = 303;
29 (C => Z) = 311;
30 (B => Z) = 309;
31 (A => Z) = 306;
32 endspecify
33 endmodule
34
35 // Two LUT4s and MUX2
36 module WIDEFN9(input A0, B0, C0, D0, A1, B1, C1, D1, SEL, output Z);
37 parameter INIT0 = "0x0000";
38 parameter INIT1 = "0x0000";
39 wire z0, z1;
40 LUT4 #(.INIT(INIT0)) lut4_0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(z0));
41 LUT4 #(.INIT(INIT1)) lut4_1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(z1));
42 assign Z = SEL ? z1 : z0;
43 endmodule
44
45 (* abc9_box, lib_whitebox *)
46 module INV(input A, output Z);
47 assign Z = !A;
48
49 specify
50 (A => Z) = 10;
51 endspecify
52 endmodule
53
54 // Bidirectional IO buffer
55 module BB(input T, I, output O,
56 (* iopad_external_pin *) inout B);
57 assign B = T ? 1'bz : O;
58 assign I = B;
59 endmodule
60
61 // Input buffer
62 module IB(
63 (* iopad_external_pin *) input I,
64 output O);
65 assign O = I;
66 endmodule
67
68 // Output buffer
69 module OB(input I,
70 (* iopad_external_pin *) output O);
71 assign O = I;
72 endmodule
73
74 // Output buffer with tristate
75 module OBZ(input I, T,
76 (* iopad_external_pin *) output O);
77 assign O = T ? 1'bz : I;
78 endmodule
79
80 // Constants
81 module VLO(output Z);
82 assign Z = 1'b0;
83 endmodule
84
85 module VHI(output Z);
86 assign Z = 1'b1;
87 endmodule
88
89 // Vendor flipflops
90 // (all have active high clock, enable and set/reset - use INV to invert)
91
92 // Async preset
93 (* abc9_box, lib_whitebox *)
94 module FD1P3BX(input D, CK, SP, PD, output reg Q);
95 parameter GSR = "DISABLED";
96 initial Q = 1'b1;
97 always @(posedge CK or posedge PD)
98 if (PD)
99 Q <= 1'b1;
100 else if (SP)
101 Q <= D;
102 specify
103 $setup(D, posedge CK, 0);
104 $setup(SP, posedge CK, 212);
105 $setup(PD, posedge CK, 224);
106 `ifndef YOSYS
107 if (PD) (posedge CLK => (Q : 1)) = 0;
108 `else
109 if (PD) (PD => Q) = 0; // Technically, this should be an edge sensitive path
110 // but for facilitating a bypass box, let's pretend it's
111 // a simple path
112 `endif
113 if (!PD && SP) (posedge CK => (Q : D)) = 336;
114 endspecify
115 endmodule
116
117 // Async clear
118 (* abc9_box, lib_whitebox *)
119 module FD1P3DX(input D, CK, SP, CD, output reg Q);
120 parameter GSR = "DISABLED";
121 initial Q = 1'b0;
122 always @(posedge CK or posedge CD)
123 if (CD)
124 Q <= 1'b0;
125 else if (SP)
126 Q <= D;
127 specify
128 $setup(D, posedge CK, 0);
129 $setup(SP, posedge CK, 212);
130 $setup(CD, posedge CK, 224);
131 `ifndef YOSYS
132 if (CD) (posedge CLK => (Q : 0)) = 0;
133 `else
134 if (CD) (CD => Q) = 0; // Technically, this should be an edge sensitive path
135 // but for facilitating a bypass box, let's pretend it's
136 // a simple path
137 `endif
138 if (!CD && SP) (posedge CK => (Q : D)) = 336;
139 endspecify
140 endmodule
141
142 // Sync clear
143 (* abc9_flop, lib_whitebox *)
144 module FD1P3IX(input D, CK, SP, CD, output reg Q);
145 parameter GSR = "DISABLED";
146 initial Q = 1'b0;
147 always @(posedge CK)
148 if (CD)
149 Q <= 1'b0;
150 else if (SP)
151 Q <= D;
152 specify
153 $setup(D, posedge CK, 0);
154 $setup(SP, posedge CK, 212);
155 $setup(CD, posedge CK, 224);
156 if (!CD && SP) (posedge CK => (Q : D)) = 336;
157 endspecify
158 endmodule
159
160 // Sync preset
161 (* abc9_flop, lib_whitebox *)
162 module FD1P3JX(input D, CK, SP, PD, output reg Q);
163 parameter GSR = "DISABLED";
164 initial Q = 1'b1;
165 always @(posedge CK)
166 if (PD)
167 Q <= 1'b1;
168 else if (SP)
169 Q <= D;
170 specify
171 $setup(D, posedge CK, 0);
172 $setup(SP, posedge CK, 212);
173 $setup(PD, posedge CK, 224);
174 if (!PD && SP) (posedge CK => (Q : D)) = 336;
175 endspecify
176 endmodule
177
178 // LUT4 with LUT3 tap for CCU2 use only
179 (* lib_whitebox *)
180 module LUT4_3(input A, B, C, D, output Z, Z3);
181 parameter INIT = "0x0000";
182 `include "parse_init.vh"
183 localparam initp = parse_init(INIT);
184 wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
185 wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
186 wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
187 assign Z = A ? s1[1] : s1[0];
188
189 wire [3:0] s2_3 = C ? initp[ 7:4] : initp[3:0];
190 wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
191 assign Z3 = A ? s1_3[1] : s1_3[0];
192
193 endmodule
194
195 // Carry primitive (incoporating two LUTs)
196 (* abc9_box, lib_whitebox *)
197 module CCU2(
198 (* abc9_carry *) input CIN,
199 input A1, B1, C1, D1, A0, B0, C0, D0,
200 output S1, S0,
201 (* abc9_carry *) output COUT);
202 parameter INJECT = "YES";
203 parameter INIT0 = "0x0000";
204 parameter INIT1 = "0x1111";
205
206 localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
207
208 wire LUT3_0, LUT4_0, LUT3_1, LUT4_1, carry_0;
209 LUT4_3 #(.INIT(INIT0)) lut0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0), .Z3(LUT3_0));
210 LUT4_3 #(.INIT(INIT1)) lut1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1), .Z3(LUT3_1));
211
212 assign S0 = LUT4_0 ^ (CIN & ~inject_p);
213 assign carry_0 = LUT4_0 ? CIN : (LUT3_0 & ~inject_p);
214 assign S1 = LUT4_1 ^ (carry_0 & ~inject_p);
215 assign COUT = LUT4_1 ? carry_0 : (LUT3_1 & ~inject_p);
216
217 specify
218 (A0 => S0) = 233;
219 (B0 => S0) = 233;
220 (C0 => S0) = 233;
221 (D0 => S0) = 233;
222 (CIN => S0) = 228;
223 (A0 => S1) = 481;
224 (B0 => S1) = 481;
225 (C0 => S1) = 481;
226 (D0 => S1) = 481;
227 (A1 => S1) = 233;
228 (B1 => S1) = 233;
229 (C1 => S1) = 233;
230 (D1 => S1) = 233;
231 (CIN => S1) = 307;
232 (A0 => COUT) = 347;
233 (B0 => COUT) = 347;
234 (C0 => COUT) = 347;
235 (D0 => COUT) = 347;
236 (A1 => COUT) = 347;
237 (B1 => COUT) = 347;
238 (C1 => COUT) = 347;
239 (D1 => COUT) = 347;
240 (CIN => COUT) = 59;
241 endspecify
242
243 endmodule
244
245 // Packed flipflop
246 module OXIDE_FF(input CLK, LSR, CE, DI, M, output reg Q);
247 parameter GSR = "ENABLED";
248 parameter [127:0] CEMUX = "1";
249 parameter CLKMUX = "CLK";
250 parameter LSRMUX = "LSR";
251 parameter REGDDR = "DISABLED";
252 parameter SRMODE = "LSR_OVER_CE";
253 parameter REGSET = "RESET";
254 parameter [127:0] LSRMODE = "LSR";
255
256 wire muxce;
257 generate
258 case (CEMUX)
259 "1": assign muxce = 1'b1;
260 "0": assign muxce = 1'b0;
261 "INV": assign muxce = ~CE;
262 default: assign muxce = CE;
263 endcase
264 endgenerate
265
266 wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
267 wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
268 wire srval;
269 generate
270 if (LSRMODE == "PRLD")
271 assign srval = M;
272 else
273 assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
274 endgenerate
275
276 initial Q = srval;
277
278 generate
279 if (REGDDR == "ENABLED") begin
280 if (SRMODE == "ASYNC") begin
281 always @(posedge muxclk, negedge muxclk, posedge muxlsr)
282 if (muxlsr)
283 Q <= srval;
284 else if (muxce)
285 Q <= DI;
286 end else begin
287 always @(posedge muxclk, negedge muxclk)
288 if (muxlsr)
289 Q <= srval;
290 else if (muxce)
291 Q <= DI;
292 end
293 end else begin
294 if (SRMODE == "ASYNC") begin
295 always @(posedge muxclk, posedge muxlsr)
296 if (muxlsr)
297 Q <= srval;
298 else if (muxce)
299 Q <= DI;
300 end else begin
301 always @(posedge muxclk)
302 if (muxlsr)
303 Q <= srval;
304 else if (muxce)
305 Q <= DI;
306 end
307 end
308 endgenerate
309 endmodule
310
311 // Packed combinational logic (for post-pnr sim)
312 module OXIDE_COMB(
313 input A, B, C, D, // LUT inputs
314 input SEL, // mux select input
315 input F1, // output from LUT 1 for mux
316 input FCI, // carry input
317 input WAD0, WAD1, WAD2, WAD3, // LUTRAM write address inputs
318 input WD, // LUTRAM write data input
319 input WCK, WRE, // LUTRAM write clock and enable
320 output F, // LUT/carry output
321 output OFX // mux output
322 );
323 parameter MODE = "LOGIC"; // LOGIC, CCU2, DPRAM
324 parameter [15:0] INIT = 16'h0000;
325 parameter INJECT = "YES";
326
327 localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
328
329 reg [15:0] lut = INIT;
330
331 wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0];
332 wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
333 wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
334 wire Z = A ? s1[1] : s1[0];
335
336 wire [3:0] s2_3 = C ? INIT[ 7:4] : INIT[3:0];
337 wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
338 wire Z3 = A ? s1_3[1] : s1_3[0];
339
340 generate
341 if (MODE == "DPRAM") begin
342 always @(posedge WCK)
343 if (WRE)
344 lut[{WAD3, WAD2, WAD1, WAD0}] <= WD;
345 end
346 if (MODE == "CCU2") begin
347 assign F = Z ^ (FCI & ~inject_p);
348 assign FCO = Z ? FCI : (Z3 & ~inject_p);
349 end else begin
350 assign F = Z;
351 end
352 endgenerate
353
354 assign OFX = SEL ? F1 : F;
355
356 endmodule
357
358 // LUTRAM
359 module DPR16X4(
360 input [3:0] RAD, DI, WAD,
361 input WRE, WCK,
362 output [3:0] DO
363 );
364 parameter INITVAL = "0x0000000000000000";
365 `include "parse_init.vh"
366 localparam [63:0] parsed_init = parse_init_64(INITVAL);
367
368 reg [3:0] mem[0:15];
369 integer i;
370 initial begin
371 for (i = 0; i < 15; i++)
372 mem[i] = parsed_init[i * 4 +: 4];
373 end
374
375 always @(posedge WCK)
376 if (WRE)
377 mem[WAD] <= DI;
378 assign DO = mem[RAD];
379 endmodule