Finished initial GP_COUNT8/14/8_ADV/14_ADV sim models. Don't support clock divide...
[yosys.git] / techlibs / greenpak4 / cells_sim_digital.v
1 `timescale 1ns/1ps
2
3 /*
4 This file contains simulation models for GreenPAK cells which are possible to fully model using synthesizeable
5 behavioral Verilog constructs only.
6 */
7
8 module GP_2LUT(input IN0, IN1, output OUT);
9 parameter [3:0] INIT = 0;
10 assign OUT = INIT[{IN1, IN0}];
11 endmodule
12
13 module GP_3LUT(input IN0, IN1, IN2, output OUT);
14 parameter [7:0] INIT = 0;
15 assign OUT = INIT[{IN2, IN1, IN0}];
16 endmodule
17
18 module GP_4LUT(
19 input wire IN0,
20 input wire IN1,
21 input wire IN2,
22 input wire IN3,
23 output wire OUT);
24
25 parameter [15:0] INIT = 0;
26 assign OUT = INIT[{IN3, IN2, IN1, IN0}];
27 endmodule
28
29 module GP_CLKBUF(input wire IN, output wire OUT);
30 assign OUT = IN;
31 endmodule
32
33 module GP_COUNT14(input CLK, input wire RST, output reg OUT);
34
35 parameter RESET_MODE = "RISING";
36
37 parameter COUNT_TO = 14'h1;
38 parameter CLKIN_DIVIDE = 1;
39
40 reg[13:0] count = COUNT_TO;
41
42 initial begin
43 if(CLKIN_DIVIDE != 1) begin
44 $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented");
45 $finish;
46 end
47 end
48
49 //Combinatorially output underflow flag whenever we wrap low
50 always @(*) begin
51 OUT <= (count == 14'h0);
52 end
53
54 //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm.
55 //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now.
56 generate
57 case(RESET_MODE)
58
59 "RISING": begin
60 always @(posedge CLK or posedge RST) begin
61 count <= count - 1'd1;
62 if(count == 0)
63 count <= COUNT_TO;
64
65 if(RST)
66 count <= 0;
67 end
68 end
69
70 "FALLING": begin
71 always @(posedge CLK or negedge RST) begin
72 count <= count - 1'd1;
73 if(count == 0)
74 count <= COUNT_TO;
75
76 if(!RST)
77 count <= 0;
78 end
79 end
80
81 "BOTH": begin
82 initial begin
83 $display("Both-edge reset mode for GP_COUNT8 not implemented");
84 $finish;
85 end
86 end
87
88 "LEVEL": begin
89 end
90
91 default: begin
92 initial begin
93 $display("Invalid RESET_MODE on GP_COUNT8");
94 $finish;
95 end
96 end
97
98 endcase
99 endgenerate
100
101 endmodule
102
103 module GP_COUNT14_ADV(input CLK, input RST, output reg OUT,
104 input UP, input KEEP, output reg[7:0] POUT);
105
106 parameter RESET_MODE = "RISING";
107 parameter RESET_VALUE = "ZERO";
108
109 parameter COUNT_TO = 14'h1;
110 parameter CLKIN_DIVIDE = 1;
111
112 initial begin
113 if(CLKIN_DIVIDE != 1) begin
114 $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented");
115 $finish;
116 end
117 end
118
119 //Combinatorially output underflow flag whenever we wrap low
120 always @(*) begin
121 if(UP)
122 OUT <= (count == 14'h4000);
123 else
124 OUT <= (count == 14'h0);
125 POUT <= count[7:0];
126 end
127
128 //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm.
129 //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now.
130 generate
131 case(RESET_MODE)
132
133 "RISING": begin
134 always @(posedge CLK or posedge RST) begin
135
136 //Main counter
137 if(KEEP) begin
138 end
139 else if(UP)
140 count <= count + 1'd1;
141 else
142 count <= count - 1'd1;
143
144 //Wrapping
145 if(count == 0 && !UP)
146 count <= COUNT_TO;
147 if(count == 14'h4000 && UP)
148 count <= COUNT_TO;
149
150 //Resets
151 if(RST) begin
152 if(RESET_VALUE == "ZERO")
153 count <= 0;
154 else
155 count <= COUNT_TO;
156 end
157
158 end
159 end
160
161 "FALLING": begin
162 always @(posedge CLK or negedge RST) begin
163
164 //Main counter
165 if(KEEP) begin
166 end
167 else if(UP)
168 count <= count + 1'd1;
169 else
170 count <= count - 1'd1;
171
172 //Wrapping
173 if(count == 0 && !UP)
174 count <= COUNT_TO;
175 if(count == 14'h4000 && UP)
176 count <= COUNT_TO;
177
178 //Resets
179 if(RST) begin
180 if(RESET_VALUE == "ZERO")
181 count <= 0;
182 else
183 count <= COUNT_TO;
184 end
185
186 end
187 end
188
189 "BOTH": begin
190 initial begin
191 $display("Both-edge reset mode for GP_COUNT14_ADV not implemented");
192 $finish;
193 end
194 end
195
196 "LEVEL": begin
197 end
198
199 default: begin
200 initial begin
201 $display("Invalid RESET_MODE on GP_COUNT14_ADV");
202 $finish;
203 end
204 end
205
206 endcase
207 endgenerate
208
209 endmodule
210
211 module GP_COUNT8_ADV(input CLK, input RST, output reg OUT,
212 input UP, input KEEP, output reg[7:0] POUT);
213
214 parameter RESET_MODE = "RISING";
215 parameter RESET_VALUE = "ZERO";
216
217 parameter COUNT_TO = 8'h1;
218 parameter CLKIN_DIVIDE = 1;
219
220 initial begin
221 if(CLKIN_DIVIDE != 1) begin
222 $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented");
223 $finish;
224 end
225 end
226
227 //Combinatorially output underflow flag whenever we wrap low
228 always @(*) begin
229 if(UP)
230 OUT <= (count == 8'hff);
231 else
232 OUT <= (count == 8'h0);
233 POUT <= count;
234 end
235
236 //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm.
237 //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now.
238 generate
239 case(RESET_MODE)
240
241 "RISING": begin
242 always @(posedge CLK or posedge RST) begin
243
244 //Main counter
245 if(KEEP) begin
246 end
247 else if(UP)
248 count <= count + 1'd1;
249 else
250 count <= count - 1'd1;
251
252 //Wrapping
253 if(count == 0 && !UP)
254 count <= COUNT_TO;
255 if(count == 8'hff && UP)
256 count <= COUNT_TO;
257
258 //Resets
259 if(RST) begin
260 if(RESET_VALUE == "ZERO")
261 count <= 0;
262 else
263 count <= COUNT_TO;
264 end
265
266 end
267 end
268
269 "FALLING": begin
270 always @(posedge CLK or negedge RST) begin
271
272 //Main counter
273 if(KEEP) begin
274 end
275 else if(UP)
276 count <= count + 1'd1;
277 else
278 count <= count - 1'd1;
279
280 //Wrapping
281 if(count == 0 && !UP)
282 count <= COUNT_TO;
283 if(count == 8'hff && UP)
284 count <= COUNT_TO;
285
286 //Resets
287 if(RST) begin
288 if(RESET_VALUE == "ZERO")
289 count <= 0;
290 else
291 count <= COUNT_TO;
292 end
293
294 end
295 end
296
297 "BOTH": begin
298 initial begin
299 $display("Both-edge reset mode for GP_COUNT8_ADV not implemented");
300 $finish;
301 end
302 end
303
304 "LEVEL": begin
305 end
306
307 default: begin
308 initial begin
309 $display("Invalid RESET_MODE on GP_COUNT8_ADV");
310 $finish;
311 end
312 end
313
314 endcase
315 endgenerate
316
317 endmodule
318
319 module GP_COUNT8(
320 input wire CLK,
321 input wire RST,
322 output reg OUT,
323 output reg[7:0] POUT);
324
325 parameter RESET_MODE = "RISING";
326
327 parameter COUNT_TO = 8'h1;
328 parameter CLKIN_DIVIDE = 1;
329
330 initial begin
331 if(CLKIN_DIVIDE != 1) begin
332 $display("ERROR: CLKIN_DIVIDE values other than 1 not implemented");
333 $finish;
334 end
335 end
336
337 reg[7:0] count = COUNT_TO;
338
339 //Combinatorially output underflow flag whenever we wrap low
340 always @(*) begin
341 OUT <= (count == 8'h0);
342 OUT <= count;
343 end
344
345 //POR or SYSRST reset value is COUNT_TO. Datasheet is unclear but conversations w/ Silego confirm.
346 //Runtime reset value is clearly 0 except in count/FSM cells where it's configurable but we leave at 0 for now.
347 generate
348 case(RESET_MODE)
349
350 "RISING": begin
351 always @(posedge CLK or posedge RST) begin
352 count <= count - 1'd1;
353 if(count == 0)
354 count <= COUNT_TO;
355
356 if(RST)
357 count <= 0;
358 end
359 end
360
361 "FALLING": begin
362 always @(posedge CLK or negedge RST) begin
363 count <= count - 1'd1;
364 if(count == 0)
365 count <= COUNT_TO;
366
367 if(!RST)
368 count <= 0;
369 end
370 end
371
372 "BOTH": begin
373 initial begin
374 $display("Both-edge reset mode for GP_COUNT8 not implemented");
375 $finish;
376 end
377 end
378
379 "LEVEL": begin
380 end
381
382 default: begin
383 initial begin
384 $display("Invalid RESET_MODE on GP_COUNT8");
385 $finish;
386 end
387 end
388
389 endcase
390 endgenerate
391
392 endmodule
393
394 module GP_DCMPREF(output reg[7:0]OUT);
395 parameter[7:0] REF_VAL = 8'h00;
396 initial OUT = REF_VAL;
397 endmodule
398
399 module GP_DCMPMUX(input[1:0] SEL, input[7:0] IN0, input[7:0] IN1, input[7:0] IN2, input[7:0] IN3, output reg[7:0] OUTA, output reg[7:0] OUTB);
400
401 always @(*) begin
402 case(SEL)
403 2'd00: begin
404 OUTA <= IN0;
405 OUTB <= IN3;
406 end
407
408 2'd01: begin
409 OUTA <= IN1;
410 OUTB <= IN2;
411 end
412
413 2'd02: begin
414 OUTA <= IN2;
415 OUTB <= IN1;
416 end
417
418 2'd03: begin
419 OUTA <= IN3;
420 OUTB <= IN0;
421 end
422
423 endcase
424 end
425 endmodule
426
427 module GP_DELAY(input IN, output reg OUT);
428
429 parameter DELAY_STEPS = 1;
430 parameter GLITCH_FILTER = 0;
431
432 initial OUT = 0;
433
434 generate
435
436 if(GLITCH_FILTER) begin
437 initial begin
438 $display("ERROR: GP_DELAY glitch filter mode not implemented");
439 $finish;
440 end
441 end
442
443 //TODO: These delays are PTV dependent! For now, hard code 3v3 timing
444 //Change simulation-mode delay depending on global Vdd range (how to specify this?)
445 always @(*) begin
446 case(DELAY_STEPS)
447 1: #166 OUT = IN;
448 2: #318 OUT = IN;
449 2: #471 OUT = IN;
450 3: #622 OUT = IN;
451 default: begin
452 $display("ERROR: GP_DELAY must have DELAY_STEPS in range [1,4]");
453 $finish;
454 end
455 endcase
456 end
457
458 endgenerate
459
460 endmodule
461
462 module GP_DFF(input D, CLK, output reg Q);
463 parameter [0:0] INIT = 1'bx;
464 initial Q = INIT;
465 always @(posedge CLK) begin
466 Q <= D;
467 end
468 endmodule
469
470 module GP_DFFI(input D, CLK, output reg nQ);
471 parameter [0:0] INIT = 1'bx;
472 initial nQ = INIT;
473 always @(posedge CLK) begin
474 nQ <= ~D;
475 end
476 endmodule
477
478 module GP_DFFR(input D, CLK, nRST, output reg Q);
479 parameter [0:0] INIT = 1'bx;
480 initial Q = INIT;
481 always @(posedge CLK, negedge nRST) begin
482 if (!nRST)
483 Q <= 1'b0;
484 else
485 Q <= D;
486 end
487 endmodule
488
489 module GP_DFFRI(input D, CLK, nRST, output reg nQ);
490 parameter [0:0] INIT = 1'bx;
491 initial nQ = INIT;
492 always @(posedge CLK, negedge nRST) begin
493 if (!nRST)
494 nQ <= 1'b1;
495 else
496 nQ <= ~D;
497 end
498 endmodule
499
500 module GP_DFFS(input D, CLK, nSET, output reg Q);
501 parameter [0:0] INIT = 1'bx;
502 initial Q = INIT;
503 always @(posedge CLK, negedge nSET) begin
504 if (!nSET)
505 Q <= 1'b1;
506 else
507 Q <= D;
508 end
509 endmodule
510
511 module GP_DFFSI(input D, CLK, nSET, output reg nQ);
512 parameter [0:0] INIT = 1'bx;
513 initial nQ = INIT;
514 always @(posedge CLK, negedge nSET) begin
515 if (!nSET)
516 nQ <= 1'b0;
517 else
518 nQ <= ~D;
519 end
520 endmodule
521
522 module GP_DFFSR(input D, CLK, nSR, output reg Q);
523 parameter [0:0] INIT = 1'bx;
524 parameter [0:0] SRMODE = 1'bx;
525 initial Q = INIT;
526 always @(posedge CLK, negedge nSR) begin
527 if (!nSR)
528 Q <= SRMODE;
529 else
530 Q <= D;
531 end
532 endmodule
533
534 module GP_DFFSRI(input D, CLK, nSR, output reg nQ);
535 parameter [0:0] INIT = 1'bx;
536 parameter [0:0] SRMODE = 1'bx;
537 initial nQ = INIT;
538 always @(posedge CLK, negedge nSR) begin
539 if (!nSR)
540 nQ <= ~SRMODE;
541 else
542 nQ <= ~D;
543 end
544 endmodule
545
546 module GP_DLATCH(input D, input nCLK, output reg Q);
547 parameter [0:0] INIT = 1'bx;
548 initial Q = INIT;
549 always @(*) begin
550 if(!nCLK)
551 Q <= D;
552 end
553 endmodule
554
555 module GP_DLATCHI(input D, input nCLK, output reg nQ);
556 parameter [0:0] INIT = 1'bx;
557 initial nQ = INIT;
558 always @(*) begin
559 if(!nCLK)
560 nQ <= ~D;
561 end
562 endmodule
563
564 module GP_DLATCHR(input D, input nCLK, input nRST, output reg Q);
565 parameter [0:0] INIT = 1'bx;
566 initial Q = INIT;
567 always @(*) begin
568 if(!nRST)
569 Q <= 1'b0;
570 else if(!nCLK)
571 Q <= D;
572 end
573 endmodule
574
575 module GP_DLATCHRI(input D, input nCLK, input nRST, output reg nQ);
576 parameter [0:0] INIT = 1'bx;
577 initial nQ = INIT;
578 always @(*) begin
579 if(!nRST)
580 nQ <= 1'b1;
581 else if(!nCLK)
582 nQ <= ~D;
583 end
584 endmodule
585
586 module GP_DLATCHS(input D, input nCLK, input nSET, output reg Q);
587 parameter [0:0] INIT = 1'bx;
588 initial Q = INIT;
589 always @(*) begin
590 if(!nSET)
591 Q <= 1'b1;
592 else if(!nCLK)
593 Q <= D;
594 end
595 endmodule
596
597 module GP_DLATCHSI(input D, input nCLK, input nSET, output reg nQ);
598 parameter [0:0] INIT = 1'bx;
599 initial nQ = INIT;
600 always @(*) begin
601 if(!nSET)
602 nQ <= 1'b0;
603 else if(!nCLK)
604 nQ <= ~D;
605 end
606 endmodule
607
608 module GP_DLATCHSR(input D, input nCLK, input nSR, output reg Q);
609 parameter [0:0] INIT = 1'bx;
610 parameter[0:0] SRMODE = 1'bx;
611 initial Q = INIT;
612 always @(*) begin
613 if(!nSR)
614 Q <= SRMODE;
615 else if(!nCLK)
616 Q <= D;
617 end
618 endmodule
619
620 module GP_DLATCHSRI(input D, input nCLK, input nSR, output reg nQ);
621 parameter [0:0] INIT = 1'bx;
622 parameter[0:0] SRMODE = 1'bx;
623 initial nQ = INIT;
624 always @(*) begin
625 if(!nSR)
626 nQ <= ~SRMODE;
627 else if(!nCLK)
628 nQ <= ~D;
629 end
630 endmodule
631
632 module GP_IBUF(input IN, output OUT);
633 assign OUT = IN;
634 endmodule
635
636 module GP_IOBUF(input IN, input OE, output OUT, inout IO);
637 assign OUT = IO;
638 assign IO = OE ? IN : 1'bz;
639 endmodule
640
641 module GP_INV(input IN, output OUT);
642 assign OUT = ~IN;
643 endmodule
644
645 module GP_OBUF(input IN, output OUT);
646 assign OUT = IN;
647 endmodule
648
649 module GP_OBUFT(input IN, input OE, output OUT);
650 assign OUT = OE ? IN : 1'bz;
651 endmodule
652
653 module GP_PGEN(input wire nRST, input wire CLK, output reg OUT);
654 initial OUT = 0;
655 parameter PATTERN_DATA = 16'h0;
656 parameter PATTERN_LEN = 5'd16;
657
658 reg[3:0] count = 0;
659 always @(posedge CLK) begin
660 if(!nRST)
661 OUT <= PATTERN_DATA[0];
662
663 else begin
664 count <= count + 1;
665 OUT <= PATTERN_DATA[count];
666
667 if( (count + 1) == PATTERN_LEN)
668 count <= 0;
669 end
670 end
671
672 endmodule
673
674 module GP_SHREG(input nRST, input CLK, input IN, output OUTA, output OUTB);
675
676 parameter OUTA_TAP = 1;
677 parameter OUTA_INVERT = 0;
678 parameter OUTB_TAP = 1;
679
680 reg[15:0] shreg = 0;
681
682 always @(posedge CLK, negedge nRST) begin
683
684 if(!nRST)
685 shreg = 0;
686
687 else
688 shreg <= {shreg[14:0], IN};
689
690 end
691
692 assign OUTA = (OUTA_INVERT) ? ~shreg[OUTA_TAP - 1] : shreg[OUTA_TAP - 1];
693 assign OUTB = shreg[OUTB_TAP - 1];
694
695 endmodule
696
697 module GP_VDD(output OUT);
698 assign OUT = 1;
699 endmodule
700
701 module GP_VSS(output OUT);
702 assign OUT = 0;
703 endmodule