2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 * The Simulation Library.
22 * This verilog library contains simple simulation models for the internal
23 * cells ($not, ...) generated by the frontends and used in most passes.
25 * This library can be used to verify the internal netlists as generated
26 * by the different frontends and passes.
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"
34 // --------------------------------------------------------
38 parameter A_SIGNED = 0;
39 parameter A_WIDTH = 0;
40 parameter Y_WIDTH = 0;
42 input [A_WIDTH-1:0] A;
43 output [Y_WIDTH-1:0] Y;
46 if (A_SIGNED) begin:BLOCK1
47 assign Y = ~$signed(A);
56 // --------------------------------------------------------
60 parameter A_SIGNED = 0;
61 parameter A_WIDTH = 0;
62 parameter Y_WIDTH = 0;
64 input [A_WIDTH-1:0] A;
65 output [Y_WIDTH-1:0] Y;
68 if (A_SIGNED) begin:BLOCK1
69 assign Y = $signed(A);
77 // --------------------------------------------------------
81 parameter A_SIGNED = 0;
82 parameter A_WIDTH = 0;
83 parameter Y_WIDTH = 0;
85 input [A_WIDTH-1:0] A;
86 output [Y_WIDTH-1:0] Y;
89 if (A_SIGNED) begin:BLOCK1
90 assign Y = -$signed(A);
98 // --------------------------------------------------------
100 module \$and (A, B, Y);
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;
108 input [A_WIDTH-1:0] A;
109 input [B_WIDTH-1:0] B;
110 output [Y_WIDTH-1:0] Y;
113 if (A_SIGNED && B_SIGNED) begin:BLOCK1
114 assign Y = $signed(A) & $signed(B);
115 end else begin:BLOCK2
122 // --------------------------------------------------------
124 module \$or (A, B, Y);
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;
132 input [A_WIDTH-1:0] A;
133 input [B_WIDTH-1:0] B;
134 output [Y_WIDTH-1:0] Y;
137 if (A_SIGNED && B_SIGNED) begin:BLOCK1
138 assign Y = $signed(A) | $signed(B);
139 end else begin:BLOCK2
146 // --------------------------------------------------------
148 module \$xor (A, B, Y);
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;
156 input [A_WIDTH-1:0] A;
157 input [B_WIDTH-1:0] B;
158 output [Y_WIDTH-1:0] Y;
161 if (A_SIGNED && B_SIGNED) begin:BLOCK1
162 assign Y = $signed(A) ^ $signed(B);
163 end else begin:BLOCK2
170 // --------------------------------------------------------
172 module \$xnor (A, B, Y);
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;
180 input [A_WIDTH-1:0] A;
181 input [B_WIDTH-1:0] B;
182 output [Y_WIDTH-1:0] Y;
185 if (A_SIGNED && B_SIGNED) begin:BLOCK1
186 assign Y = $signed(A) ~^ $signed(B);
187 end else begin:BLOCK2
194 // --------------------------------------------------------
196 module \$reduce_and (A, Y);
198 parameter A_SIGNED = 0;
199 parameter A_WIDTH = 0;
200 parameter Y_WIDTH = 0;
202 input [A_WIDTH-1:0] A;
203 output [Y_WIDTH-1:0] Y;
206 if (A_SIGNED) begin:BLOCK1
207 assign Y = &$signed(A);
208 end else begin:BLOCK2
215 // --------------------------------------------------------
217 module \$reduce_or (A, Y);
219 parameter A_SIGNED = 0;
220 parameter A_WIDTH = 0;
221 parameter Y_WIDTH = 0;
223 input [A_WIDTH-1:0] A;
224 output [Y_WIDTH-1:0] Y;
227 if (A_SIGNED) begin:BLOCK1
228 assign Y = |$signed(A);
229 end else begin:BLOCK2
236 // --------------------------------------------------------
238 module \$reduce_xor (A, Y);
240 parameter A_SIGNED = 0;
241 parameter A_WIDTH = 0;
242 parameter Y_WIDTH = 0;
244 input [A_WIDTH-1:0] A;
245 output [Y_WIDTH-1:0] Y;
248 if (A_SIGNED) begin:BLOCK1
249 assign Y = ^$signed(A);
250 end else begin:BLOCK2
257 // --------------------------------------------------------
259 module \$reduce_xnor (A, Y);
261 parameter A_SIGNED = 0;
262 parameter A_WIDTH = 0;
263 parameter Y_WIDTH = 0;
265 input [A_WIDTH-1:0] A;
266 output [Y_WIDTH-1:0] Y;
269 if (A_SIGNED) begin:BLOCK1
270 assign Y = ~^$signed(A);
271 end else begin:BLOCK2
278 // --------------------------------------------------------
280 module \$reduce_bool (A, Y);
282 parameter A_SIGNED = 0;
283 parameter A_WIDTH = 0;
284 parameter Y_WIDTH = 0;
286 input [A_WIDTH-1:0] A;
287 output [Y_WIDTH-1:0] Y;
290 if (A_SIGNED) begin:BLOCK1
291 assign Y = !(!$signed(A));
292 end else begin:BLOCK2
299 // --------------------------------------------------------
301 module \$shl (A, B, Y);
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;
309 input [A_WIDTH-1:0] A;
310 input [B_WIDTH-1:0] B;
311 output [Y_WIDTH-1:0] Y;
314 if (A_SIGNED) begin:BLOCK1
315 assign Y = $signed(A) << B;
316 end else begin:BLOCK2
323 // --------------------------------------------------------
325 module \$shr (A, B, Y);
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;
333 input [A_WIDTH-1:0] A;
334 input [B_WIDTH-1:0] B;
335 output [Y_WIDTH-1:0] Y;
338 if (A_SIGNED) begin:BLOCK1
339 assign Y = $signed(A) >> B;
340 end else begin:BLOCK2
347 // --------------------------------------------------------
349 module \$sshl (A, B, Y);
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;
357 input [A_WIDTH-1:0] A;
358 input [B_WIDTH-1:0] B;
359 output [Y_WIDTH-1:0] Y;
362 if (A_SIGNED) begin:BLOCK1
363 assign Y = $signed(A) <<< B;
364 end else begin:BLOCK2
371 // --------------------------------------------------------
373 module \$sshr (A, B, Y);
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;
381 input [A_WIDTH-1:0] A;
382 input [B_WIDTH-1:0] B;
383 output [Y_WIDTH-1:0] Y;
386 if (A_SIGNED) begin:BLOCK1
387 assign Y = $signed(A) >>> B;
388 end else begin:BLOCK2
395 // --------------------------------------------------------
397 module \$shift (A, B, Y);
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;
405 input [A_WIDTH-1:0] A;
406 input [B_WIDTH-1:0] B;
407 output [Y_WIDTH-1:0] Y;
410 if (B_SIGNED) begin:BLOCK1
411 assign Y = $signed(B) < 0 ? A << -B : A >> B;
412 end else begin:BLOCK2
419 // --------------------------------------------------------
421 module \$shiftx (A, B, Y);
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;
429 input [A_WIDTH-1:0] A;
430 input [B_WIDTH-1:0] B;
431 output [Y_WIDTH-1:0] Y;
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];
444 // --------------------------------------------------------
446 module \$fa (A, B, C, X, Y);
450 input [WIDTH-1:0] A, B, C;
451 output [WIDTH-1:0] X, Y;
453 wire [WIDTH-1:0] t1, t2, t3;
455 assign t1 = A ^ B, t2 = A & B, t3 = C & t1;
456 assign Y = t1 ^ C, X = t2 | t3;
460 // --------------------------------------------------------
462 module \$lcu (P, G, CI, CO);
466 input [WIDTH-1:0] P, G;
469 output reg [WIDTH-1:0] CO;
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]);
483 // --------------------------------------------------------
485 module \$alu (A, B, CI, BI, X, Y, CO);
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;
493 input [A_WIDTH-1:0] A;
494 input [B_WIDTH-1:0] B;
495 output [Y_WIDTH-1:0] X, Y;
498 output [Y_WIDTH-1:0] CO;
500 wire [Y_WIDTH-1:0] AA, BB;
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);
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};
514 assign Y = (AA + BB + CI) ^ {Y_WIDTH{y_co_undef}};
518 get_carry = (a&b) | (a&c) | (b&c);
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;
531 // --------------------------------------------------------
533 module \$lt (A, B, Y);
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;
541 input [A_WIDTH-1:0] A;
542 input [B_WIDTH-1:0] B;
543 output [Y_WIDTH-1:0] Y;
546 if (A_SIGNED && B_SIGNED) begin:BLOCK1
547 assign Y = $signed(A) < $signed(B);
548 end else begin:BLOCK2
555 // --------------------------------------------------------
557 module \$le (A, B, Y);
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;
565 input [A_WIDTH-1:0] A;
566 input [B_WIDTH-1:0] B;
567 output [Y_WIDTH-1:0] Y;
570 if (A_SIGNED && B_SIGNED) begin:BLOCK1
571 assign Y = $signed(A) <= $signed(B);
572 end else begin:BLOCK2
579 // --------------------------------------------------------
581 module \$eq (A, B, Y);
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;
589 input [A_WIDTH-1:0] A;
590 input [B_WIDTH-1:0] B;
591 output [Y_WIDTH-1:0] Y;
594 if (A_SIGNED && B_SIGNED) begin:BLOCK1
595 assign Y = $signed(A) == $signed(B);
596 end else begin:BLOCK2
603 // --------------------------------------------------------
605 module \$ne (A, B, Y);
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;
613 input [A_WIDTH-1:0] A;
614 input [B_WIDTH-1:0] B;
615 output [Y_WIDTH-1:0] Y;
618 if (A_SIGNED && B_SIGNED) begin:BLOCK1
619 assign Y = $signed(A) != $signed(B);
620 end else begin:BLOCK2
627 // --------------------------------------------------------
629 module \$eqx (A, B, Y);
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;
637 input [A_WIDTH-1:0] A;
638 input [B_WIDTH-1:0] B;
639 output [Y_WIDTH-1:0] Y;
642 if (A_SIGNED && B_SIGNED) begin:BLOCK1
643 assign Y = $signed(A) === $signed(B);
644 end else begin:BLOCK2
651 // --------------------------------------------------------
653 module \$nex (A, B, Y);
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;
661 input [A_WIDTH-1:0] A;
662 input [B_WIDTH-1:0] B;
663 output [Y_WIDTH-1:0] Y;
666 if (A_SIGNED && B_SIGNED) begin:BLOCK1
667 assign Y = $signed(A) !== $signed(B);
668 end else begin:BLOCK2
675 // --------------------------------------------------------
677 module \$ge (A, B, Y);
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;
685 input [A_WIDTH-1:0] A;
686 input [B_WIDTH-1:0] B;
687 output [Y_WIDTH-1:0] Y;
690 if (A_SIGNED && B_SIGNED) begin:BLOCK1
691 assign Y = $signed(A) >= $signed(B);
692 end else begin:BLOCK2
699 // --------------------------------------------------------
701 module \$gt (A, B, Y);
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;
709 input [A_WIDTH-1:0] A;
710 input [B_WIDTH-1:0] B;
711 output [Y_WIDTH-1:0] Y;
714 if (A_SIGNED && B_SIGNED) begin:BLOCK1
715 assign Y = $signed(A) > $signed(B);
716 end else begin:BLOCK2
723 // --------------------------------------------------------
725 module \$add (A, B, Y);
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;
733 input [A_WIDTH-1:0] A;
734 input [B_WIDTH-1:0] B;
735 output [Y_WIDTH-1:0] Y;
738 if (A_SIGNED && B_SIGNED) begin:BLOCK1
739 assign Y = $signed(A) + $signed(B);
740 end else begin:BLOCK2
747 // --------------------------------------------------------
749 module \$sub (A, B, Y);
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;
757 input [A_WIDTH-1:0] A;
758 input [B_WIDTH-1:0] B;
759 output [Y_WIDTH-1:0] Y;
762 if (A_SIGNED && B_SIGNED) begin:BLOCK1
763 assign Y = $signed(A) - $signed(B);
764 end else begin:BLOCK2
771 // --------------------------------------------------------
773 module \$mul (A, B, Y);
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;
781 input [A_WIDTH-1:0] A;
782 input [B_WIDTH-1:0] B;
783 output [Y_WIDTH-1:0] Y;
786 if (A_SIGNED && B_SIGNED) begin:BLOCK1
787 assign Y = $signed(A) * $signed(B);
788 end else begin:BLOCK2
795 // --------------------------------------------------------
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;
804 input [A_WIDTH-1:0] A;
805 input [B_WIDTH-1:0] B;
806 output reg [Y_WIDTH-1:0] Y;
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;
812 function [2*num_ports*num_abits-1:0] get_port_offsets;
813 input [CONFIG_WIDTH-1:0] cfg;
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];
827 localparam [2*num_ports*num_abits-1:0] port_offsets = get_port_offsets(CONFIG);
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])
837 reg [Y_WIDTH-1:0] tmp_a, tmp_b;
841 for (i = 0; i < num_ports; i = i+1)
846 for (j = 0; j < `PORT_SIZE_A; j = j+1)
847 tmp_a[j] = A[`PORT_OFFSET_A + j];
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];
853 for (j = 0; j < `PORT_SIZE_B; j = j+1)
854 tmp_b[j] = A[`PORT_OFFSET_B + j];
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];
860 if (`PORT_SIZE_B > 0)
861 tmp_a = tmp_a * tmp_b;
863 if (`PORT_DO_SUBTRACT)
868 for (i = 0; i < B_WIDTH; i = i+1) begin
873 `undef PORT_IS_SIGNED
874 `undef PORT_DO_SUBTRACT
881 // --------------------------------------------------------
883 module \$div (A, B, Y);
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;
891 input [A_WIDTH-1:0] A;
892 input [B_WIDTH-1:0] B;
893 output [Y_WIDTH-1:0] Y;
896 if (A_SIGNED && B_SIGNED) begin:BLOCK1
897 assign Y = $signed(A) / $signed(B);
898 end else begin:BLOCK2
905 // --------------------------------------------------------
907 module \$mod (A, B, Y);
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;
915 input [A_WIDTH-1:0] A;
916 input [B_WIDTH-1:0] B;
917 output [Y_WIDTH-1:0] Y;
920 if (A_SIGNED && B_SIGNED) begin:BLOCK1
921 assign Y = $signed(A) % $signed(B);
922 end else begin:BLOCK2
929 // --------------------------------------------------------
932 module \$pow (A, B, Y);
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;
940 input [A_WIDTH-1:0] A;
941 input [B_WIDTH-1:0] B;
942 output [Y_WIDTH-1:0] Y;
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
959 // --------------------------------------------------------
961 module \$logic_not (A, Y);
963 parameter A_SIGNED = 0;
964 parameter A_WIDTH = 0;
965 parameter Y_WIDTH = 0;
967 input [A_WIDTH-1:0] A;
968 output [Y_WIDTH-1:0] Y;
971 if (A_SIGNED) begin:BLOCK1
972 assign Y = !$signed(A);
973 end else begin:BLOCK2
980 // --------------------------------------------------------
982 module \$logic_and (A, B, Y);
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;
990 input [A_WIDTH-1:0] A;
991 input [B_WIDTH-1:0] B;
992 output [Y_WIDTH-1:0] Y;
995 if (A_SIGNED && B_SIGNED) begin:BLOCK1
996 assign Y = $signed(A) && $signed(B);
997 end else begin:BLOCK2
1004 // --------------------------------------------------------
1006 module \$logic_or (A, B, Y);
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;
1014 input [A_WIDTH-1:0] A;
1015 input [B_WIDTH-1:0] B;
1016 output [Y_WIDTH-1:0] Y;
1019 if (A_SIGNED && B_SIGNED) begin:BLOCK1
1020 assign Y = $signed(A) || $signed(B);
1021 end else begin:BLOCK2
1028 // --------------------------------------------------------
1030 module \$slice (A, Y);
1032 parameter OFFSET = 0;
1033 parameter A_WIDTH = 0;
1034 parameter Y_WIDTH = 0;
1036 input [A_WIDTH-1:0] A;
1037 output [Y_WIDTH-1:0] Y;
1039 assign Y = A >> OFFSET;
1043 // --------------------------------------------------------
1045 module \$concat (A, B, Y);
1047 parameter A_WIDTH = 0;
1048 parameter B_WIDTH = 0;
1050 input [A_WIDTH-1:0] A;
1051 input [B_WIDTH-1:0] B;
1052 output [A_WIDTH+B_WIDTH-1:0] Y;
1058 // --------------------------------------------------------
1060 module \$mux (A, B, S, Y);
1062 parameter WIDTH = 0;
1064 input [WIDTH-1:0] A, B;
1066 output reg [WIDTH-1:0] Y;
1077 // --------------------------------------------------------
1079 module \$pmux (A, B, S, Y);
1081 parameter WIDTH = 0;
1082 parameter S_WIDTH = 0;
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;
1090 reg found_active_sel_bit;
1094 found_active_sel_bit = 0;
1095 for (i = 0; i < S_WIDTH; i = i+1)
1097 Y = found_active_sel_bit ? 'bx : B >> (WIDTH*i);
1098 found_active_sel_bit = 1;
1104 // --------------------------------------------------------
1105 `ifndef SIMLIB_NOLUT
1107 module \$lut (A, Y);
1109 parameter WIDTH = 0;
1112 input [WIDTH-1:0] A;
1115 wire lut0_out, lut1_out;
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) );
1125 if (WIDTH > 0) begin:lutlogic
1127 casez ({A[WIDTH-1], lut0_out, lut1_out})
1130 3'b0??: Y = lut0_out;
1131 3'b1??: Y = lut1_out;
1141 // --------------------------------------------------------
1143 module \$assert (A, EN);
1148 if (A !== 1'b1 && EN === 1'b1) begin
1149 $display("Assertation failed!");
1156 // --------------------------------------------------------
1159 module \$sr (SET, CLR, Q);
1161 parameter WIDTH = 0;
1162 parameter SET_POLARITY = 1'b1;
1163 parameter CLR_POLARITY = 1'b1;
1165 input [WIDTH-1:0] SET, CLR;
1166 output reg [WIDTH-1:0] Q;
1168 wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET;
1169 wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
1173 for (i = 0; i < WIDTH; i = i+1) begin:bit
1174 always @(posedge pos_set[i], posedge pos_clr[i])
1177 else if (pos_set[i])
1185 // --------------------------------------------------------
1187 module \$dff (CLK, D, Q);
1189 parameter WIDTH = 0;
1190 parameter CLK_POLARITY = 1'b1;
1193 input [WIDTH-1:0] D;
1194 output reg [WIDTH-1:0] Q;
1195 wire pos_clk = CLK == CLK_POLARITY;
1197 always @(posedge pos_clk) begin
1203 // --------------------------------------------------------
1206 module \$dffsr (CLK, SET, CLR, D, Q);
1208 parameter WIDTH = 0;
1209 parameter CLK_POLARITY = 1'b1;
1210 parameter SET_POLARITY = 1'b1;
1211 parameter CLR_POLARITY = 1'b1;
1214 input [WIDTH-1:0] SET, CLR, D;
1215 output reg [WIDTH-1:0] Q;
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;
1223 for (i = 0; i < WIDTH; i = i+1) begin:bit
1224 always @(posedge pos_set[i], posedge pos_clr[i], posedge pos_clk)
1227 else if (pos_set[i])
1237 // --------------------------------------------------------
1239 module \$adff (CLK, ARST, D, Q);
1241 parameter WIDTH = 0;
1242 parameter CLK_POLARITY = 1'b1;
1243 parameter ARST_POLARITY = 1'b1;
1244 parameter ARST_VALUE = 0;
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;
1252 always @(posedge pos_clk, posedge pos_arst) begin
1261 // --------------------------------------------------------
1263 module \$dlatch (EN, D, Q);
1265 parameter WIDTH = 0;
1266 parameter EN_POLARITY = 1'b1;
1269 input [WIDTH-1:0] D;
1270 output reg [WIDTH-1:0] Q;
1273 if (EN == EN_POLARITY)
1279 // --------------------------------------------------------
1282 module \$dlatchsr (EN, SET, CLR, D, Q);
1284 parameter WIDTH = 0;
1285 parameter EN_POLARITY = 1'b1;
1286 parameter SET_POLARITY = 1'b1;
1287 parameter CLR_POLARITY = 1'b1;
1290 input [WIDTH-1:0] SET, CLR, D;
1291 output reg [WIDTH-1:0] Q;
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;
1299 for (i = 0; i < WIDTH; i = i+1) begin:bit
1303 else if (pos_set[i])
1313 // --------------------------------------------------------
1315 module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT);
1317 parameter NAME = "";
1319 parameter CLK_POLARITY = 1'b1;
1320 parameter ARST_POLARITY = 1'b1;
1322 parameter CTRL_IN_WIDTH = 1;
1323 parameter CTRL_OUT_WIDTH = 1;
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;
1331 parameter TRANS_NUM = 1;
1332 parameter TRANS_TABLE = 4'b0x0x;
1335 input [CTRL_IN_WIDTH-1:0] CTRL_IN;
1336 output reg [CTRL_OUT_WIDTH-1:0] CTRL_OUT;
1338 wire pos_clk = CLK == CLK_POLARITY;
1339 wire pos_arst = ARST == ARST_POLARITY;
1341 reg [STATE_BITS-1:0] state;
1342 reg [STATE_BITS-1:0] state_tmp;
1343 reg [STATE_BITS-1:0] next_state;
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;
1353 input [31:0] tr_num;
1355 reg [STATE_NUM_LOG2-1:0] state_num;
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;
1371 always @(posedge pos_clk, posedge 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)
1379 state_tmp = next_state;
1380 for (i = 0; i < STATE_BITS; i = i+1)
1381 if (state_tmp[i] === 1'bz)
1387 always @(state, CTRL_IN) begin
1388 next_state <= STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST];
1391 // $display("Q: %b %b", state, CTRL_IN);
1392 for (i = 0; i < TRANS_NUM; i = i+1) begin
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};
1406 // --------------------------------------------------------
1407 `ifndef SIMLIB_NOMEM
1409 module \$memrd (CLK, ADDR, DATA);
1411 parameter MEMID = "";
1412 parameter ABITS = 8;
1413 parameter WIDTH = 8;
1415 parameter CLK_ENABLE = 0;
1416 parameter CLK_POLARITY = 0;
1419 input [ABITS-1:0] ADDR;
1420 output [WIDTH-1:0] DATA;
1423 if (MEMID != "") begin
1424 $display("ERROR: Found non-simulatable instance of $memrd!");
1431 // --------------------------------------------------------
1433 module \$memwr (CLK, EN, ADDR, DATA);
1435 parameter MEMID = "";
1436 parameter ABITS = 8;
1437 parameter WIDTH = 8;
1439 parameter CLK_ENABLE = 0;
1440 parameter CLK_POLARITY = 0;
1443 input [WIDTH-1:0] EN;
1444 input [ABITS-1:0] ADDR;
1445 input [WIDTH-1:0] DATA;
1448 if (MEMID != "") begin
1449 $display("ERROR: Found non-simulatable instance of $memwr!");
1456 // --------------------------------------------------------
1458 module \$mem (RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
1460 parameter MEMID = "";
1461 parameter SIZE = 256;
1462 parameter OFFSET = 0;
1463 parameter ABITS = 8;
1464 parameter WIDTH = 8;
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;
1471 parameter WR_PORTS = 1;
1472 parameter WR_CLK_ENABLE = 1'b1;
1473 parameter WR_CLK_POLARITY = 1'b1;
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;
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;
1484 reg [WIDTH-1:0] data [SIZE-1:0];
1485 reg update_async_rd;
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];
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];
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];
1517 for (i = 0; i < WR_PORTS; i = i+1) begin:wr
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
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];
1535 if (run_update) begin
1536 update_async_rd <= 1;
1537 update_async_rd <= 0;
1541 if (WR_CLK_POLARITY[i] == 1) begin:rd_posclk
1542 always @(posedge WR_CLK[i]) begin
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];
1556 if (run_update) begin
1557 update_async_rd <= 1;
1558 update_async_rd <= 0;
1561 end else begin:rd_negclk
1562 always @(negedge WR_CLK[i]) begin
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];
1576 if (run_update) begin
1577 update_async_rd <= 1;
1578 update_async_rd <= 0;
1589 // --------------------------------------------------------