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