1b67f3257abe56f9bddf6d629efeac9b39a86fb6
[yosys.git] / techlibs / common / simlib.v
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * ---
19 *
20 * The Simulation Library.
21 *
22 * This verilog library contains simple simulation models for the internal
23 * cells ($not, ...) generated by the frontends and used in most passes.
24 *
25 * This library can be used to verify the internal netlists as generated
26 * by the different frontends and passes.
27 *
28 * Note that memory can only be simulated when all $memrd and $memwr cells
29 * have been merged to stand-alone $mem cells (this is what the "memory_collect"
30 * pass is doing).
31 *
32 */
33
34 // --------------------------------------------------------
35
36 module \$not (A, Y);
37
38 parameter A_SIGNED = 0;
39 parameter A_WIDTH = 0;
40 parameter Y_WIDTH = 0;
41
42 input [A_WIDTH-1:0] A;
43 output [Y_WIDTH-1:0] Y;
44
45 generate
46 if (A_SIGNED) begin:BLOCK1
47 assign Y = ~$signed(A);
48 end else begin:BLOCK2
49 assign Y = ~A;
50 end
51 endgenerate
52
53 endmodule
54
55
56 // --------------------------------------------------------
57
58 module \$pos (A, Y);
59
60 parameter A_SIGNED = 0;
61 parameter A_WIDTH = 0;
62 parameter Y_WIDTH = 0;
63
64 input [A_WIDTH-1:0] A;
65 output [Y_WIDTH-1:0] Y;
66
67 generate
68 if (A_SIGNED) begin:BLOCK1
69 assign Y = $signed(A);
70 end else begin:BLOCK2
71 assign Y = A;
72 end
73 endgenerate
74
75 endmodule
76
77 // --------------------------------------------------------
78
79 module \$neg (A, Y);
80
81 parameter A_SIGNED = 0;
82 parameter A_WIDTH = 0;
83 parameter Y_WIDTH = 0;
84
85 input [A_WIDTH-1:0] A;
86 output [Y_WIDTH-1:0] Y;
87
88 generate
89 if (A_SIGNED) begin:BLOCK1
90 assign Y = -$signed(A);
91 end else begin:BLOCK2
92 assign Y = -A;
93 end
94 endgenerate
95
96 endmodule
97
98 // --------------------------------------------------------
99
100 module \$and (A, B, Y);
101
102 parameter A_SIGNED = 0;
103 parameter B_SIGNED = 0;
104 parameter A_WIDTH = 0;
105 parameter B_WIDTH = 0;
106 parameter Y_WIDTH = 0;
107
108 input [A_WIDTH-1:0] A;
109 input [B_WIDTH-1:0] B;
110 output [Y_WIDTH-1:0] Y;
111
112 generate
113 if (A_SIGNED && B_SIGNED) begin:BLOCK1
114 assign Y = $signed(A) & $signed(B);
115 end else begin:BLOCK2
116 assign Y = A & B;
117 end
118 endgenerate
119
120 endmodule
121
122 // --------------------------------------------------------
123
124 module \$or (A, B, Y);
125
126 parameter A_SIGNED = 0;
127 parameter B_SIGNED = 0;
128 parameter A_WIDTH = 0;
129 parameter B_WIDTH = 0;
130 parameter Y_WIDTH = 0;
131
132 input [A_WIDTH-1:0] A;
133 input [B_WIDTH-1:0] B;
134 output [Y_WIDTH-1:0] Y;
135
136 generate
137 if (A_SIGNED && B_SIGNED) begin:BLOCK1
138 assign Y = $signed(A) | $signed(B);
139 end else begin:BLOCK2
140 assign Y = A | B;
141 end
142 endgenerate
143
144 endmodule
145
146 // --------------------------------------------------------
147
148 module \$xor (A, B, Y);
149
150 parameter A_SIGNED = 0;
151 parameter B_SIGNED = 0;
152 parameter A_WIDTH = 0;
153 parameter B_WIDTH = 0;
154 parameter Y_WIDTH = 0;
155
156 input [A_WIDTH-1:0] A;
157 input [B_WIDTH-1:0] B;
158 output [Y_WIDTH-1:0] Y;
159
160 generate
161 if (A_SIGNED && B_SIGNED) begin:BLOCK1
162 assign Y = $signed(A) ^ $signed(B);
163 end else begin:BLOCK2
164 assign Y = A ^ B;
165 end
166 endgenerate
167
168 endmodule
169
170 // --------------------------------------------------------
171
172 module \$xnor (A, B, Y);
173
174 parameter A_SIGNED = 0;
175 parameter B_SIGNED = 0;
176 parameter A_WIDTH = 0;
177 parameter B_WIDTH = 0;
178 parameter Y_WIDTH = 0;
179
180 input [A_WIDTH-1:0] A;
181 input [B_WIDTH-1:0] B;
182 output [Y_WIDTH-1:0] Y;
183
184 generate
185 if (A_SIGNED && B_SIGNED) begin:BLOCK1
186 assign Y = $signed(A) ~^ $signed(B);
187 end else begin:BLOCK2
188 assign Y = A ~^ B;
189 end
190 endgenerate
191
192 endmodule
193
194 // --------------------------------------------------------
195
196 module \$reduce_and (A, Y);
197
198 parameter A_SIGNED = 0;
199 parameter A_WIDTH = 0;
200 parameter Y_WIDTH = 0;
201
202 input [A_WIDTH-1:0] A;
203 output [Y_WIDTH-1:0] Y;
204
205 generate
206 if (A_SIGNED) begin:BLOCK1
207 assign Y = &$signed(A);
208 end else begin:BLOCK2
209 assign Y = &A;
210 end
211 endgenerate
212
213 endmodule
214
215 // --------------------------------------------------------
216
217 module \$reduce_or (A, Y);
218
219 parameter A_SIGNED = 0;
220 parameter A_WIDTH = 0;
221 parameter Y_WIDTH = 0;
222
223 input [A_WIDTH-1:0] A;
224 output [Y_WIDTH-1:0] Y;
225
226 generate
227 if (A_SIGNED) begin:BLOCK1
228 assign Y = |$signed(A);
229 end else begin:BLOCK2
230 assign Y = |A;
231 end
232 endgenerate
233
234 endmodule
235
236 // --------------------------------------------------------
237
238 module \$reduce_xor (A, Y);
239
240 parameter A_SIGNED = 0;
241 parameter A_WIDTH = 0;
242 parameter Y_WIDTH = 0;
243
244 input [A_WIDTH-1:0] A;
245 output [Y_WIDTH-1:0] Y;
246
247 generate
248 if (A_SIGNED) begin:BLOCK1
249 assign Y = ^$signed(A);
250 end else begin:BLOCK2
251 assign Y = ^A;
252 end
253 endgenerate
254
255 endmodule
256
257 // --------------------------------------------------------
258
259 module \$reduce_xnor (A, Y);
260
261 parameter A_SIGNED = 0;
262 parameter A_WIDTH = 0;
263 parameter Y_WIDTH = 0;
264
265 input [A_WIDTH-1:0] A;
266 output [Y_WIDTH-1:0] Y;
267
268 generate
269 if (A_SIGNED) begin:BLOCK1
270 assign Y = ~^$signed(A);
271 end else begin:BLOCK2
272 assign Y = ~^A;
273 end
274 endgenerate
275
276 endmodule
277
278 // --------------------------------------------------------
279
280 module \$reduce_bool (A, Y);
281
282 parameter A_SIGNED = 0;
283 parameter A_WIDTH = 0;
284 parameter Y_WIDTH = 0;
285
286 input [A_WIDTH-1:0] A;
287 output [Y_WIDTH-1:0] Y;
288
289 generate
290 if (A_SIGNED) begin:BLOCK1
291 assign Y = !(!$signed(A));
292 end else begin:BLOCK2
293 assign Y = !(!A);
294 end
295 endgenerate
296
297 endmodule
298
299 // --------------------------------------------------------
300
301 module \$shl (A, B, Y);
302
303 parameter A_SIGNED = 0;
304 parameter B_SIGNED = 0;
305 parameter A_WIDTH = 0;
306 parameter B_WIDTH = 0;
307 parameter Y_WIDTH = 0;
308
309 input [A_WIDTH-1:0] A;
310 input [B_WIDTH-1:0] B;
311 output [Y_WIDTH-1:0] Y;
312
313 generate
314 if (A_SIGNED) begin:BLOCK1
315 assign Y = $signed(A) << B;
316 end else begin:BLOCK2
317 assign Y = A << B;
318 end
319 endgenerate
320
321 endmodule
322
323 // --------------------------------------------------------
324
325 module \$shr (A, B, Y);
326
327 parameter A_SIGNED = 0;
328 parameter B_SIGNED = 0;
329 parameter A_WIDTH = 0;
330 parameter B_WIDTH = 0;
331 parameter Y_WIDTH = 0;
332
333 input [A_WIDTH-1:0] A;
334 input [B_WIDTH-1:0] B;
335 output [Y_WIDTH-1:0] Y;
336
337 generate
338 if (A_SIGNED) begin:BLOCK1
339 assign Y = $signed(A) >> B;
340 end else begin:BLOCK2
341 assign Y = A >> B;
342 end
343 endgenerate
344
345 endmodule
346
347 // --------------------------------------------------------
348
349 module \$sshl (A, B, Y);
350
351 parameter A_SIGNED = 0;
352 parameter B_SIGNED = 0;
353 parameter A_WIDTH = 0;
354 parameter B_WIDTH = 0;
355 parameter Y_WIDTH = 0;
356
357 input [A_WIDTH-1:0] A;
358 input [B_WIDTH-1:0] B;
359 output [Y_WIDTH-1:0] Y;
360
361 generate
362 if (A_SIGNED) begin:BLOCK1
363 assign Y = $signed(A) <<< B;
364 end else begin:BLOCK2
365 assign Y = A <<< B;
366 end
367 endgenerate
368
369 endmodule
370
371 // --------------------------------------------------------
372
373 module \$sshr (A, B, Y);
374
375 parameter A_SIGNED = 0;
376 parameter B_SIGNED = 0;
377 parameter A_WIDTH = 0;
378 parameter B_WIDTH = 0;
379 parameter Y_WIDTH = 0;
380
381 input [A_WIDTH-1:0] A;
382 input [B_WIDTH-1:0] B;
383 output [Y_WIDTH-1:0] Y;
384
385 generate
386 if (A_SIGNED) begin:BLOCK1
387 assign Y = $signed(A) >>> B;
388 end else begin:BLOCK2
389 assign Y = A >>> B;
390 end
391 endgenerate
392
393 endmodule
394
395 // --------------------------------------------------------
396
397 module \$shift (A, B, Y);
398
399 parameter A_SIGNED = 0;
400 parameter B_SIGNED = 0;
401 parameter A_WIDTH = 0;
402 parameter B_WIDTH = 0;
403 parameter Y_WIDTH = 0;
404
405 input [A_WIDTH-1:0] A;
406 input [B_WIDTH-1:0] B;
407 output [Y_WIDTH-1:0] Y;
408
409 generate
410 if (B_SIGNED) begin:BLOCK1
411 assign Y = $signed(B) < 0 ? A << -B : A >> B;
412 end else begin:BLOCK2
413 assign Y = A >> B;
414 end
415 endgenerate
416
417 endmodule
418
419 // --------------------------------------------------------
420
421 module \$shiftx (A, B, Y);
422
423 parameter A_SIGNED = 0;
424 parameter B_SIGNED = 0;
425 parameter A_WIDTH = 0;
426 parameter B_WIDTH = 0;
427 parameter Y_WIDTH = 0;
428
429 input [A_WIDTH-1:0] A;
430 input [B_WIDTH-1:0] B;
431 output [Y_WIDTH-1:0] Y;
432
433 generate
434 if (Y_WIDTH > 0)
435 if (B_SIGNED) begin:BLOCK1
436 assign Y = A[$signed(B) +: Y_WIDTH];
437 end else begin:BLOCK2
438 assign Y = A[B +: Y_WIDTH];
439 end
440 endgenerate
441
442 endmodule
443
444 // --------------------------------------------------------
445
446 module \$fa (A, B, C, X, Y);
447
448 parameter WIDTH = 1;
449
450 input [WIDTH-1:0] A, B, C;
451 output [WIDTH-1:0] X, Y;
452
453 wire [WIDTH-1:0] t1, t2, t3;
454
455 assign t1 = A ^ B, t2 = A & B, t3 = C & t1;
456 assign Y = t1 ^ C, X = t2 | t3;
457
458 endmodule
459
460 // --------------------------------------------------------
461
462 module \$lcu (P, G, CI, CO);
463
464 parameter WIDTH = 1;
465
466 input [WIDTH-1:0] P, G;
467 input CI;
468
469 output reg [WIDTH-1:0] CO;
470
471 integer i;
472 always @* begin
473 CO = 'bx;
474 if (^{P, G, CI} !== 1'bx) begin
475 CO[0] = G[0] || (P[0] && CI);
476 for (i = 1; i < WIDTH; i = i+1)
477 CO[i] = G[i] || (P[i] && CO[i-1]);
478 end
479 end
480
481 endmodule
482
483 // --------------------------------------------------------
484
485 module \$alu (A, B, CI, BI, X, Y, CO);
486
487 parameter A_SIGNED = 0;
488 parameter B_SIGNED = 0;
489 parameter A_WIDTH = 1;
490 parameter B_WIDTH = 1;
491 parameter Y_WIDTH = 1;
492
493 input [A_WIDTH-1:0] A;
494 input [B_WIDTH-1:0] B;
495 output [Y_WIDTH-1:0] X, Y;
496
497 input CI, BI;
498 output [Y_WIDTH-1:0] CO;
499
500 wire [Y_WIDTH-1:0] AA, BB;
501
502 generate
503 if (A_SIGNED && B_SIGNED) begin:BLOCK1
504 assign AA = $signed(A), BB = BI ? ~$signed(B) : $signed(B);
505 end else begin:BLOCK2
506 assign AA = $unsigned(A), BB = BI ? ~$unsigned(B) : $unsigned(B);
507 end
508 endgenerate
509
510 // this is 'x' if Y and CO should be all 'x', and '0' otherwise
511 wire y_co_undef = ^{A, A, B, B, CI, CI, BI, BI};
512
513 assign X = AA ^ BB;
514 assign Y = (AA + BB + CI) ^ {Y_WIDTH{y_co_undef}};
515
516 function get_carry;
517 input a, b, c;
518 get_carry = (a&b) | (a&c) | (b&c);
519 endfunction
520
521 genvar i;
522 generate
523 assign CO[0] = get_carry(AA[0], BB[0], CI) ^ y_co_undef;
524 for (i = 1; i < Y_WIDTH; i = i+1) begin:BLOCK3
525 assign CO[i] = get_carry(AA[i], BB[i], CO[i-1]) ^ y_co_undef;
526 end
527 endgenerate
528
529 endmodule
530
531 // --------------------------------------------------------
532
533 module \$lt (A, B, Y);
534
535 parameter A_SIGNED = 0;
536 parameter B_SIGNED = 0;
537 parameter A_WIDTH = 0;
538 parameter B_WIDTH = 0;
539 parameter Y_WIDTH = 0;
540
541 input [A_WIDTH-1:0] A;
542 input [B_WIDTH-1:0] B;
543 output [Y_WIDTH-1:0] Y;
544
545 generate
546 if (A_SIGNED && B_SIGNED) begin:BLOCK1
547 assign Y = $signed(A) < $signed(B);
548 end else begin:BLOCK2
549 assign Y = A < B;
550 end
551 endgenerate
552
553 endmodule
554
555 // --------------------------------------------------------
556
557 module \$le (A, B, Y);
558
559 parameter A_SIGNED = 0;
560 parameter B_SIGNED = 0;
561 parameter A_WIDTH = 0;
562 parameter B_WIDTH = 0;
563 parameter Y_WIDTH = 0;
564
565 input [A_WIDTH-1:0] A;
566 input [B_WIDTH-1:0] B;
567 output [Y_WIDTH-1:0] Y;
568
569 generate
570 if (A_SIGNED && B_SIGNED) begin:BLOCK1
571 assign Y = $signed(A) <= $signed(B);
572 end else begin:BLOCK2
573 assign Y = A <= B;
574 end
575 endgenerate
576
577 endmodule
578
579 // --------------------------------------------------------
580
581 module \$eq (A, B, Y);
582
583 parameter A_SIGNED = 0;
584 parameter B_SIGNED = 0;
585 parameter A_WIDTH = 0;
586 parameter B_WIDTH = 0;
587 parameter Y_WIDTH = 0;
588
589 input [A_WIDTH-1:0] A;
590 input [B_WIDTH-1:0] B;
591 output [Y_WIDTH-1:0] Y;
592
593 generate
594 if (A_SIGNED && B_SIGNED) begin:BLOCK1
595 assign Y = $signed(A) == $signed(B);
596 end else begin:BLOCK2
597 assign Y = A == B;
598 end
599 endgenerate
600
601 endmodule
602
603 // --------------------------------------------------------
604
605 module \$ne (A, B, Y);
606
607 parameter A_SIGNED = 0;
608 parameter B_SIGNED = 0;
609 parameter A_WIDTH = 0;
610 parameter B_WIDTH = 0;
611 parameter Y_WIDTH = 0;
612
613 input [A_WIDTH-1:0] A;
614 input [B_WIDTH-1:0] B;
615 output [Y_WIDTH-1:0] Y;
616
617 generate
618 if (A_SIGNED && B_SIGNED) begin:BLOCK1
619 assign Y = $signed(A) != $signed(B);
620 end else begin:BLOCK2
621 assign Y = A != B;
622 end
623 endgenerate
624
625 endmodule
626
627 // --------------------------------------------------------
628
629 module \$eqx (A, B, Y);
630
631 parameter A_SIGNED = 0;
632 parameter B_SIGNED = 0;
633 parameter A_WIDTH = 0;
634 parameter B_WIDTH = 0;
635 parameter Y_WIDTH = 0;
636
637 input [A_WIDTH-1:0] A;
638 input [B_WIDTH-1:0] B;
639 output [Y_WIDTH-1:0] Y;
640
641 generate
642 if (A_SIGNED && B_SIGNED) begin:BLOCK1
643 assign Y = $signed(A) === $signed(B);
644 end else begin:BLOCK2
645 assign Y = A === B;
646 end
647 endgenerate
648
649 endmodule
650
651 // --------------------------------------------------------
652
653 module \$nex (A, B, Y);
654
655 parameter A_SIGNED = 0;
656 parameter B_SIGNED = 0;
657 parameter A_WIDTH = 0;
658 parameter B_WIDTH = 0;
659 parameter Y_WIDTH = 0;
660
661 input [A_WIDTH-1:0] A;
662 input [B_WIDTH-1:0] B;
663 output [Y_WIDTH-1:0] Y;
664
665 generate
666 if (A_SIGNED && B_SIGNED) begin:BLOCK1
667 assign Y = $signed(A) !== $signed(B);
668 end else begin:BLOCK2
669 assign Y = A !== B;
670 end
671 endgenerate
672
673 endmodule
674
675 // --------------------------------------------------------
676
677 module \$ge (A, B, Y);
678
679 parameter A_SIGNED = 0;
680 parameter B_SIGNED = 0;
681 parameter A_WIDTH = 0;
682 parameter B_WIDTH = 0;
683 parameter Y_WIDTH = 0;
684
685 input [A_WIDTH-1:0] A;
686 input [B_WIDTH-1:0] B;
687 output [Y_WIDTH-1:0] Y;
688
689 generate
690 if (A_SIGNED && B_SIGNED) begin:BLOCK1
691 assign Y = $signed(A) >= $signed(B);
692 end else begin:BLOCK2
693 assign Y = A >= B;
694 end
695 endgenerate
696
697 endmodule
698
699 // --------------------------------------------------------
700
701 module \$gt (A, B, Y);
702
703 parameter A_SIGNED = 0;
704 parameter B_SIGNED = 0;
705 parameter A_WIDTH = 0;
706 parameter B_WIDTH = 0;
707 parameter Y_WIDTH = 0;
708
709 input [A_WIDTH-1:0] A;
710 input [B_WIDTH-1:0] B;
711 output [Y_WIDTH-1:0] Y;
712
713 generate
714 if (A_SIGNED && B_SIGNED) begin:BLOCK1
715 assign Y = $signed(A) > $signed(B);
716 end else begin:BLOCK2
717 assign Y = A > B;
718 end
719 endgenerate
720
721 endmodule
722
723 // --------------------------------------------------------
724
725 module \$add (A, B, Y);
726
727 parameter A_SIGNED = 0;
728 parameter B_SIGNED = 0;
729 parameter A_WIDTH = 0;
730 parameter B_WIDTH = 0;
731 parameter Y_WIDTH = 0;
732
733 input [A_WIDTH-1:0] A;
734 input [B_WIDTH-1:0] B;
735 output [Y_WIDTH-1:0] Y;
736
737 generate
738 if (A_SIGNED && B_SIGNED) begin:BLOCK1
739 assign Y = $signed(A) + $signed(B);
740 end else begin:BLOCK2
741 assign Y = A + B;
742 end
743 endgenerate
744
745 endmodule
746
747 // --------------------------------------------------------
748
749 module \$sub (A, B, Y);
750
751 parameter A_SIGNED = 0;
752 parameter B_SIGNED = 0;
753 parameter A_WIDTH = 0;
754 parameter B_WIDTH = 0;
755 parameter Y_WIDTH = 0;
756
757 input [A_WIDTH-1:0] A;
758 input [B_WIDTH-1:0] B;
759 output [Y_WIDTH-1:0] Y;
760
761 generate
762 if (A_SIGNED && B_SIGNED) begin:BLOCK1
763 assign Y = $signed(A) - $signed(B);
764 end else begin:BLOCK2
765 assign Y = A - B;
766 end
767 endgenerate
768
769 endmodule
770
771 // --------------------------------------------------------
772
773 module \$mul (A, B, Y);
774
775 parameter A_SIGNED = 0;
776 parameter B_SIGNED = 0;
777 parameter A_WIDTH = 0;
778 parameter B_WIDTH = 0;
779 parameter Y_WIDTH = 0;
780
781 input [A_WIDTH-1:0] A;
782 input [B_WIDTH-1:0] B;
783 output [Y_WIDTH-1:0] Y;
784
785 generate
786 if (A_SIGNED && B_SIGNED) begin:BLOCK1
787 assign Y = $signed(A) * $signed(B);
788 end else begin:BLOCK2
789 assign Y = A * B;
790 end
791 endgenerate
792
793 endmodule
794
795 // --------------------------------------------------------
796
797 module \$macc (A, B, Y);
798 parameter A_WIDTH = 0;
799 parameter B_WIDTH = 0;
800 parameter Y_WIDTH = 0;
801 parameter CONFIG = 4'b0000;
802 parameter CONFIG_WIDTH = 4;
803
804 input [A_WIDTH-1:0] A;
805 input [B_WIDTH-1:0] B;
806 output reg [Y_WIDTH-1:0] Y;
807
808 localparam integer num_bits = CONFIG[3:0];
809 localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits);
810 localparam integer num_abits = $clog2(A_WIDTH) > 0 ? $clog2(A_WIDTH) : 1;
811
812 function [2*num_ports*num_abits-1:0] get_port_offsets;
813 input [CONFIG_WIDTH-1:0] cfg;
814 integer i, cursor;
815 begin
816 cursor = 0;
817 get_port_offsets = 0;
818 for (i = 0; i < num_ports; i = i+1) begin
819 get_port_offsets[(2*i + 0)*num_abits +: num_abits] = cursor;
820 cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 +: num_bits];
821 get_port_offsets[(2*i + 1)*num_abits +: num_abits] = cursor;
822 cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits];
823 end
824 end
825 endfunction
826
827 localparam [2*num_ports*num_abits-1:0] port_offsets = get_port_offsets(CONFIG);
828
829 `define PORT_IS_SIGNED (0 + CONFIG[4 + i*(2 + 2*num_bits)])
830 `define PORT_DO_SUBTRACT (0 + CONFIG[4 + i*(2 + 2*num_bits) + 1])
831 `define PORT_SIZE_A (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits])
832 `define PORT_SIZE_B (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits])
833 `define PORT_OFFSET_A (0 + port_offsets[2*i*num_abits +: num_abits])
834 `define PORT_OFFSET_B (0 + port_offsets[2*i*num_abits + num_abits +: num_abits])
835
836 integer i, j;
837 reg [Y_WIDTH-1:0] tmp_a, tmp_b;
838
839 always @* begin
840 Y = 0;
841 for (i = 0; i < num_ports; i = i+1)
842 begin
843 tmp_a = 0;
844 tmp_b = 0;
845
846 for (j = 0; j < `PORT_SIZE_A; j = j+1)
847 tmp_a[j] = A[`PORT_OFFSET_A + j];
848
849 if (`PORT_IS_SIGNED && `PORT_SIZE_A > 0)
850 for (j = `PORT_SIZE_A; j < Y_WIDTH; j = j+1)
851 tmp_a[j] = tmp_a[`PORT_SIZE_A-1];
852
853 for (j = 0; j < `PORT_SIZE_B; j = j+1)
854 tmp_b[j] = A[`PORT_OFFSET_B + j];
855
856 if (`PORT_IS_SIGNED && `PORT_SIZE_B > 0)
857 for (j = `PORT_SIZE_B; j < Y_WIDTH; j = j+1)
858 tmp_b[j] = tmp_b[`PORT_SIZE_B-1];
859
860 if (`PORT_SIZE_B > 0)
861 tmp_a = tmp_a * tmp_b;
862
863 if (`PORT_DO_SUBTRACT)
864 Y = Y - tmp_a;
865 else
866 Y = Y + tmp_a;
867 end
868 for (i = 0; i < B_WIDTH; i = i+1) begin
869 Y = Y + B[i];
870 end
871 end
872
873 `undef PORT_IS_SIGNED
874 `undef PORT_DO_SUBTRACT
875 `undef PORT_SIZE_A
876 `undef PORT_SIZE_B
877 `undef PORT_OFFSET_A
878 `undef PORT_OFFSET_B
879 endmodule
880
881 // --------------------------------------------------------
882
883 module \$div (A, B, Y);
884
885 parameter A_SIGNED = 0;
886 parameter B_SIGNED = 0;
887 parameter A_WIDTH = 0;
888 parameter B_WIDTH = 0;
889 parameter Y_WIDTH = 0;
890
891 input [A_WIDTH-1:0] A;
892 input [B_WIDTH-1:0] B;
893 output [Y_WIDTH-1:0] Y;
894
895 generate
896 if (A_SIGNED && B_SIGNED) begin:BLOCK1
897 assign Y = $signed(A) / $signed(B);
898 end else begin:BLOCK2
899 assign Y = A / B;
900 end
901 endgenerate
902
903 endmodule
904
905 // --------------------------------------------------------
906
907 module \$mod (A, B, Y);
908
909 parameter A_SIGNED = 0;
910 parameter B_SIGNED = 0;
911 parameter A_WIDTH = 0;
912 parameter B_WIDTH = 0;
913 parameter Y_WIDTH = 0;
914
915 input [A_WIDTH-1:0] A;
916 input [B_WIDTH-1:0] B;
917 output [Y_WIDTH-1:0] Y;
918
919 generate
920 if (A_SIGNED && B_SIGNED) begin:BLOCK1
921 assign Y = $signed(A) % $signed(B);
922 end else begin:BLOCK2
923 assign Y = A % B;
924 end
925 endgenerate
926
927 endmodule
928
929 // --------------------------------------------------------
930 `ifndef SIMLIB_NOPOW
931
932 module \$pow (A, B, Y);
933
934 parameter A_SIGNED = 0;
935 parameter B_SIGNED = 0;
936 parameter A_WIDTH = 0;
937 parameter B_WIDTH = 0;
938 parameter Y_WIDTH = 0;
939
940 input [A_WIDTH-1:0] A;
941 input [B_WIDTH-1:0] B;
942 output [Y_WIDTH-1:0] Y;
943
944 generate
945 if (A_SIGNED && B_SIGNED) begin:BLOCK1
946 assign Y = $signed(A) ** $signed(B);
947 end else if (A_SIGNED) begin:BLOCK2
948 assign Y = $signed(A) ** B;
949 end else if (B_SIGNED) begin:BLOCK3
950 assign Y = A ** $signed(B);
951 end else begin:BLOCK4
952 assign Y = A ** B;
953 end
954 endgenerate
955
956 endmodule
957
958 `endif
959 // --------------------------------------------------------
960
961 module \$logic_not (A, Y);
962
963 parameter A_SIGNED = 0;
964 parameter A_WIDTH = 0;
965 parameter Y_WIDTH = 0;
966
967 input [A_WIDTH-1:0] A;
968 output [Y_WIDTH-1:0] Y;
969
970 generate
971 if (A_SIGNED) begin:BLOCK1
972 assign Y = !$signed(A);
973 end else begin:BLOCK2
974 assign Y = !A;
975 end
976 endgenerate
977
978 endmodule
979
980 // --------------------------------------------------------
981
982 module \$logic_and (A, B, Y);
983
984 parameter A_SIGNED = 0;
985 parameter B_SIGNED = 0;
986 parameter A_WIDTH = 0;
987 parameter B_WIDTH = 0;
988 parameter Y_WIDTH = 0;
989
990 input [A_WIDTH-1:0] A;
991 input [B_WIDTH-1:0] B;
992 output [Y_WIDTH-1:0] Y;
993
994 generate
995 if (A_SIGNED && B_SIGNED) begin:BLOCK1
996 assign Y = $signed(A) && $signed(B);
997 end else begin:BLOCK2
998 assign Y = A && B;
999 end
1000 endgenerate
1001
1002 endmodule
1003
1004 // --------------------------------------------------------
1005
1006 module \$logic_or (A, B, Y);
1007
1008 parameter A_SIGNED = 0;
1009 parameter B_SIGNED = 0;
1010 parameter A_WIDTH = 0;
1011 parameter B_WIDTH = 0;
1012 parameter Y_WIDTH = 0;
1013
1014 input [A_WIDTH-1:0] A;
1015 input [B_WIDTH-1:0] B;
1016 output [Y_WIDTH-1:0] Y;
1017
1018 generate
1019 if (A_SIGNED && B_SIGNED) begin:BLOCK1
1020 assign Y = $signed(A) || $signed(B);
1021 end else begin:BLOCK2
1022 assign Y = A || B;
1023 end
1024 endgenerate
1025
1026 endmodule
1027
1028 // --------------------------------------------------------
1029
1030 module \$slice (A, Y);
1031
1032 parameter OFFSET = 0;
1033 parameter A_WIDTH = 0;
1034 parameter Y_WIDTH = 0;
1035
1036 input [A_WIDTH-1:0] A;
1037 output [Y_WIDTH-1:0] Y;
1038
1039 assign Y = A >> OFFSET;
1040
1041 endmodule
1042
1043 // --------------------------------------------------------
1044
1045 module \$concat (A, B, Y);
1046
1047 parameter A_WIDTH = 0;
1048 parameter B_WIDTH = 0;
1049
1050 input [A_WIDTH-1:0] A;
1051 input [B_WIDTH-1:0] B;
1052 output [A_WIDTH+B_WIDTH-1:0] Y;
1053
1054 assign Y = {B, A};
1055
1056 endmodule
1057
1058 // --------------------------------------------------------
1059
1060 module \$mux (A, B, S, Y);
1061
1062 parameter WIDTH = 0;
1063
1064 input [WIDTH-1:0] A, B;
1065 input S;
1066 output reg [WIDTH-1:0] Y;
1067
1068 always @* begin
1069 if (S)
1070 Y = B;
1071 else
1072 Y = A;
1073 end
1074
1075 endmodule
1076
1077 // --------------------------------------------------------
1078
1079 module \$pmux (A, B, S, Y);
1080
1081 parameter WIDTH = 0;
1082 parameter S_WIDTH = 0;
1083
1084 input [WIDTH-1:0] A;
1085 input [WIDTH*S_WIDTH-1:0] B;
1086 input [S_WIDTH-1:0] S;
1087 output reg [WIDTH-1:0] Y;
1088
1089 integer i;
1090 reg found_active_sel_bit;
1091
1092 always @* begin
1093 Y = A;
1094 found_active_sel_bit = 0;
1095 for (i = 0; i < S_WIDTH; i = i+1)
1096 if (S[i]) begin
1097 Y = found_active_sel_bit ? 'bx : B >> (WIDTH*i);
1098 found_active_sel_bit = 1;
1099 end
1100 end
1101
1102 endmodule
1103
1104 // --------------------------------------------------------
1105 `ifndef SIMLIB_NOLUT
1106
1107 module \$lut (A, Y);
1108
1109 parameter WIDTH = 0;
1110 parameter LUT = 0;
1111
1112 input [WIDTH-1:0] A;
1113 output reg Y;
1114
1115 wire lut0_out, lut1_out;
1116
1117 generate
1118 if (WIDTH <= 1) begin:simple
1119 assign {lut1_out, lut0_out} = LUT;
1120 end else begin:complex
1121 \$lut #( .WIDTH(WIDTH-1), .LUT(LUT ) ) lut0 ( .A(A[WIDTH-2:0]), .Y(lut0_out) );
1122 \$lut #( .WIDTH(WIDTH-1), .LUT(LUT >> (2**(WIDTH-1))) ) lut1 ( .A(A[WIDTH-2:0]), .Y(lut1_out) );
1123 end
1124
1125 if (WIDTH > 0) begin:lutlogic
1126 always @* begin
1127 casez ({A[WIDTH-1], lut0_out, lut1_out})
1128 3'b?11: Y = 1'b1;
1129 3'b?00: Y = 1'b0;
1130 3'b0??: Y = lut0_out;
1131 3'b1??: Y = lut1_out;
1132 default: Y = 1'bx;
1133 endcase
1134 end
1135 end
1136 endgenerate
1137
1138 endmodule
1139
1140 `endif
1141 // --------------------------------------------------------
1142
1143 module \$assert (A, EN);
1144
1145 input A, EN;
1146
1147 always @* begin
1148 if (A !== 1'b1 && EN === 1'b1) begin
1149 $display("Assertation failed!");
1150 $finish;
1151 end
1152 end
1153
1154 endmodule
1155
1156 // --------------------------------------------------------
1157 `ifndef SIMLIB_NOSR
1158
1159 module \$sr (SET, CLR, Q);
1160
1161 parameter WIDTH = 0;
1162 parameter SET_POLARITY = 1'b1;
1163 parameter CLR_POLARITY = 1'b1;
1164
1165 input [WIDTH-1:0] SET, CLR;
1166 output reg [WIDTH-1:0] Q;
1167
1168 wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET;
1169 wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
1170
1171 genvar i;
1172 generate
1173 for (i = 0; i < WIDTH; i = i+1) begin:bit
1174 always @(posedge pos_set[i], posedge pos_clr[i])
1175 if (pos_clr[i])
1176 Q[i] <= 0;
1177 else if (pos_set[i])
1178 Q[i] <= 1;
1179 end
1180 endgenerate
1181
1182 endmodule
1183
1184 `endif
1185 // --------------------------------------------------------
1186
1187 module \$dff (CLK, D, Q);
1188
1189 parameter WIDTH = 0;
1190 parameter CLK_POLARITY = 1'b1;
1191
1192 input CLK;
1193 input [WIDTH-1:0] D;
1194 output reg [WIDTH-1:0] Q;
1195 wire pos_clk = CLK == CLK_POLARITY;
1196
1197 always @(posedge pos_clk) begin
1198 Q <= D;
1199 end
1200
1201 endmodule
1202
1203 // --------------------------------------------------------
1204 `ifndef SIMLIB_NOSR
1205
1206 module \$dffsr (CLK, SET, CLR, D, Q);
1207
1208 parameter WIDTH = 0;
1209 parameter CLK_POLARITY = 1'b1;
1210 parameter SET_POLARITY = 1'b1;
1211 parameter CLR_POLARITY = 1'b1;
1212
1213 input CLK;
1214 input [WIDTH-1:0] SET, CLR, D;
1215 output reg [WIDTH-1:0] Q;
1216
1217 wire pos_clk = CLK == CLK_POLARITY;
1218 wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET;
1219 wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
1220
1221 genvar i;
1222 generate
1223 for (i = 0; i < WIDTH; i = i+1) begin:bit
1224 always @(posedge pos_set[i], posedge pos_clr[i], posedge pos_clk)
1225 if (pos_clr[i])
1226 Q[i] <= 0;
1227 else if (pos_set[i])
1228 Q[i] <= 1;
1229 else
1230 Q[i] <= D[i];
1231 end
1232 endgenerate
1233
1234 endmodule
1235
1236 `endif
1237 // --------------------------------------------------------
1238
1239 module \$adff (CLK, ARST, D, Q);
1240
1241 parameter WIDTH = 0;
1242 parameter CLK_POLARITY = 1'b1;
1243 parameter ARST_POLARITY = 1'b1;
1244 parameter ARST_VALUE = 0;
1245
1246 input CLK, ARST;
1247 input [WIDTH-1:0] D;
1248 output reg [WIDTH-1:0] Q;
1249 wire pos_clk = CLK == CLK_POLARITY;
1250 wire pos_arst = ARST == ARST_POLARITY;
1251
1252 always @(posedge pos_clk, posedge pos_arst) begin
1253 if (pos_arst)
1254 Q <= ARST_VALUE;
1255 else
1256 Q <= D;
1257 end
1258
1259 endmodule
1260
1261 // --------------------------------------------------------
1262
1263 module \$dlatch (EN, D, Q);
1264
1265 parameter WIDTH = 0;
1266 parameter EN_POLARITY = 1'b1;
1267
1268 input EN;
1269 input [WIDTH-1:0] D;
1270 output reg [WIDTH-1:0] Q;
1271
1272 always @* begin
1273 if (EN == EN_POLARITY)
1274 Q <= D;
1275 end
1276
1277 endmodule
1278
1279 // --------------------------------------------------------
1280 `ifndef SIMLIB_NOSR
1281
1282 module \$dlatchsr (EN, SET, CLR, D, Q);
1283
1284 parameter WIDTH = 0;
1285 parameter EN_POLARITY = 1'b1;
1286 parameter SET_POLARITY = 1'b1;
1287 parameter CLR_POLARITY = 1'b1;
1288
1289 input EN;
1290 input [WIDTH-1:0] SET, CLR, D;
1291 output reg [WIDTH-1:0] Q;
1292
1293 wire pos_en = EN == EN_POLARITY;
1294 wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET;
1295 wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
1296
1297 genvar i;
1298 generate
1299 for (i = 0; i < WIDTH; i = i+1) begin:bit
1300 always @*
1301 if (pos_clr[i])
1302 Q[i] <= 0;
1303 else if (pos_set[i])
1304 Q[i] <= 1;
1305 else if (pos_en)
1306 Q[i] <= D[i];
1307 end
1308 endgenerate
1309
1310 endmodule
1311
1312 `endif
1313 // --------------------------------------------------------
1314
1315 module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT);
1316
1317 parameter NAME = "";
1318
1319 parameter CLK_POLARITY = 1'b1;
1320 parameter ARST_POLARITY = 1'b1;
1321
1322 parameter CTRL_IN_WIDTH = 1;
1323 parameter CTRL_OUT_WIDTH = 1;
1324
1325 parameter STATE_BITS = 1;
1326 parameter STATE_NUM = 1;
1327 parameter STATE_NUM_LOG2 = 1;
1328 parameter STATE_RST = 0;
1329 parameter STATE_TABLE = 1'b0;
1330
1331 parameter TRANS_NUM = 1;
1332 parameter TRANS_TABLE = 4'b0x0x;
1333
1334 input CLK, ARST;
1335 input [CTRL_IN_WIDTH-1:0] CTRL_IN;
1336 output reg [CTRL_OUT_WIDTH-1:0] CTRL_OUT;
1337
1338 wire pos_clk = CLK == CLK_POLARITY;
1339 wire pos_arst = ARST == ARST_POLARITY;
1340
1341 reg [STATE_BITS-1:0] state;
1342 reg [STATE_BITS-1:0] state_tmp;
1343 reg [STATE_BITS-1:0] next_state;
1344
1345 reg [STATE_BITS-1:0] tr_state_in;
1346 reg [STATE_BITS-1:0] tr_state_out;
1347 reg [CTRL_IN_WIDTH-1:0] tr_ctrl_in;
1348 reg [CTRL_OUT_WIDTH-1:0] tr_ctrl_out;
1349
1350 integer i;
1351
1352 task tr_fetch;
1353 input [31:0] tr_num;
1354 reg [31:0] tr_pos;
1355 reg [STATE_NUM_LOG2-1:0] state_num;
1356 begin
1357 tr_pos = (2*STATE_NUM_LOG2+CTRL_IN_WIDTH+CTRL_OUT_WIDTH)*tr_num;
1358 tr_ctrl_out = TRANS_TABLE >> tr_pos;
1359 tr_pos = tr_pos + CTRL_OUT_WIDTH;
1360 state_num = TRANS_TABLE >> tr_pos;
1361 tr_state_out = STATE_TABLE >> (STATE_BITS*state_num);
1362 tr_pos = tr_pos + STATE_NUM_LOG2;
1363 tr_ctrl_in = TRANS_TABLE >> tr_pos;
1364 tr_pos = tr_pos + CTRL_IN_WIDTH;
1365 state_num = TRANS_TABLE >> tr_pos;
1366 tr_state_in = STATE_TABLE >> (STATE_BITS*state_num);
1367 tr_pos = tr_pos + STATE_NUM_LOG2;
1368 end
1369 endtask
1370
1371 always @(posedge pos_clk, posedge pos_arst) begin
1372 if (pos_arst) begin
1373 state_tmp = STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST];
1374 for (i = 0; i < STATE_BITS; i = i+1)
1375 if (state_tmp[i] === 1'bz)
1376 state_tmp[i] = 0;
1377 state <= state_tmp;
1378 end else begin
1379 state_tmp = next_state;
1380 for (i = 0; i < STATE_BITS; i = i+1)
1381 if (state_tmp[i] === 1'bz)
1382 state_tmp[i] = 0;
1383 state <= state_tmp;
1384 end
1385 end
1386
1387 always @(state, CTRL_IN) begin
1388 next_state <= STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST];
1389 CTRL_OUT <= 'bx;
1390 // $display("---");
1391 // $display("Q: %b %b", state, CTRL_IN);
1392 for (i = 0; i < TRANS_NUM; i = i+1) begin
1393 tr_fetch(i);
1394 // $display("T: %b %b -> %b %b [%d]", tr_state_in, tr_ctrl_in, tr_state_out, tr_ctrl_out, i);
1395 casez ({state, CTRL_IN})
1396 {tr_state_in, tr_ctrl_in}: begin
1397 // $display("-> %b %b <- MATCH", state, CTRL_IN);
1398 {next_state, CTRL_OUT} <= {tr_state_out, tr_ctrl_out};
1399 end
1400 endcase
1401 end
1402 end
1403
1404 endmodule
1405
1406 // --------------------------------------------------------
1407 `ifndef SIMLIB_NOMEM
1408
1409 module \$memrd (CLK, ADDR, DATA);
1410
1411 parameter MEMID = "";
1412 parameter ABITS = 8;
1413 parameter WIDTH = 8;
1414
1415 parameter CLK_ENABLE = 0;
1416 parameter CLK_POLARITY = 0;
1417
1418 input CLK;
1419 input [ABITS-1:0] ADDR;
1420 output [WIDTH-1:0] DATA;
1421
1422 initial begin
1423 if (MEMID != "") begin
1424 $display("ERROR: Found non-simulatable instance of $memrd!");
1425 $finish;
1426 end
1427 end
1428
1429 endmodule
1430
1431 // --------------------------------------------------------
1432
1433 module \$memwr (CLK, EN, ADDR, DATA);
1434
1435 parameter MEMID = "";
1436 parameter ABITS = 8;
1437 parameter WIDTH = 8;
1438
1439 parameter CLK_ENABLE = 0;
1440 parameter CLK_POLARITY = 0;
1441
1442 input CLK;
1443 input [WIDTH-1:0] EN;
1444 input [ABITS-1:0] ADDR;
1445 input [WIDTH-1:0] DATA;
1446
1447 initial begin
1448 if (MEMID != "") begin
1449 $display("ERROR: Found non-simulatable instance of $memwr!");
1450 $finish;
1451 end
1452 end
1453
1454 endmodule
1455
1456 // --------------------------------------------------------
1457
1458 module \$mem (RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
1459
1460 parameter MEMID = "";
1461 parameter SIZE = 256;
1462 parameter OFFSET = 0;
1463 parameter ABITS = 8;
1464 parameter WIDTH = 8;
1465
1466 parameter RD_PORTS = 1;
1467 parameter RD_CLK_ENABLE = 1'b1;
1468 parameter RD_CLK_POLARITY = 1'b1;
1469 parameter RD_TRANSPARENT = 1'b1;
1470
1471 parameter WR_PORTS = 1;
1472 parameter WR_CLK_ENABLE = 1'b1;
1473 parameter WR_CLK_POLARITY = 1'b1;
1474
1475 input [RD_PORTS-1:0] RD_CLK;
1476 input [RD_PORTS*ABITS-1:0] RD_ADDR;
1477 output reg [RD_PORTS*WIDTH-1:0] RD_DATA;
1478
1479 input [WR_PORTS-1:0] WR_CLK;
1480 input [WR_PORTS*WIDTH-1:0] WR_EN;
1481 input [WR_PORTS*ABITS-1:0] WR_ADDR;
1482 input [WR_PORTS*WIDTH-1:0] WR_DATA;
1483
1484 reg [WIDTH-1:0] data [SIZE-1:0];
1485 reg update_async_rd;
1486
1487 genvar i;
1488 generate
1489
1490 for (i = 0; i < RD_PORTS; i = i+1) begin:rd
1491 if (RD_CLK_ENABLE[i] == 0) begin:rd_noclk
1492 always @(RD_ADDR or update_async_rd)
1493 RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
1494 end else
1495 if (RD_TRANSPARENT[i] == 1) begin:rd_transparent
1496 reg [ABITS-1:0] addr_buf;
1497 if (RD_CLK_POLARITY[i] == 1) begin:rd_trans_posclk
1498 always @(posedge RD_CLK[i])
1499 addr_buf <= RD_ADDR[i*ABITS +: ABITS];
1500 end else begin:rd_trans_negclk
1501 always @(negedge RD_CLK[i])
1502 addr_buf <= RD_ADDR[i*ABITS +: ABITS];
1503 end
1504 always @(addr_buf or update_async_rd)
1505 RD_DATA[i*WIDTH +: WIDTH] <= data[addr_buf - OFFSET];
1506 end else begin:rd_notransparent
1507 if (RD_CLK_POLARITY[i] == 1) begin:rd_notrans_posclk
1508 always @(posedge RD_CLK[i])
1509 RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
1510 end else begin:rd_notrans_negclk
1511 always @(negedge RD_CLK[i])
1512 RD_DATA[i*WIDTH +: WIDTH] <= data[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
1513 end
1514 end
1515 end
1516
1517 for (i = 0; i < WR_PORTS; i = i+1) begin:wr
1518 integer k, n;
1519 reg found_collision, run_update;
1520 if (WR_CLK_ENABLE[i] == 0) begin:wr_noclk
1521 always @(WR_ADDR or WR_DATA or WR_EN) begin
1522 run_update = 0;
1523 for (n = 0; n < WIDTH; n = n+1) begin
1524 if (WR_EN[i*WIDTH + n]) begin
1525 found_collision = 0;
1526 for (k = i+1; k < WR_PORTS; k = k+1)
1527 if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS])
1528 found_collision = 1;
1529 if (!found_collision) begin
1530 data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n];
1531 run_update = 1;
1532 end
1533 end
1534 end
1535 if (run_update) begin
1536 update_async_rd <= 1;
1537 update_async_rd <= 0;
1538 end
1539 end
1540 end else
1541 if (WR_CLK_POLARITY[i] == 1) begin:rd_posclk
1542 always @(posedge WR_CLK[i]) begin
1543 run_update = 0;
1544 for (n = 0; n < WIDTH; n = n+1) begin
1545 if (WR_EN[i*WIDTH + n]) begin
1546 found_collision = 0;
1547 for (k = i+1; k < WR_PORTS; k = k+1)
1548 if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS])
1549 found_collision = 1;
1550 if (!found_collision) begin
1551 data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n];
1552 run_update = 1;
1553 end
1554 end
1555 end
1556 if (run_update) begin
1557 update_async_rd <= 1;
1558 update_async_rd <= 0;
1559 end
1560 end
1561 end else begin:rd_negclk
1562 always @(negedge WR_CLK[i]) begin
1563 run_update = 0;
1564 for (n = 0; n < WIDTH; n = n+1) begin
1565 if (WR_EN[i*WIDTH + n]) begin
1566 found_collision = 0;
1567 for (k = i+1; k < WR_PORTS; k = k+1)
1568 if (WR_EN[k*WIDTH + n] && WR_ADDR[i*ABITS +: ABITS] == WR_ADDR[k*ABITS +: ABITS])
1569 found_collision = 1;
1570 if (!found_collision) begin
1571 data[WR_ADDR[i*ABITS +: ABITS] - OFFSET][n] <= WR_DATA[i*WIDTH + n];
1572 run_update = 1;
1573 end
1574 end
1575 end
1576 if (run_update) begin
1577 update_async_rd <= 1;
1578 update_async_rd <= 0;
1579 end
1580 end
1581 end
1582 end
1583
1584 endgenerate
1585
1586 endmodule
1587
1588 `endif
1589 // --------------------------------------------------------