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