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