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) ^ (Y ^ Y);
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);
799 parameter A_WIDTH = 0;
800 parameter B_WIDTH = 0;
801 parameter Y_WIDTH = 0;
802 parameter CONFIG = 4'b0000;
803 parameter CONFIG_WIDTH = 4;
805 input [A_WIDTH-1:0] A;
806 input [B_WIDTH-1:0] B;
807 output reg [Y_WIDTH-1:0] Y;
809 // Xilinx XSIM does not like $clog2() below..
810 function integer my_clog2;
818 my_clog2 = my_clog2 + 1;
823 localparam integer num_bits = CONFIG[3:0] > 0 ? CONFIG[3:0] : 1;
824 localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits);
825 localparam integer num_abits = my_clog2(A_WIDTH) > 0 ? my_clog2(A_WIDTH) : 1;
827 function [2*num_ports*num_abits-1:0] get_port_offsets;
828 input [CONFIG_WIDTH-1:0] cfg;
832 get_port_offsets = 0;
833 for (i = 0; i < num_ports; i = i+1) begin
834 get_port_offsets[(2*i + 0)*num_abits +: num_abits] = cursor;
835 cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 +: num_bits];
836 get_port_offsets[(2*i + 1)*num_abits +: num_abits] = cursor;
837 cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits];
842 localparam [2*num_ports*num_abits-1:0] port_offsets = get_port_offsets(CONFIG);
844 `define PORT_IS_SIGNED (0 + CONFIG[4 + i*(2 + 2*num_bits)])
845 `define PORT_DO_SUBTRACT (0 + CONFIG[4 + i*(2 + 2*num_bits) + 1])
846 `define PORT_SIZE_A (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits])
847 `define PORT_SIZE_B (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits])
848 `define PORT_OFFSET_A (0 + port_offsets[2*i*num_abits +: num_abits])
849 `define PORT_OFFSET_B (0 + port_offsets[2*i*num_abits + num_abits +: num_abits])
852 reg [Y_WIDTH-1:0] tmp_a, tmp_b;
856 for (i = 0; i < num_ports; i = i+1)
861 for (j = 0; j < `PORT_SIZE_A; j = j+1)
862 tmp_a[j] = A[`PORT_OFFSET_A + j];
864 if (`PORT_IS_SIGNED && `PORT_SIZE_A > 0)
865 for (j = `PORT_SIZE_A; j < Y_WIDTH; j = j+1)
866 tmp_a[j] = tmp_a[`PORT_SIZE_A-1];
868 for (j = 0; j < `PORT_SIZE_B; j = j+1)
869 tmp_b[j] = A[`PORT_OFFSET_B + j];
871 if (`PORT_IS_SIGNED && `PORT_SIZE_B > 0)
872 for (j = `PORT_SIZE_B; j < Y_WIDTH; j = j+1)
873 tmp_b[j] = tmp_b[`PORT_SIZE_B-1];
875 if (`PORT_SIZE_B > 0)
876 tmp_a = tmp_a * tmp_b;
878 if (`PORT_DO_SUBTRACT)
883 for (i = 0; i < B_WIDTH; i = i+1) begin
888 `undef PORT_IS_SIGNED
889 `undef PORT_DO_SUBTRACT
897 // --------------------------------------------------------
899 module \$div (A, B, Y);
901 parameter A_SIGNED = 0;
902 parameter B_SIGNED = 0;
903 parameter A_WIDTH = 0;
904 parameter B_WIDTH = 0;
905 parameter Y_WIDTH = 0;
907 input [A_WIDTH-1:0] A;
908 input [B_WIDTH-1:0] B;
909 output [Y_WIDTH-1:0] Y;
912 if (A_SIGNED && B_SIGNED) begin:BLOCK1
913 assign Y = $signed(A) / $signed(B);
914 end else begin:BLOCK2
921 // --------------------------------------------------------
923 module \$mod (A, B, Y);
925 parameter A_SIGNED = 0;
926 parameter B_SIGNED = 0;
927 parameter A_WIDTH = 0;
928 parameter B_WIDTH = 0;
929 parameter Y_WIDTH = 0;
931 input [A_WIDTH-1:0] A;
932 input [B_WIDTH-1:0] B;
933 output [Y_WIDTH-1:0] Y;
936 if (A_SIGNED && B_SIGNED) begin:BLOCK1
937 assign Y = $signed(A) % $signed(B);
938 end else begin:BLOCK2
945 // --------------------------------------------------------
948 module \$pow (A, B, Y);
950 parameter A_SIGNED = 0;
951 parameter B_SIGNED = 0;
952 parameter A_WIDTH = 0;
953 parameter B_WIDTH = 0;
954 parameter Y_WIDTH = 0;
956 input [A_WIDTH-1:0] A;
957 input [B_WIDTH-1:0] B;
958 output [Y_WIDTH-1:0] Y;
961 if (A_SIGNED && B_SIGNED) begin:BLOCK1
962 assign Y = $signed(A) ** $signed(B);
963 end else if (A_SIGNED) begin:BLOCK2
964 assign Y = $signed(A) ** B;
965 end else if (B_SIGNED) begin:BLOCK3
966 assign Y = A ** $signed(B);
967 end else begin:BLOCK4
975 // --------------------------------------------------------
977 module \$logic_not (A, Y);
979 parameter A_SIGNED = 0;
980 parameter A_WIDTH = 0;
981 parameter Y_WIDTH = 0;
983 input [A_WIDTH-1:0] A;
984 output [Y_WIDTH-1:0] Y;
987 if (A_SIGNED) begin:BLOCK1
988 assign Y = !$signed(A);
989 end else begin:BLOCK2
996 // --------------------------------------------------------
998 module \$logic_and (A, B, Y);
1000 parameter A_SIGNED = 0;
1001 parameter B_SIGNED = 0;
1002 parameter A_WIDTH = 0;
1003 parameter B_WIDTH = 0;
1004 parameter Y_WIDTH = 0;
1006 input [A_WIDTH-1:0] A;
1007 input [B_WIDTH-1:0] B;
1008 output [Y_WIDTH-1:0] Y;
1011 if (A_SIGNED && B_SIGNED) begin:BLOCK1
1012 assign Y = $signed(A) && $signed(B);
1013 end else begin:BLOCK2
1020 // --------------------------------------------------------
1022 module \$logic_or (A, B, Y);
1024 parameter A_SIGNED = 0;
1025 parameter B_SIGNED = 0;
1026 parameter A_WIDTH = 0;
1027 parameter B_WIDTH = 0;
1028 parameter Y_WIDTH = 0;
1030 input [A_WIDTH-1:0] A;
1031 input [B_WIDTH-1:0] B;
1032 output [Y_WIDTH-1:0] Y;
1035 if (A_SIGNED && B_SIGNED) begin:BLOCK1
1036 assign Y = $signed(A) || $signed(B);
1037 end else begin:BLOCK2
1044 // --------------------------------------------------------
1046 module \$slice (A, Y);
1048 parameter OFFSET = 0;
1049 parameter A_WIDTH = 0;
1050 parameter Y_WIDTH = 0;
1052 input [A_WIDTH-1:0] A;
1053 output [Y_WIDTH-1:0] Y;
1055 assign Y = A >> OFFSET;
1059 // --------------------------------------------------------
1061 module \$concat (A, B, Y);
1063 parameter A_WIDTH = 0;
1064 parameter B_WIDTH = 0;
1066 input [A_WIDTH-1:0] A;
1067 input [B_WIDTH-1:0] B;
1068 output [A_WIDTH+B_WIDTH-1:0] Y;
1074 // --------------------------------------------------------
1076 module \$mux (A, B, S, Y);
1078 parameter WIDTH = 0;
1080 input [WIDTH-1:0] A, B;
1082 output reg [WIDTH-1:0] Y;
1093 // --------------------------------------------------------
1095 module \$pmux (A, B, S, Y);
1097 parameter WIDTH = 0;
1098 parameter S_WIDTH = 0;
1100 input [WIDTH-1:0] A;
1101 input [WIDTH*S_WIDTH-1:0] B;
1102 input [S_WIDTH-1:0] S;
1103 output reg [WIDTH-1:0] Y;
1106 reg found_active_sel_bit;
1110 found_active_sel_bit = 0;
1111 for (i = 0; i < S_WIDTH; i = i+1)
1113 Y = found_active_sel_bit ? 'bx : B >> (WIDTH*i);
1114 found_active_sel_bit = 1;
1120 // --------------------------------------------------------
1121 `ifndef SIMLIB_NOLUT
1123 module \$lut (A, Y);
1125 parameter WIDTH = 0;
1128 input [WIDTH-1:0] A;
1131 wire lut0_out, lut1_out;
1134 if (WIDTH <= 1) begin:simple
1135 assign {lut1_out, lut0_out} = LUT;
1136 end else begin:complex
1137 \$lut #( .WIDTH(WIDTH-1), .LUT(LUT ) ) lut0 ( .A(A[WIDTH-2:0]), .Y(lut0_out) );
1138 \$lut #( .WIDTH(WIDTH-1), .LUT(LUT >> (2**(WIDTH-1))) ) lut1 ( .A(A[WIDTH-2:0]), .Y(lut1_out) );
1141 if (WIDTH > 0) begin:lutlogic
1143 casez ({A[WIDTH-1], lut0_out, lut1_out})
1146 3'b0??: Y = lut0_out;
1147 3'b1??: Y = lut1_out;
1157 // --------------------------------------------------------
1159 module \$assert (A, EN);
1163 `ifndef SIMLIB_NOCHECKS
1165 if (A !== 1'b1 && EN === 1'b1) begin
1166 $display("Assertation %m failed!");
1174 // --------------------------------------------------------
1176 module \$assume (A, EN);
1180 `ifndef SIMLIB_NOCHECKS
1182 if (A !== 1'b1 && EN === 1'b1) begin
1183 $display("Assumption %m failed!");
1191 // --------------------------------------------------------
1193 module \$equiv (A, B, Y);
1198 assign Y = (A !== 1'bx && A !== B) ? 1'bx : A;
1200 `ifndef SIMLIB_NOCHECKS
1202 if (A !== 1'bx && A !== B) begin
1203 $display("Equivalence failed!");
1211 // --------------------------------------------------------
1214 module \$sr (SET, CLR, Q);
1216 parameter WIDTH = 0;
1217 parameter SET_POLARITY = 1'b1;
1218 parameter CLR_POLARITY = 1'b1;
1220 input [WIDTH-1:0] SET, CLR;
1221 output reg [WIDTH-1:0] Q;
1223 wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET;
1224 wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
1228 for (i = 0; i < WIDTH; i = i+1) begin:bit
1229 always @(posedge pos_set[i], posedge pos_clr[i])
1232 else if (pos_set[i])
1240 // --------------------------------------------------------
1242 module \$dff (CLK, D, Q);
1244 parameter WIDTH = 0;
1245 parameter CLK_POLARITY = 1'b1;
1248 input [WIDTH-1:0] D;
1249 output reg [WIDTH-1:0] Q;
1250 wire pos_clk = CLK == CLK_POLARITY;
1252 always @(posedge pos_clk) begin
1258 // --------------------------------------------------------
1260 module \$dffe (CLK, EN, D, Q);
1262 parameter WIDTH = 0;
1263 parameter CLK_POLARITY = 1'b1;
1264 parameter EN_POLARITY = 1'b1;
1267 input [WIDTH-1:0] D;
1268 output reg [WIDTH-1:0] Q;
1269 wire pos_clk = CLK == CLK_POLARITY;
1271 always @(posedge pos_clk) begin
1272 if (EN == EN_POLARITY) Q <= D;
1277 // --------------------------------------------------------
1280 module \$dffsr (CLK, SET, CLR, D, Q);
1282 parameter WIDTH = 0;
1283 parameter CLK_POLARITY = 1'b1;
1284 parameter SET_POLARITY = 1'b1;
1285 parameter CLR_POLARITY = 1'b1;
1288 input [WIDTH-1:0] SET, CLR, D;
1289 output reg [WIDTH-1:0] Q;
1291 wire pos_clk = CLK == CLK_POLARITY;
1292 wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET;
1293 wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
1297 for (i = 0; i < WIDTH; i = i+1) begin:bit
1298 always @(posedge pos_set[i], posedge pos_clr[i], posedge pos_clk)
1301 else if (pos_set[i])
1311 // --------------------------------------------------------
1313 module \$adff (CLK, ARST, D, Q);
1315 parameter WIDTH = 0;
1316 parameter CLK_POLARITY = 1'b1;
1317 parameter ARST_POLARITY = 1'b1;
1318 parameter ARST_VALUE = 0;
1321 input [WIDTH-1:0] D;
1322 output reg [WIDTH-1:0] Q;
1323 wire pos_clk = CLK == CLK_POLARITY;
1324 wire pos_arst = ARST == ARST_POLARITY;
1326 always @(posedge pos_clk, posedge pos_arst) begin
1335 // --------------------------------------------------------
1337 module \$dlatch (EN, D, Q);
1339 parameter WIDTH = 0;
1340 parameter EN_POLARITY = 1'b1;
1343 input [WIDTH-1:0] D;
1344 output reg [WIDTH-1:0] Q;
1347 if (EN == EN_POLARITY)
1353 // --------------------------------------------------------
1356 module \$dlatchsr (EN, SET, CLR, D, Q);
1358 parameter WIDTH = 0;
1359 parameter EN_POLARITY = 1'b1;
1360 parameter SET_POLARITY = 1'b1;
1361 parameter CLR_POLARITY = 1'b1;
1364 input [WIDTH-1:0] SET, CLR, D;
1365 output reg [WIDTH-1:0] Q;
1367 wire pos_en = EN == EN_POLARITY;
1368 wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET;
1369 wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR;
1373 for (i = 0; i < WIDTH; i = i+1) begin:bit
1377 else if (pos_set[i])
1387 // --------------------------------------------------------
1389 module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT);
1391 parameter NAME = "";
1393 parameter CLK_POLARITY = 1'b1;
1394 parameter ARST_POLARITY = 1'b1;
1396 parameter CTRL_IN_WIDTH = 1;
1397 parameter CTRL_OUT_WIDTH = 1;
1399 parameter STATE_BITS = 1;
1400 parameter STATE_NUM = 1;
1401 parameter STATE_NUM_LOG2 = 1;
1402 parameter STATE_RST = 0;
1403 parameter STATE_TABLE = 1'b0;
1405 parameter TRANS_NUM = 1;
1406 parameter TRANS_TABLE = 4'b0x0x;
1409 input [CTRL_IN_WIDTH-1:0] CTRL_IN;
1410 output reg [CTRL_OUT_WIDTH-1:0] CTRL_OUT;
1412 wire pos_clk = CLK == CLK_POLARITY;
1413 wire pos_arst = ARST == ARST_POLARITY;
1415 reg [STATE_BITS-1:0] state;
1416 reg [STATE_BITS-1:0] state_tmp;
1417 reg [STATE_BITS-1:0] next_state;
1419 reg [STATE_BITS-1:0] tr_state_in;
1420 reg [STATE_BITS-1:0] tr_state_out;
1421 reg [CTRL_IN_WIDTH-1:0] tr_ctrl_in;
1422 reg [CTRL_OUT_WIDTH-1:0] tr_ctrl_out;
1427 input [31:0] tr_num;
1429 reg [STATE_NUM_LOG2-1:0] state_num;
1431 tr_pos = (2*STATE_NUM_LOG2+CTRL_IN_WIDTH+CTRL_OUT_WIDTH)*tr_num;
1432 tr_ctrl_out = TRANS_TABLE >> tr_pos;
1433 tr_pos = tr_pos + CTRL_OUT_WIDTH;
1434 state_num = TRANS_TABLE >> tr_pos;
1435 tr_state_out = STATE_TABLE >> (STATE_BITS*state_num);
1436 tr_pos = tr_pos + STATE_NUM_LOG2;
1437 tr_ctrl_in = TRANS_TABLE >> tr_pos;
1438 tr_pos = tr_pos + CTRL_IN_WIDTH;
1439 state_num = TRANS_TABLE >> tr_pos;
1440 tr_state_in = STATE_TABLE >> (STATE_BITS*state_num);
1441 tr_pos = tr_pos + STATE_NUM_LOG2;
1445 always @(posedge pos_clk, posedge pos_arst) begin
1447 state_tmp = STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST];
1448 for (i = 0; i < STATE_BITS; i = i+1)
1449 if (state_tmp[i] === 1'bz)
1453 state_tmp = next_state;
1454 for (i = 0; i < STATE_BITS; i = i+1)
1455 if (state_tmp[i] === 1'bz)
1461 always @(state, CTRL_IN) begin
1462 next_state <= STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST];
1465 // $display("Q: %b %b", state, CTRL_IN);
1466 for (i = 0; i < TRANS_NUM; i = i+1) begin
1468 // $display("T: %b %b -> %b %b [%d]", tr_state_in, tr_ctrl_in, tr_state_out, tr_ctrl_out, i);
1469 casez ({state, CTRL_IN})
1470 {tr_state_in, tr_ctrl_in}: begin
1471 // $display("-> %b %b <- MATCH", state, CTRL_IN);
1472 {next_state, CTRL_OUT} <= {tr_state_out, tr_ctrl_out};
1480 // --------------------------------------------------------
1481 `ifndef SIMLIB_NOMEM
1483 module \$memrd (CLK, ADDR, DATA);
1485 parameter MEMID = "";
1486 parameter ABITS = 8;
1487 parameter WIDTH = 8;
1489 parameter CLK_ENABLE = 0;
1490 parameter CLK_POLARITY = 0;
1491 parameter TRANSPARENT = 0;
1494 input [ABITS-1:0] ADDR;
1495 output [WIDTH-1:0] DATA;
1498 if (MEMID != "") begin
1499 $display("ERROR: Found non-simulatable instance of $memrd!");
1506 // --------------------------------------------------------
1508 module \$memwr (CLK, EN, ADDR, DATA);
1510 parameter MEMID = "";
1511 parameter ABITS = 8;
1512 parameter WIDTH = 8;
1514 parameter CLK_ENABLE = 0;
1515 parameter CLK_POLARITY = 0;
1516 parameter PRIORITY = 0;
1519 input [WIDTH-1:0] EN;
1520 input [ABITS-1:0] ADDR;
1521 input [WIDTH-1:0] DATA;
1524 if (MEMID != "") begin
1525 $display("ERROR: Found non-simulatable instance of $memwr!");
1532 // --------------------------------------------------------
1534 module \$meminit (ADDR, DATA);
1536 parameter MEMID = "";
1537 parameter ABITS = 8;
1538 parameter WIDTH = 8;
1540 parameter PRIORITY = 0;
1542 input [ABITS-1:0] ADDR;
1543 input [WIDTH-1:0] DATA;
1546 if (MEMID != "") begin
1547 $display("ERROR: Found non-simulatable instance of $meminit!");
1554 // --------------------------------------------------------
1556 module \$mem (RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
1558 parameter MEMID = "";
1559 parameter signed SIZE = 4;
1560 parameter signed OFFSET = 0;
1561 parameter signed ABITS = 2;
1562 parameter signed WIDTH = 8;
1563 parameter signed INIT = 1'bx;
1565 parameter signed RD_PORTS = 1;
1566 parameter RD_CLK_ENABLE = 1'b1;
1567 parameter RD_CLK_POLARITY = 1'b1;
1568 parameter RD_TRANSPARENT = 1'b1;
1570 parameter signed WR_PORTS = 1;
1571 parameter WR_CLK_ENABLE = 1'b1;
1572 parameter WR_CLK_POLARITY = 1'b1;
1574 input [RD_PORTS-1:0] RD_CLK;
1575 input [RD_PORTS*ABITS-1:0] RD_ADDR;
1576 output reg [RD_PORTS*WIDTH-1:0] RD_DATA;
1578 input [WR_PORTS-1:0] WR_CLK;
1579 input [WR_PORTS*WIDTH-1:0] WR_EN;
1580 input [WR_PORTS*ABITS-1:0] WR_ADDR;
1581 input [WR_PORTS*WIDTH-1:0] WR_DATA;
1583 reg [WIDTH-1:0] memory [SIZE-1:0];
1586 reg [WR_PORTS-1:0] LAST_WR_CLK;
1587 reg [RD_PORTS-1:0] LAST_RD_CLK;
1589 function port_active;
1595 casez ({clk_enable, clk_polarity, last_clk, this_clk})
1596 4'b0???: port_active = 1;
1597 4'b1101: port_active = 1;
1598 4'b1010: port_active = 1;
1599 default: port_active = 0;
1605 for (i = 0; i < SIZE; i = i+1)
1606 memory[i] = INIT >>> (i*WIDTH);
1609 always @(RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA) begin
1610 `ifdef SIMLIB_MEMDELAY
1613 for (i = 0; i < RD_PORTS; i = i+1) begin
1614 if ((!RD_TRANSPARENT[i] && RD_CLK_ENABLE[i]) && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) begin
1615 // $display("Read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]);
1616 RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
1620 for (i = 0; i < WR_PORTS; i = i+1) begin
1621 if (port_active(WR_CLK_ENABLE[i], WR_CLK_POLARITY[i], LAST_WR_CLK[i], WR_CLK[i]))
1622 for (j = 0; j < WIDTH; j = j+1)
1623 if (WR_EN[i*WIDTH+j]) begin
1624 // $display("Write to %s: addr=%b data=%b", MEMID, WR_ADDR[i*ABITS +: ABITS], WR_DATA[i*WIDTH+j]);
1625 memory[WR_ADDR[i*ABITS +: ABITS] - OFFSET][j] = WR_DATA[i*WIDTH+j];
1629 for (i = 0; i < RD_PORTS; i = i+1) begin
1630 if ((RD_TRANSPARENT[i] || !RD_CLK_ENABLE[i]) && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) begin
1631 // $display("Transparent read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]);
1632 RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
1636 LAST_RD_CLK <= RD_CLK;
1637 LAST_WR_CLK <= WR_CLK;
1643 // --------------------------------------------------------