1/* 2 * yosys -- Yosys Open SYnthesis Suite 3 * 4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com> 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// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 37//- 38//- $not (A, Y) 39//- 40//- A bit-wise inverter. This corresponds to the Verilog unary prefix '~' operator. 41//- 42module \$not (A, Y); 43 44parameter A_SIGNED = 0; 45parameter A_WIDTH = 0; 46parameter Y_WIDTH = 0; 47 48input [A_WIDTH-1:0] A; 49output [Y_WIDTH-1:0] Y; 50 51generate 52 if (A_SIGNED) begin:BLOCK1 53 assign Y = ~$signed(A); 54 end else begin:BLOCK2 55 assign Y = ~A; 56 end 57endgenerate 58 59endmodule 60 61 62// -------------------------------------------------------- 63 64// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 65//- 66//- $pos (A, Y) 67//- 68//- A buffer. This corresponds to the Verilog unary prefix '+' operator. 69//- 70module \$pos (A, Y); 71 72parameter A_SIGNED = 0; 73parameter A_WIDTH = 0; 74parameter Y_WIDTH = 0; 75 76input [A_WIDTH-1:0] A; 77output [Y_WIDTH-1:0] Y; 78 79generate 80 if (A_SIGNED) begin:BLOCK1 81 assign Y = $signed(A); 82 end else begin:BLOCK2 83 assign Y = A; 84 end 85endgenerate 86 87endmodule 88 89// -------------------------------------------------------- 90 91// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 92//- 93//- $neg (A, Y) 94//- 95//- An arithmetic inverter. This corresponds to the Verilog unary prefix '-' operator. 96//- 97module \$neg (A, Y); 98 99parameter A_SIGNED = 0; 100parameter A_WIDTH = 0; 101parameter Y_WIDTH = 0; 102 103input [A_WIDTH-1:0] A; 104output [Y_WIDTH-1:0] Y; 105 106generate 107 if (A_SIGNED) begin:BLOCK1 108 assign Y = -$signed(A); 109 end else begin:BLOCK2 110 assign Y = -A; 111 end 112endgenerate 113 114endmodule 115 116// -------------------------------------------------------- 117 118// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 119//- 120//- $and (A, B, Y) 121//- 122//- A bit-wise AND. This corresponds to the Verilog '&' operator. 123//- 124module \$and (A, B, Y); 125 126parameter A_SIGNED = 0; 127parameter B_SIGNED = 0; 128parameter A_WIDTH = 0; 129parameter B_WIDTH = 0; 130parameter Y_WIDTH = 0; 131 132input [A_WIDTH-1:0] A; 133input [B_WIDTH-1:0] B; 134output [Y_WIDTH-1:0] Y; 135 136generate 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 142endgenerate 143 144endmodule 145 146// -------------------------------------------------------- 147 148// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 149//- 150//- $or (A, B, Y) 151//- 152//- A bit-wise OR. This corresponds to the Verilog '|' operator. 153//- 154module \$or (A, B, Y); 155 156parameter A_SIGNED = 0; 157parameter B_SIGNED = 0; 158parameter A_WIDTH = 0; 159parameter B_WIDTH = 0; 160parameter Y_WIDTH = 0; 161 162input [A_WIDTH-1:0] A; 163input [B_WIDTH-1:0] B; 164output [Y_WIDTH-1:0] Y; 165 166generate 167 if (A_SIGNED && B_SIGNED) begin:BLOCK1 168 assign Y = $signed(A) | $signed(B); 169 end else begin:BLOCK2 170 assign Y = A | B; 171 end 172endgenerate 173 174endmodule 175 176// -------------------------------------------------------- 177 178// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 179//- 180//- $xor (A, B, Y) 181//- 182//- A bit-wise XOR. This corresponds to the Verilog '^' operator. 183//- 184module \$xor (A, B, Y); 185 186parameter A_SIGNED = 0; 187parameter B_SIGNED = 0; 188parameter A_WIDTH = 0; 189parameter B_WIDTH = 0; 190parameter Y_WIDTH = 0; 191 192input [A_WIDTH-1:0] A; 193input [B_WIDTH-1:0] B; 194output [Y_WIDTH-1:0] Y; 195 196generate 197 if (A_SIGNED && B_SIGNED) begin:BLOCK1 198 assign Y = $signed(A) ^ $signed(B); 199 end else begin:BLOCK2 200 assign Y = A ^ B; 201 end 202endgenerate 203 204endmodule 205 206// -------------------------------------------------------- 207 208// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 209//- 210//- $xnor (A, B, Y) 211//- 212//- A bit-wise XNOR. This corresponds to the Verilog '~^' operator. 213//- 214module \$xnor (A, B, Y); 215 216parameter A_SIGNED = 0; 217parameter B_SIGNED = 0; 218parameter A_WIDTH = 0; 219parameter B_WIDTH = 0; 220parameter Y_WIDTH = 0; 221 222input [A_WIDTH-1:0] A; 223input [B_WIDTH-1:0] B; 224output [Y_WIDTH-1:0] Y; 225 226generate 227 if (A_SIGNED && B_SIGNED) begin:BLOCK1 228 assign Y = $signed(A) ~^ $signed(B); 229 end else begin:BLOCK2 230 assign Y = A ~^ B; 231 end 232endgenerate 233 234endmodule 235 236// -------------------------------------------------------- 237 238// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 239//- 240//- $reduce_and (A, Y) 241//- 242//- An AND reduction. This corresponds to the Verilog unary prefix '&' operator. 243//- 244module \$reduce_and (A, Y); 245 246parameter A_SIGNED = 0; 247parameter A_WIDTH = 0; 248parameter Y_WIDTH = 0; 249 250input [A_WIDTH-1:0] A; 251output [Y_WIDTH-1:0] Y; 252 253generate 254 if (A_SIGNED) begin:BLOCK1 255 assign Y = &$signed(A); 256 end else begin:BLOCK2 257 assign Y = &A; 258 end 259endgenerate 260 261endmodule 262 263// -------------------------------------------------------- 264 265// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 266//- 267//- $reduce_or (A, Y) 268//- 269//- An OR reduction. This corresponds to the Verilog unary prefix '|' operator. 270//- 271module \$reduce_or (A, Y); 272 273parameter A_SIGNED = 0; 274parameter A_WIDTH = 0; 275parameter Y_WIDTH = 0; 276 277input [A_WIDTH-1:0] A; 278output [Y_WIDTH-1:0] Y; 279 280generate 281 if (A_SIGNED) begin:BLOCK1 282 assign Y = |$signed(A); 283 end else begin:BLOCK2 284 assign Y = |A; 285 end 286endgenerate 287 288endmodule 289 290// -------------------------------------------------------- 291 292// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 293//- 294//- $reduce_xor (A, Y) 295//- 296//- A XOR reduction. This corresponds to the Verilog unary prefix '^' operator. 297//- 298module \$reduce_xor (A, Y); 299 300parameter A_SIGNED = 0; 301parameter A_WIDTH = 0; 302parameter Y_WIDTH = 0; 303 304input [A_WIDTH-1:0] A; 305output [Y_WIDTH-1:0] Y; 306 307generate 308 if (A_SIGNED) begin:BLOCK1 309 assign Y = ^$signed(A); 310 end else begin:BLOCK2 311 assign Y = ^A; 312 end 313endgenerate 314 315endmodule 316 317// -------------------------------------------------------- 318 319// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 320//- 321//- $reduce_xnor (A, Y) 322//- 323//- A XNOR reduction. This corresponds to the Verilog unary prefix '~^' operator. 324//- 325module \$reduce_xnor (A, Y); 326 327parameter A_SIGNED = 0; 328parameter A_WIDTH = 0; 329parameter Y_WIDTH = 0; 330 331input [A_WIDTH-1:0] A; 332output [Y_WIDTH-1:0] Y; 333 334generate 335 if (A_SIGNED) begin:BLOCK1 336 assign Y = ~^$signed(A); 337 end else begin:BLOCK2 338 assign Y = ~^A; 339 end 340endgenerate 341 342endmodule 343 344// -------------------------------------------------------- 345 346// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 347//- 348//- $reduce_bool (A, Y) 349//- 350//- An OR reduction. This cell type is used instead of $reduce_or when a signal is 351//- implicitly converted to a boolean signal, e.g. for operands of '&&' and '||'. 352//- 353module \$reduce_bool (A, Y); 354 355parameter A_SIGNED = 0; 356parameter A_WIDTH = 0; 357parameter Y_WIDTH = 0; 358 359input [A_WIDTH-1:0] A; 360output [Y_WIDTH-1:0] Y; 361 362generate 363 if (A_SIGNED) begin:BLOCK1 364 assign Y = !(!$signed(A)); 365 end else begin:BLOCK2 366 assign Y = !(!A); 367 end 368endgenerate 369 370endmodule 371 372// -------------------------------------------------------- 373 374module \$shl (A, B, Y); 375 376parameter A_SIGNED = 0; 377parameter B_SIGNED = 0; 378parameter A_WIDTH = 0; 379parameter B_WIDTH = 0; 380parameter Y_WIDTH = 0; 381 382input [A_WIDTH-1:0] A; 383input [B_WIDTH-1:0] B; 384output [Y_WIDTH-1:0] Y; 385 386generate 387 if (A_SIGNED) begin:BLOCK1 388 assign Y = $signed(A) << B; 389 end else begin:BLOCK2 390 assign Y = A << B; 391 end 392endgenerate 393 394endmodule 395 396// -------------------------------------------------------- 397 398module \$shr (A, B, Y); 399 400parameter A_SIGNED = 0; 401parameter B_SIGNED = 0; 402parameter A_WIDTH = 0; 403parameter B_WIDTH = 0; 404parameter Y_WIDTH = 0; 405 406input [A_WIDTH-1:0] A; 407input [B_WIDTH-1:0] B; 408output [Y_WIDTH-1:0] Y; 409 410generate 411 if (A_SIGNED) begin:BLOCK1 412 assign Y = $signed(A) >> B; 413 end else begin:BLOCK2 414 assign Y = A >> B; 415 end 416endgenerate 417 418endmodule 419 420// -------------------------------------------------------- 421 422module \$sshl (A, B, Y); 423 424parameter A_SIGNED = 0; 425parameter B_SIGNED = 0; 426parameter A_WIDTH = 0; 427parameter B_WIDTH = 0; 428parameter Y_WIDTH = 0; 429 430input [A_WIDTH-1:0] A; 431input [B_WIDTH-1:0] B; 432output [Y_WIDTH-1:0] Y; 433 434generate 435 if (A_SIGNED) begin:BLOCK1 436 assign Y = $signed(A) <<< B; 437 end else begin:BLOCK2 438 assign Y = A <<< B; 439 end 440endgenerate 441 442endmodule 443 444// -------------------------------------------------------- 445 446module \$sshr (A, B, Y); 447 448parameter A_SIGNED = 0; 449parameter B_SIGNED = 0; 450parameter A_WIDTH = 0; 451parameter B_WIDTH = 0; 452parameter Y_WIDTH = 0; 453 454input [A_WIDTH-1:0] A; 455input [B_WIDTH-1:0] B; 456output [Y_WIDTH-1:0] Y; 457 458generate 459 if (A_SIGNED) begin:BLOCK1 460 assign Y = $signed(A) >>> B; 461 end else begin:BLOCK2 462 assign Y = A >>> B; 463 end 464endgenerate 465 466endmodule 467 468// -------------------------------------------------------- 469 470module \$shift (A, B, Y); 471 472parameter A_SIGNED = 0; 473parameter B_SIGNED = 0; 474parameter A_WIDTH = 0; 475parameter B_WIDTH = 0; 476parameter Y_WIDTH = 0; 477 478input [A_WIDTH-1:0] A; 479input [B_WIDTH-1:0] B; 480output [Y_WIDTH-1:0] Y; 481 482generate 483 if (A_SIGNED) begin:BLOCK1 484 if (B_SIGNED) begin:BLOCK2 485 assign Y = $signed(B) < 0 ? $signed(A) << -B : $signed(A) >> B; 486 end else begin:BLOCK3 487 assign Y = $signed(A) >> B; 488 end 489 end else begin:BLOCK4 490 if (B_SIGNED) begin:BLOCK5 491 assign Y = $signed(B) < 0 ? A << -B : A >> B; 492 end else begin:BLOCK6 493 assign Y = A >> B; 494 end 495 end 496endgenerate 497 498endmodule 499 500// -------------------------------------------------------- 501 502module \$shiftx (A, B, Y); 503 504parameter A_SIGNED = 0; 505parameter B_SIGNED = 0; 506parameter A_WIDTH = 0; 507parameter B_WIDTH = 0; 508parameter Y_WIDTH = 0; 509 510input [A_WIDTH-1:0] A; 511input [B_WIDTH-1:0] B; 512output [Y_WIDTH-1:0] Y; 513 514generate 515 if (Y_WIDTH > 0) 516 if (B_SIGNED) begin:BLOCK1 517 assign Y = A[$signed(B) +: Y_WIDTH]; 518 end else begin:BLOCK2 519 assign Y = A[B +: Y_WIDTH]; 520 end 521endgenerate 522 523endmodule 524 525// -------------------------------------------------------- 526 527module \$fa (A, B, C, X, Y); 528 529parameter WIDTH = 1; 530 531input [WIDTH-1:0] A, B, C; 532output [WIDTH-1:0] X, Y; 533 534wire [WIDTH-1:0] t1, t2, t3; 535 536assign t1 = A ^ B, t2 = A & B, t3 = C & t1; 537assign Y = t1 ^ C, X = (t2 | t3) ^ (Y ^ Y); 538 539endmodule 540 541// -------------------------------------------------------- 542 543// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 544//- 545//- $lcu (P, G, CI, CO) 546//- 547//- Lookahead carry unit 548//- A building block dedicated to fast computation of carry-bits used in binary 549//- arithmetic operations. By replacing the ripple carry structure used in full-adder 550//- blocks, the more significant bits of the sum can be expected to be computed more 551//- quickly. 552//- Typically created during `techmap` of $alu cells (see the "_90_alu" rule in 553//- +/techmap.v). 554module \$lcu (P, G, CI, CO); 555 556parameter WIDTH = 1; 557 558input [WIDTH-1:0] P; // Propagate 559input [WIDTH-1:0] G; // Generate 560input CI; // Carry-in 561 562output reg [WIDTH-1:0] CO; // Carry-out 563 564integer i; 565always @* begin 566 CO = 'bx; 567 if (^{P, G, CI} !== 1'bx) begin 568 CO[0] = G[0] || (P[0] && CI); 569 for (i = 1; i < WIDTH; i = i+1) 570 CO[i] = G[i] || (P[i] && CO[i-1]); 571 end 572end 573 574endmodule 575 576// -------------------------------------------------------- 577 578// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 579//- 580//- $alu (A, B, CI, BI, X, Y, CO) 581//- 582//- Arithmetic logic unit. 583//- A building block supporting both binary addition/subtraction operations, and 584//- indirectly, comparison operations. 585//- Typically created by the `alumacc` pass, which transforms: 586//- $add, $sub, $lt, $le, $ge, $gt, $eq, $eqx, $ne, $nex 587//- cells into this $alu cell. 588//- 589module \$alu (A, B, CI, BI, X, Y, CO); 590 591parameter A_SIGNED = 0; 592parameter B_SIGNED = 0; 593parameter A_WIDTH = 1; 594parameter B_WIDTH = 1; 595parameter Y_WIDTH = 1; 596 597input [A_WIDTH-1:0] A; // Input operand 598input [B_WIDTH-1:0] B; // Input operand 599output [Y_WIDTH-1:0] X; // A xor B (sign-extended, optional B inversion, 600 // used in combination with 601 // reduction-AND for $eq/$ne ops) 602output [Y_WIDTH-1:0] Y; // Sum 603 604input CI; // Carry-in (set for $sub) 605input BI; // Invert-B (set for $sub) 606output [Y_WIDTH-1:0] CO; // Carry-out 607 608wire [Y_WIDTH-1:0] AA, BB; 609 610generate 611 if (A_SIGNED && B_SIGNED) begin:BLOCK1 612 assign AA = $signed(A), BB = BI ? ~$signed(B) : $signed(B); 613 end else begin:BLOCK2 614 assign AA = $unsigned(A), BB = BI ? ~$unsigned(B) : $unsigned(B); 615 end 616endgenerate 617 618// this is 'x' if Y and CO should be all 'x', and '0' otherwise 619wire y_co_undef = ^{A, A, B, B, CI, CI, BI, BI}; 620 621assign X = AA ^ BB; 622// Full adder 623assign Y = (AA + BB + CI) ^ {Y_WIDTH{y_co_undef}}; 624 625function get_carry; 626 input a, b, c; 627 get_carry = (a&b) | (a&c) | (b&c); 628endfunction 629 630genvar i; 631generate 632 assign CO[0] = get_carry(AA[0], BB[0], CI) ^ y_co_undef; 633 for (i = 1; i < Y_WIDTH; i = i+1) begin:BLOCK3 634 assign CO[i] = get_carry(AA[i], BB[i], CO[i-1]) ^ y_co_undef; 635 end 636endgenerate 637 638endmodule 639 640// -------------------------------------------------------- 641 642module \$lt (A, B, Y); 643 644parameter A_SIGNED = 0; 645parameter B_SIGNED = 0; 646parameter A_WIDTH = 0; 647parameter B_WIDTH = 0; 648parameter Y_WIDTH = 0; 649 650input [A_WIDTH-1:0] A; 651input [B_WIDTH-1:0] B; 652output [Y_WIDTH-1:0] Y; 653 654generate 655 if (A_SIGNED && B_SIGNED) begin:BLOCK1 656 assign Y = $signed(A) < $signed(B); 657 end else begin:BLOCK2 658 assign Y = A < B; 659 end 660endgenerate 661 662endmodule 663 664// -------------------------------------------------------- 665 666module \$le (A, B, Y); 667 668parameter A_SIGNED = 0; 669parameter B_SIGNED = 0; 670parameter A_WIDTH = 0; 671parameter B_WIDTH = 0; 672parameter Y_WIDTH = 0; 673 674input [A_WIDTH-1:0] A; 675input [B_WIDTH-1:0] B; 676output [Y_WIDTH-1:0] Y; 677 678generate 679 if (A_SIGNED && B_SIGNED) begin:BLOCK1 680 assign Y = $signed(A) <= $signed(B); 681 end else begin:BLOCK2 682 assign Y = A <= B; 683 end 684endgenerate 685 686endmodule 687 688// -------------------------------------------------------- 689 690module \$eq (A, B, Y); 691 692parameter A_SIGNED = 0; 693parameter B_SIGNED = 0; 694parameter A_WIDTH = 0; 695parameter B_WIDTH = 0; 696parameter Y_WIDTH = 0; 697 698input [A_WIDTH-1:0] A; 699input [B_WIDTH-1:0] B; 700output [Y_WIDTH-1:0] Y; 701 702generate 703 if (A_SIGNED && B_SIGNED) begin:BLOCK1 704 assign Y = $signed(A) == $signed(B); 705 end else begin:BLOCK2 706 assign Y = A == B; 707 end 708endgenerate 709 710endmodule 711 712// -------------------------------------------------------- 713 714module \$ne (A, B, Y); 715 716parameter A_SIGNED = 0; 717parameter B_SIGNED = 0; 718parameter A_WIDTH = 0; 719parameter B_WIDTH = 0; 720parameter Y_WIDTH = 0; 721 722input [A_WIDTH-1:0] A; 723input [B_WIDTH-1:0] B; 724output [Y_WIDTH-1:0] Y; 725 726generate 727 if (A_SIGNED && B_SIGNED) begin:BLOCK1 728 assign Y = $signed(A) != $signed(B); 729 end else begin:BLOCK2 730 assign Y = A != B; 731 end 732endgenerate 733 734endmodule 735 736// -------------------------------------------------------- 737 738module \$eqx (A, B, Y); 739 740parameter A_SIGNED = 0; 741parameter B_SIGNED = 0; 742parameter A_WIDTH = 0; 743parameter B_WIDTH = 0; 744parameter Y_WIDTH = 0; 745 746input [A_WIDTH-1:0] A; 747input [B_WIDTH-1:0] B; 748output [Y_WIDTH-1:0] Y; 749 750generate 751 if (A_SIGNED && B_SIGNED) begin:BLOCK1 752 assign Y = $signed(A) === $signed(B); 753 end else begin:BLOCK2 754 assign Y = A === B; 755 end 756endgenerate 757 758endmodule 759 760// -------------------------------------------------------- 761 762module \$nex (A, B, Y); 763 764parameter A_SIGNED = 0; 765parameter B_SIGNED = 0; 766parameter A_WIDTH = 0; 767parameter B_WIDTH = 0; 768parameter Y_WIDTH = 0; 769 770input [A_WIDTH-1:0] A; 771input [B_WIDTH-1:0] B; 772output [Y_WIDTH-1:0] Y; 773 774generate 775 if (A_SIGNED && B_SIGNED) begin:BLOCK1 776 assign Y = $signed(A) !== $signed(B); 777 end else begin:BLOCK2 778 assign Y = A !== B; 779 end 780endgenerate 781 782endmodule 783 784// -------------------------------------------------------- 785 786module \$ge (A, B, Y); 787 788parameter A_SIGNED = 0; 789parameter B_SIGNED = 0; 790parameter A_WIDTH = 0; 791parameter B_WIDTH = 0; 792parameter Y_WIDTH = 0; 793 794input [A_WIDTH-1:0] A; 795input [B_WIDTH-1:0] B; 796output [Y_WIDTH-1:0] Y; 797 798generate 799 if (A_SIGNED && B_SIGNED) begin:BLOCK1 800 assign Y = $signed(A) >= $signed(B); 801 end else begin:BLOCK2 802 assign Y = A >= B; 803 end 804endgenerate 805 806endmodule 807 808// -------------------------------------------------------- 809 810module \$gt (A, B, Y); 811 812parameter A_SIGNED = 0; 813parameter B_SIGNED = 0; 814parameter A_WIDTH = 0; 815parameter B_WIDTH = 0; 816parameter Y_WIDTH = 0; 817 818input [A_WIDTH-1:0] A; 819input [B_WIDTH-1:0] B; 820output [Y_WIDTH-1:0] Y; 821 822generate 823 if (A_SIGNED && B_SIGNED) begin:BLOCK1 824 assign Y = $signed(A) > $signed(B); 825 end else begin:BLOCK2 826 assign Y = A > B; 827 end 828endgenerate 829 830endmodule 831 832// -------------------------------------------------------- 833 834module \$add (A, B, Y); 835 836parameter A_SIGNED = 0; 837parameter B_SIGNED = 0; 838parameter A_WIDTH = 0; 839parameter B_WIDTH = 0; 840parameter Y_WIDTH = 0; 841 842input [A_WIDTH-1:0] A; 843input [B_WIDTH-1:0] B; 844output [Y_WIDTH-1:0] Y; 845 846generate 847 if (A_SIGNED && B_SIGNED) begin:BLOCK1 848 assign Y = $signed(A) + $signed(B); 849 end else begin:BLOCK2 850 assign Y = A + B; 851 end 852endgenerate 853 854endmodule 855 856// -------------------------------------------------------- 857 858module \$sub (A, B, Y); 859 860parameter A_SIGNED = 0; 861parameter B_SIGNED = 0; 862parameter A_WIDTH = 0; 863parameter B_WIDTH = 0; 864parameter Y_WIDTH = 0; 865 866input [A_WIDTH-1:0] A; 867input [B_WIDTH-1:0] B; 868output [Y_WIDTH-1:0] Y; 869 870generate 871 if (A_SIGNED && B_SIGNED) begin:BLOCK1 872 assign Y = $signed(A) - $signed(B); 873 end else begin:BLOCK2 874 assign Y = A - B; 875 end 876endgenerate 877 878endmodule 879 880// -------------------------------------------------------- 881 882module \$mul (A, B, Y); 883 884parameter A_SIGNED = 0; 885parameter B_SIGNED = 0; 886parameter A_WIDTH = 0; 887parameter B_WIDTH = 0; 888parameter Y_WIDTH = 0; 889 890input [A_WIDTH-1:0] A; 891input [B_WIDTH-1:0] B; 892output [Y_WIDTH-1:0] Y; 893 894generate 895 if (A_SIGNED && B_SIGNED) begin:BLOCK1 896 assign Y = $signed(A) * $signed(B); 897 end else begin:BLOCK2 898 assign Y = A * B; 899 end 900endgenerate 901 902endmodule 903 904// -------------------------------------------------------- 905 906module \$macc (A, B, Y); 907 908parameter A_WIDTH = 0; 909parameter B_WIDTH = 0; 910parameter Y_WIDTH = 0; 911parameter CONFIG = 4'b0000; 912parameter CONFIG_WIDTH = 4; 913 914input [A_WIDTH-1:0] A; 915input [B_WIDTH-1:0] B; 916output reg [Y_WIDTH-1:0] Y; 917 918// Xilinx XSIM does not like $clog2() below.. 919function integer my_clog2; 920 input integer v; 921 begin 922 if (v > 0) 923 v = v - 1; 924 my_clog2 = 0; 925 while (v) begin 926 v = v >> 1; 927 my_clog2 = my_clog2 + 1; 928 end 929 end 930endfunction 931 932localparam integer num_bits = CONFIG[3:0] > 0 ? CONFIG[3:0] : 1; 933localparam integer num_ports = (CONFIG_WIDTH-4) / (2 + 2*num_bits); 934localparam integer num_abits = my_clog2(A_WIDTH) > 0 ? my_clog2(A_WIDTH) : 1; 935 936function [2*num_ports*num_abits-1:0] get_port_offsets; 937 input [CONFIG_WIDTH-1:0] cfg; 938 integer i, cursor; 939 begin 940 cursor = 0; 941 get_port_offsets = 0; 942 for (i = 0; i < num_ports; i = i+1) begin 943 get_port_offsets[(2*i + 0)*num_abits +: num_abits] = cursor; 944 cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 +: num_bits]; 945 get_port_offsets[(2*i + 1)*num_abits +: num_abits] = cursor; 946 cursor = cursor + cfg[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]; 947 end 948 end 949endfunction 950 951localparam [2*num_ports*num_abits-1:0] port_offsets = get_port_offsets(CONFIG); 952 953`define PORT_IS_SIGNED (0 + CONFIG[4 + i*(2 + 2*num_bits)]) 954`define PORT_DO_SUBTRACT (0 + CONFIG[4 + i*(2 + 2*num_bits) + 1]) 955`define PORT_SIZE_A (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 +: num_bits]) 956`define PORT_SIZE_B (0 + CONFIG[4 + i*(2 + 2*num_bits) + 2 + num_bits +: num_bits]) 957`define PORT_OFFSET_A (0 + port_offsets[2*i*num_abits +: num_abits]) 958`define PORT_OFFSET_B (0 + port_offsets[2*i*num_abits + num_abits +: num_abits]) 959 960integer i, j; 961reg [Y_WIDTH-1:0] tmp_a, tmp_b; 962 963always @* begin 964 Y = 0; 965 for (i = 0; i < num_ports; i = i+1) 966 begin 967 tmp_a = 0; 968 tmp_b = 0; 969 970 for (j = 0; j < `PORT_SIZE_A; j = j+1) 971 tmp_a[j] = A[`PORT_OFFSET_A + j]; 972 973 if (`PORT_IS_SIGNED && `PORT_SIZE_A > 0) 974 for (j = `PORT_SIZE_A; j < Y_WIDTH; j = j+1) 975 tmp_a[j] = tmp_a[`PORT_SIZE_A-1]; 976 977 for (j = 0; j < `PORT_SIZE_B; j = j+1) 978 tmp_b[j] = A[`PORT_OFFSET_B + j]; 979 980 if (`PORT_IS_SIGNED && `PORT_SIZE_B > 0) 981 for (j = `PORT_SIZE_B; j < Y_WIDTH; j = j+1) 982 tmp_b[j] = tmp_b[`PORT_SIZE_B-1]; 983 984 if (`PORT_SIZE_B > 0) 985 tmp_a = tmp_a * tmp_b; 986 987 if (`PORT_DO_SUBTRACT) 988 Y = Y - tmp_a; 989 else 990 Y = Y + tmp_a; 991 end 992 for (i = 0; i < B_WIDTH; i = i+1) begin 993 Y = Y + B[i]; 994 end 995end 996 997`undef PORT_IS_SIGNED 998`undef PORT_DO_SUBTRACT 999`undef PORT_SIZE_A 1000`undef PORT_SIZE_B 1001`undef PORT_OFFSET_A 1002`undef PORT_OFFSET_B 1003 1004endmodule 1005 1006// -------------------------------------------------------- 1007 1008// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 1009//- 1010//- $div (A, B, Y) 1011//- 1012//- Division with truncated result (rounded towards 0). 1013//- 1014module \$div (A, B, Y); 1015 1016parameter A_SIGNED = 0; 1017parameter B_SIGNED = 0; 1018parameter A_WIDTH = 0; 1019parameter B_WIDTH = 0; 1020parameter Y_WIDTH = 0; 1021 1022input [A_WIDTH-1:0] A; 1023input [B_WIDTH-1:0] B; 1024output [Y_WIDTH-1:0] Y; 1025 1026generate 1027 if (A_SIGNED && B_SIGNED) begin:BLOCK1 1028 assign Y = $signed(A) / $signed(B); 1029 end else begin:BLOCK2 1030 assign Y = A / B; 1031 end 1032endgenerate 1033 1034endmodule 1035 1036// -------------------------------------------------------- 1037 1038// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 1039//- 1040//- $mod (A, B, Y) 1041//- 1042//- Modulo/remainder of division with truncated result (rounded towards 0). 1043//- 1044//- Invariant: $div(A, B) * B + $mod(A, B) == A 1045//- 1046module \$mod (A, B, Y); 1047 1048parameter A_SIGNED = 0; 1049parameter B_SIGNED = 0; 1050parameter A_WIDTH = 0; 1051parameter B_WIDTH = 0; 1052parameter Y_WIDTH = 0; 1053 1054input [A_WIDTH-1:0] A; 1055input [B_WIDTH-1:0] B; 1056output [Y_WIDTH-1:0] Y; 1057 1058generate 1059 if (A_SIGNED && B_SIGNED) begin:BLOCK1 1060 assign Y = $signed(A) % $signed(B); 1061 end else begin:BLOCK2 1062 assign Y = A % B; 1063 end 1064endgenerate 1065 1066endmodule 1067 1068// -------------------------------------------------------- 1069 1070// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 1071//- 1072//- $divfloor (A, B, Y) 1073//- 1074//- Division with floored result (rounded towards negative infinity). 1075//- 1076module \$divfloor (A, B, Y); 1077 1078parameter A_SIGNED = 0; 1079parameter B_SIGNED = 0; 1080parameter A_WIDTH = 0; 1081parameter B_WIDTH = 0; 1082parameter Y_WIDTH = 0; 1083 1084input [A_WIDTH-1:0] A; 1085input [B_WIDTH-1:0] B; 1086output [Y_WIDTH-1:0] Y; 1087 1088generate 1089 if (A_SIGNED && B_SIGNED) begin:BLOCK1 1090 localparam WIDTH = 1091 A_WIDTH >= B_WIDTH && A_WIDTH >= Y_WIDTH ? A_WIDTH : 1092 B_WIDTH >= A_WIDTH && B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; 1093 wire [WIDTH:0] A_buf, B_buf, N_buf; 1094 assign A_buf = $signed(A); 1095 assign B_buf = $signed(B); 1096 assign N_buf = (A[A_WIDTH-1] == B[B_WIDTH-1]) || A == 0 ? A_buf : $signed(A_buf - (B[B_WIDTH-1] ? B_buf+1 : B_buf-1)); 1097 assign Y = $signed(N_buf) / $signed(B_buf); 1098 end else begin:BLOCK2 1099 assign Y = A / B; 1100 end 1101endgenerate 1102 1103endmodule 1104 1105// -------------------------------------------------------- 1106 1107// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| 1108//- 1109//- $modfloor (A, B, Y) 1110//- 1111//- Modulo/remainder of division with floored result (rounded towards negative infinity). 1112//- 1113//- Invariant: $divfloor(A, B) * B + $modfloor(A, B) == A 1114//- 1115module \$modfloor (A, B, Y); 1116 1117parameter A_SIGNED = 0; 1118parameter B_SIGNED = 0; 1119parameter A_WIDTH = 0; 1120parameter B_WIDTH = 0; 1121parameter Y_WIDTH = 0; 1122 1123input [A_WIDTH-1:0] A; 1124input [B_WIDTH-1:0] B; 1125output [Y_WIDTH-1:0] Y; 1126 1127generate 1128 if (A_SIGNED && B_SIGNED) begin:BLOCK1 1129 localparam WIDTH = B_WIDTH >= Y_WIDTH ? B_WIDTH : Y_WIDTH; 1130 wire [WIDTH-1:0] B_buf, Y_trunc; 1131 assign B_buf = $signed(B); 1132 assign Y_trunc = $signed(A) % $signed(B); 1133 // flooring mod is the same as truncating mod for positive division results (A and B have 1134 // the same sign), as well as when there's no remainder. 1135 // For all other cases, they behave as `floor - trunc = B` 1136 assign Y = (A[A_WIDTH-1] == B[B_WIDTH-1]) || Y_trunc == 0 ? Y_trunc : $signed(B_buf) + $signed(Y_trunc); 1137 end else begin:BLOCK2 1138 // no difference between truncating and flooring for unsigned 1139 assign Y = A % B; 1140 end 1141endgenerate 1142 1143endmodule 1144 1145// -------------------------------------------------------- 1146`ifndef SIMLIB_NOPOW 1147 1148module \$pow (A, B, Y); 1149 1150parameter A_SIGNED = 0; 1151parameter B_SIGNED = 0; 1152parameter A_WIDTH = 0; 1153parameter B_WIDTH = 0; 1154parameter Y_WIDTH = 0; 1155 1156input [A_WIDTH-1:0] A; 1157input [B_WIDTH-1:0] B; 1158output [Y_WIDTH-1:0] Y; 1159 1160generate 1161 if (A_SIGNED && B_SIGNED) begin:BLOCK1 1162 assign Y = $signed(A) ** $signed(B); 1163 end else if (A_SIGNED) begin:BLOCK2 1164 assign Y = $signed(A) ** B; 1165 end else if (B_SIGNED) begin:BLOCK3 1166 assign Y = A ** $signed(B); 1167 end else begin:BLOCK4 1168 assign Y = A ** B; 1169 end 1170endgenerate 1171 1172endmodule 1173 1174`endif 1175// -------------------------------------------------------- 1176 1177module \$logic_not (A, Y); 1178 1179parameter A_SIGNED = 0; 1180parameter A_WIDTH = 0; 1181parameter Y_WIDTH = 0; 1182 1183input [A_WIDTH-1:0] A; 1184output [Y_WIDTH-1:0] Y; 1185 1186generate 1187 if (A_SIGNED) begin:BLOCK1 1188 assign Y = !$signed(A); 1189 end else begin:BLOCK2 1190 assign Y = !A; 1191 end 1192endgenerate 1193 1194endmodule 1195 1196// -------------------------------------------------------- 1197 1198module \$logic_and (A, B, Y); 1199 1200parameter A_SIGNED = 0; 1201parameter B_SIGNED = 0; 1202parameter A_WIDTH = 0; 1203parameter B_WIDTH = 0; 1204parameter Y_WIDTH = 0; 1205 1206input [A_WIDTH-1:0] A; 1207input [B_WIDTH-1:0] B; 1208output [Y_WIDTH-1:0] Y; 1209 1210generate 1211 if (A_SIGNED && B_SIGNED) begin:BLOCK1 1212 assign Y = $signed(A) && $signed(B); 1213 end else begin:BLOCK2 1214 assign Y = A && B; 1215 end 1216endgenerate 1217 1218endmodule 1219 1220// -------------------------------------------------------- 1221 1222module \$logic_or (A, B, Y); 1223 1224parameter A_SIGNED = 0; 1225parameter B_SIGNED = 0; 1226parameter A_WIDTH = 0; 1227parameter B_WIDTH = 0; 1228parameter Y_WIDTH = 0; 1229 1230input [A_WIDTH-1:0] A; 1231input [B_WIDTH-1:0] B; 1232output [Y_WIDTH-1:0] Y; 1233 1234generate 1235 if (A_SIGNED && B_SIGNED) begin:BLOCK1 1236 assign Y = $signed(A) || $signed(B); 1237 end else begin:BLOCK2 1238 assign Y = A || B; 1239 end 1240endgenerate 1241 1242endmodule 1243 1244// -------------------------------------------------------- 1245 1246module \$slice (A, Y); 1247 1248parameter OFFSET = 0; 1249parameter A_WIDTH = 0; 1250parameter Y_WIDTH = 0; 1251 1252input [A_WIDTH-1:0] A; 1253output [Y_WIDTH-1:0] Y; 1254 1255assign Y = A >> OFFSET; 1256 1257endmodule 1258 1259// -------------------------------------------------------- 1260 1261module \$concat (A, B, Y); 1262 1263parameter A_WIDTH = 0; 1264parameter B_WIDTH = 0; 1265 1266input [A_WIDTH-1:0] A; 1267input [B_WIDTH-1:0] B; 1268output [A_WIDTH+B_WIDTH-1:0] Y; 1269 1270assign Y = {B, A}; 1271 1272endmodule 1273 1274// -------------------------------------------------------- 1275 1276module \$mux (A, B, S, Y); 1277 1278parameter WIDTH = 0; 1279 1280input [WIDTH-1:0] A, B; 1281input S; 1282output reg [WIDTH-1:0] Y; 1283 1284always @* begin 1285 if (S) 1286 Y = B; 1287 else 1288 Y = A; 1289end 1290 1291endmodule 1292 1293// -------------------------------------------------------- 1294 1295module \$pmux (A, B, S, Y); 1296 1297parameter WIDTH = 0; 1298parameter S_WIDTH = 0; 1299 1300input [WIDTH-1:0] A; 1301input [WIDTH*S_WIDTH-1:0] B; 1302input [S_WIDTH-1:0] S; 1303output reg [WIDTH-1:0] Y; 1304 1305integer i; 1306reg found_active_sel_bit; 1307 1308always @* begin 1309 Y = A; 1310 found_active_sel_bit = 0; 1311 for (i = 0; i < S_WIDTH; i = i+1) 1312 if (S[i]) begin 1313 Y = found_active_sel_bit ? 'bx : B >> (WIDTH*i); 1314 found_active_sel_bit = 1; 1315 end 1316end 1317 1318endmodule 1319 1320// -------------------------------------------------------- 1321`ifndef SIMLIB_NOLUT 1322 1323module \$lut (A, Y); 1324 1325parameter WIDTH = 0; 1326parameter LUT = 0; 1327 1328input [WIDTH-1:0] A; 1329output reg Y; 1330 1331wire lut0_out, lut1_out; 1332 1333generate 1334 if (WIDTH <= 1) begin:simple 1335 assign {lut1_out, lut0_out} = LUT; 1336 end else begin:complex 1337 \$lut #( .WIDTH(WIDTH-1), .LUT(LUT ) ) lut0 ( .A(A[WIDTH-2:0]), .Y(lut0_out) ); 1338 \$lut #( .WIDTH(WIDTH-1), .LUT(LUT >> (2**(WIDTH-1))) ) lut1 ( .A(A[WIDTH-2:0]), .Y(lut1_out) ); 1339 end 1340 1341 if (WIDTH > 0) begin:lutlogic 1342 always @* begin 1343 casez ({A[WIDTH-1], lut0_out, lut1_out}) 1344 3'b?11: Y = 1'b1; 1345 3'b?00: Y = 1'b0; 1346 3'b0??: Y = lut0_out; 1347 3'b1??: Y = lut1_out; 1348 default: Y = 1'bx; 1349 endcase 1350 end 1351 end 1352endgenerate 1353 1354endmodule 1355 1356`endif 1357// -------------------------------------------------------- 1358 1359module \$sop (A, Y); 1360 1361parameter WIDTH = 0; 1362parameter DEPTH = 0; 1363parameter TABLE = 0; 1364 1365input [WIDTH-1:0] A; 1366output reg Y; 1367 1368integer i, j; 1369reg match; 1370 1371always @* begin 1372 Y = 0; 1373 for (i = 0; i < DEPTH; i=i+1) begin 1374 match = 1; 1375 for (j = 0; j < WIDTH; j=j+1) begin 1376 if (TABLE[2*WIDTH*i + 2*j + 0] && A[j]) match = 0; 1377 if (TABLE[2*WIDTH*i + 2*j + 1] && !A[j]) match = 0; 1378 end 1379 if (match) Y = 1; 1380 end 1381end 1382 1383endmodule 1384 1385// -------------------------------------------------------- 1386 1387module \$tribuf (A, EN, Y); 1388 1389parameter WIDTH = 0; 1390 1391input [WIDTH-1:0] A; 1392input EN; 1393output [WIDTH-1:0] Y; 1394 1395assign Y = EN ? A : 'bz; 1396 1397endmodule 1398 1399// -------------------------------------------------------- 1400 1401module \$specify2 (EN, SRC, DST); 1402 1403parameter FULL = 0; 1404parameter SRC_WIDTH = 1; 1405parameter DST_WIDTH = 1; 1406 1407parameter SRC_DST_PEN = 0; 1408parameter SRC_DST_POL = 0; 1409 1410parameter T_RISE_MIN = 0; 1411parameter T_RISE_TYP = 0; 1412parameter T_RISE_MAX = 0; 1413 1414parameter T_FALL_MIN = 0; 1415parameter T_FALL_TYP = 0; 1416parameter T_FALL_MAX = 0; 1417 1418input EN; 1419input [SRC_WIDTH-1:0] SRC; 1420input [DST_WIDTH-1:0] DST; 1421 1422localparam SD = SRC_DST_PEN ? (SRC_DST_POL ? 1 : 2) : 0; 1423 1424`ifdef SIMLIB_SPECIFY 1425specify 1426 if (EN && SD==0 && !FULL) (SRC => DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1427 if (EN && SD==0 && FULL) (SRC *> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1428 if (EN && SD==1 && !FULL) (SRC +=> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1429 if (EN && SD==1 && FULL) (SRC +*> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1430 if (EN && SD==2 && !FULL) (SRC -=> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1431 if (EN && SD==2 && FULL) (SRC -*> DST) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1432endspecify 1433`endif 1434 1435endmodule 1436 1437// -------------------------------------------------------- 1438 1439module \$specify3 (EN, SRC, DST, DAT); 1440 1441parameter FULL = 0; 1442parameter SRC_WIDTH = 1; 1443parameter DST_WIDTH = 1; 1444 1445parameter EDGE_EN = 0; 1446parameter EDGE_POL = 0; 1447 1448parameter SRC_DST_PEN = 0; 1449parameter SRC_DST_POL = 0; 1450 1451parameter DAT_DST_PEN = 0; 1452parameter DAT_DST_POL = 0; 1453 1454parameter T_RISE_MIN = 0; 1455parameter T_RISE_TYP = 0; 1456parameter T_RISE_MAX = 0; 1457 1458parameter T_FALL_MIN = 0; 1459parameter T_FALL_TYP = 0; 1460parameter T_FALL_MAX = 0; 1461 1462input EN; 1463input [SRC_WIDTH-1:0] SRC; 1464input [DST_WIDTH-1:0] DST, DAT; 1465 1466localparam ED = EDGE_EN ? (EDGE_POL ? 1 : 2) : 0; 1467localparam SD = SRC_DST_PEN ? (SRC_DST_POL ? 1 : 2) : 0; 1468localparam DD = DAT_DST_PEN ? (DAT_DST_POL ? 1 : 2) : 0; 1469 1470`ifdef SIMLIB_SPECIFY 1471specify 1472 // DD=0 1473 1474 if (EN && DD==0 && SD==0 && ED==0 && !FULL) ( SRC => (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1475 if (EN && DD==0 && SD==0 && ED==0 && FULL) ( SRC *> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1476 if (EN && DD==0 && SD==0 && ED==1 && !FULL) (posedge SRC => (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1477 if (EN && DD==0 && SD==0 && ED==1 && FULL) (posedge SRC *> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1478 if (EN && DD==0 && SD==0 && ED==2 && !FULL) (negedge SRC => (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1479 if (EN && DD==0 && SD==0 && ED==2 && FULL) (negedge SRC *> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1480 1481 if (EN && DD==0 && SD==1 && ED==0 && !FULL) ( SRC +=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1482 if (EN && DD==0 && SD==1 && ED==0 && FULL) ( SRC +*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1483 if (EN && DD==0 && SD==1 && ED==1 && !FULL) (posedge SRC +=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1484 if (EN && DD==0 && SD==1 && ED==1 && FULL) (posedge SRC +*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1485 if (EN && DD==0 && SD==1 && ED==2 && !FULL) (negedge SRC +=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1486 if (EN && DD==0 && SD==1 && ED==2 && FULL) (negedge SRC +*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1487 1488 if (EN && DD==0 && SD==2 && ED==0 && !FULL) ( SRC -=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1489 if (EN && DD==0 && SD==2 && ED==0 && FULL) ( SRC -*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1490 if (EN && DD==0 && SD==2 && ED==1 && !FULL) (posedge SRC -=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1491 if (EN && DD==0 && SD==2 && ED==1 && FULL) (posedge SRC -*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1492 if (EN && DD==0 && SD==2 && ED==2 && !FULL) (negedge SRC -=> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1493 if (EN && DD==0 && SD==2 && ED==2 && FULL) (negedge SRC -*> (DST : DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1494 1495 // DD=1 1496 1497 if (EN && DD==1 && SD==0 && ED==0 && !FULL) ( SRC => (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1498 if (EN && DD==1 && SD==0 && ED==0 && FULL) ( SRC *> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1499 if (EN && DD==1 && SD==0 && ED==1 && !FULL) (posedge SRC => (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1500 if (EN && DD==1 && SD==0 && ED==1 && FULL) (posedge SRC *> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1501 if (EN && DD==1 && SD==0 && ED==2 && !FULL) (negedge SRC => (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1502 if (EN && DD==1 && SD==0 && ED==2 && FULL) (negedge SRC *> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1503 1504 if (EN && DD==1 && SD==1 && ED==0 && !FULL) ( SRC +=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1505 if (EN && DD==1 && SD==1 && ED==0 && FULL) ( SRC +*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1506 if (EN && DD==1 && SD==1 && ED==1 && !FULL) (posedge SRC +=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1507 if (EN && DD==1 && SD==1 && ED==1 && FULL) (posedge SRC +*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1508 if (EN && DD==1 && SD==1 && ED==2 && !FULL) (negedge SRC +=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1509 if (EN && DD==1 && SD==1 && ED==2 && FULL) (negedge SRC +*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1510 1511 if (EN && DD==1 && SD==2 && ED==0 && !FULL) ( SRC -=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1512 if (EN && DD==1 && SD==2 && ED==0 && FULL) ( SRC -*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1513 if (EN && DD==1 && SD==2 && ED==1 && !FULL) (posedge SRC -=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1514 if (EN && DD==1 && SD==2 && ED==1 && FULL) (posedge SRC -*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1515 if (EN && DD==1 && SD==2 && ED==2 && !FULL) (negedge SRC -=> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1516 if (EN && DD==1 && SD==2 && ED==2 && FULL) (negedge SRC -*> (DST +: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1517 1518 // DD=2 1519 1520 if (EN && DD==2 && SD==0 && ED==0 && !FULL) ( SRC => (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1521 if (EN && DD==2 && SD==0 && ED==0 && FULL) ( SRC *> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1522 if (EN && DD==2 && SD==0 && ED==1 && !FULL) (posedge SRC => (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1523 if (EN && DD==2 && SD==0 && ED==1 && FULL) (posedge SRC *> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1524 if (EN && DD==2 && SD==0 && ED==2 && !FULL) (negedge SRC => (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1525 if (EN && DD==2 && SD==0 && ED==2 && FULL) (negedge SRC *> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1526 1527 if (EN && DD==2 && SD==1 && ED==0 && !FULL) ( SRC +=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1528 if (EN && DD==2 && SD==1 && ED==0 && FULL) ( SRC +*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1529 if (EN && DD==2 && SD==1 && ED==1 && !FULL) (posedge SRC +=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1530 if (EN && DD==2 && SD==1 && ED==1 && FULL) (posedge SRC +*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1531 if (EN && DD==2 && SD==1 && ED==2 && !FULL) (negedge SRC +=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1532 if (EN && DD==2 && SD==1 && ED==2 && FULL) (negedge SRC +*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1533 1534 if (EN && DD==2 && SD==2 && ED==0 && !FULL) ( SRC -=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1535 if (EN && DD==2 && SD==2 && ED==0 && FULL) ( SRC -*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1536 if (EN && DD==2 && SD==2 && ED==1 && !FULL) (posedge SRC -=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1537 if (EN && DD==2 && SD==2 && ED==1 && FULL) (posedge SRC -*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1538 if (EN && DD==2 && SD==2 && ED==2 && !FULL) (negedge SRC -=> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1539 if (EN && DD==2 && SD==2 && ED==2 && FULL) (negedge SRC -*> (DST -: DAT)) = (T_RISE_MIN:T_RISE_TYP:T_RISE_MAX, T_FALL_MIN:T_FALL_TYP:T_FALL_MAX); 1540endspecify 1541`endif 1542 1543endmodule 1544 1545// -------------------------------------------------------- 1546 1547module \$specrule (EN_SRC, EN_DST, SRC, DST); 1548 1549parameter TYPE = ""; 1550parameter T_LIMIT = 0; 1551parameter T_LIMIT2 = 0; 1552 1553parameter SRC_WIDTH = 1; 1554parameter DST_WIDTH = 1; 1555 1556parameter SRC_PEN = 0; 1557parameter SRC_POL = 0; 1558 1559parameter DST_PEN = 0; 1560parameter DST_POL = 0; 1561 1562input EN_SRC, EN_DST; 1563input [SRC_WIDTH-1:0] SRC; 1564input [DST_WIDTH-1:0] DST; 1565 1566`ifdef SIMLIB_SPECIFY 1567specify 1568 // TBD 1569endspecify 1570`endif 1571 1572endmodule 1573 1574// -------------------------------------------------------- 1575 1576module \$assert (A, EN); 1577 1578input A, EN; 1579 1580`ifndef SIMLIB_NOCHECKS 1581always @* begin 1582 if (A !== 1'b1 && EN === 1'b1) begin 1583 $display("Assertion %m failed!"); 1584 $stop; 1585 end 1586end 1587`endif 1588 1589endmodule 1590 1591// -------------------------------------------------------- 1592 1593module \$assume (A, EN); 1594 1595input A, EN; 1596 1597`ifndef SIMLIB_NOCHECKS 1598always @* begin 1599 if (A !== 1'b1 && EN === 1'b1) begin 1600 $display("Assumption %m failed!"); 1601 $stop; 1602 end 1603end 1604`endif 1605 1606endmodule 1607 1608// -------------------------------------------------------- 1609 1610module \$live (A, EN); 1611 1612input A, EN; 1613 1614endmodule 1615 1616// -------------------------------------------------------- 1617 1618module \$fair (A, EN); 1619 1620input A, EN; 1621 1622endmodule 1623 1624// -------------------------------------------------------- 1625 1626module \$cover (A, EN); 1627 1628input A, EN; 1629 1630endmodule 1631 1632// -------------------------------------------------------- 1633 1634module \$initstate (Y); 1635 1636output reg Y = 1; 1637reg [3:0] cnt = 1; 1638reg trig = 0; 1639 1640initial trig <= 1; 1641 1642always @(cnt, trig) begin 1643 Y <= |cnt; 1644 cnt <= cnt + |cnt; 1645end 1646 1647endmodule 1648 1649// -------------------------------------------------------- 1650 1651module \$anyconst (Y); 1652 1653parameter WIDTH = 0; 1654 1655output [WIDTH-1:0] Y; 1656 1657assign Y = 'bx; 1658 1659endmodule 1660 1661// -------------------------------------------------------- 1662 1663module \$anyseq (Y); 1664 1665parameter WIDTH = 0; 1666 1667output [WIDTH-1:0] Y; 1668 1669assign Y = 'bx; 1670 1671endmodule 1672 1673// -------------------------------------------------------- 1674 1675module \$allconst (Y); 1676 1677parameter WIDTH = 0; 1678 1679output [WIDTH-1:0] Y; 1680 1681assign Y = 'bx; 1682 1683endmodule 1684 1685// -------------------------------------------------------- 1686 1687module \$allseq (Y); 1688 1689parameter WIDTH = 0; 1690 1691output [WIDTH-1:0] Y; 1692 1693assign Y = 'bx; 1694 1695endmodule 1696 1697// -------------------------------------------------------- 1698 1699module \$equiv (A, B, Y); 1700 1701input A, B; 1702output Y; 1703 1704assign Y = (A !== 1'bx && A !== B) ? 1'bx : A; 1705 1706`ifndef SIMLIB_NOCHECKS 1707always @* begin 1708 if (A !== 1'bx && A !== B) begin 1709 $display("Equivalence failed!"); 1710 $stop; 1711 end 1712end 1713`endif 1714 1715endmodule 1716 1717// -------------------------------------------------------- 1718`ifndef SIMLIB_NOSR 1719 1720module \$sr (SET, CLR, Q); 1721 1722parameter WIDTH = 0; 1723parameter SET_POLARITY = 1'b1; 1724parameter CLR_POLARITY = 1'b1; 1725 1726input [WIDTH-1:0] SET, CLR; 1727output reg [WIDTH-1:0] Q; 1728 1729wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET; 1730wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR; 1731 1732genvar i; 1733generate 1734 for (i = 0; i < WIDTH; i = i+1) begin:bitslices 1735 always @* 1736 if (pos_clr[i]) 1737 Q[i] <= 0; 1738 else if (pos_set[i]) 1739 Q[i] <= 1; 1740 end 1741endgenerate 1742 1743endmodule 1744 1745`endif 1746// -------------------------------------------------------- 1747`ifdef SIMLIB_FF 1748 1749module \$ff (D, Q); 1750 1751parameter WIDTH = 0; 1752 1753input [WIDTH-1:0] D; 1754output reg [WIDTH-1:0] Q; 1755 1756always @($global_clk) begin 1757 Q <= D; 1758end 1759 1760endmodule 1761 1762`endif 1763// -------------------------------------------------------- 1764 1765module \$dff (CLK, D, Q); 1766 1767parameter WIDTH = 0; 1768parameter CLK_POLARITY = 1'b1; 1769 1770input CLK; 1771input [WIDTH-1:0] D; 1772output reg [WIDTH-1:0] Q; 1773wire pos_clk = CLK == CLK_POLARITY; 1774 1775always @(posedge pos_clk) begin 1776 Q <= D; 1777end 1778 1779endmodule 1780 1781// -------------------------------------------------------- 1782 1783module \$dffe (CLK, EN, D, Q); 1784 1785parameter WIDTH = 0; 1786parameter CLK_POLARITY = 1'b1; 1787parameter EN_POLARITY = 1'b1; 1788 1789input CLK, EN; 1790input [WIDTH-1:0] D; 1791output reg [WIDTH-1:0] Q; 1792wire pos_clk = CLK == CLK_POLARITY; 1793 1794always @(posedge pos_clk) begin 1795 if (EN == EN_POLARITY) Q <= D; 1796end 1797 1798endmodule 1799 1800// -------------------------------------------------------- 1801`ifndef SIMLIB_NOSR 1802 1803module \$dffsr (CLK, SET, CLR, D, Q); 1804 1805parameter WIDTH = 0; 1806parameter CLK_POLARITY = 1'b1; 1807parameter SET_POLARITY = 1'b1; 1808parameter CLR_POLARITY = 1'b1; 1809 1810input CLK; 1811input [WIDTH-1:0] SET, CLR, D; 1812output reg [WIDTH-1:0] Q; 1813 1814wire pos_clk = CLK == CLK_POLARITY; 1815wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET; 1816wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR; 1817 1818genvar i; 1819generate 1820 for (i = 0; i < WIDTH; i = i+1) begin:bitslices 1821 always @(posedge pos_set[i], posedge pos_clr[i], posedge pos_clk) 1822 if (pos_clr[i]) 1823 Q[i] <= 0; 1824 else if (pos_set[i]) 1825 Q[i] <= 1; 1826 else 1827 Q[i] <= D[i]; 1828 end 1829endgenerate 1830 1831endmodule 1832 1833// -------------------------------------------------------- 1834 1835module \$dffsre (CLK, SET, CLR, EN, D, Q); 1836 1837parameter WIDTH = 0; 1838parameter CLK_POLARITY = 1'b1; 1839parameter SET_POLARITY = 1'b1; 1840parameter CLR_POLARITY = 1'b1; 1841parameter EN_POLARITY = 1'b1; 1842 1843input CLK, EN; 1844input [WIDTH-1:0] SET, CLR, D; 1845output reg [WIDTH-1:0] Q; 1846 1847wire pos_clk = CLK == CLK_POLARITY; 1848wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET; 1849wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR; 1850 1851genvar i; 1852generate 1853 for (i = 0; i < WIDTH; i = i+1) begin:bitslices 1854 always @(posedge pos_set[i], posedge pos_clr[i], posedge pos_clk) 1855 if (pos_clr[i]) 1856 Q[i] <= 0; 1857 else if (pos_set[i]) 1858 Q[i] <= 1; 1859 else if (EN == EN_POLARITY) 1860 Q[i] <= D[i]; 1861 end 1862endgenerate 1863 1864endmodule 1865 1866`endif 1867// -------------------------------------------------------- 1868 1869module \$adff (CLK, ARST, D, Q); 1870 1871parameter WIDTH = 0; 1872parameter CLK_POLARITY = 1'b1; 1873parameter ARST_POLARITY = 1'b1; 1874parameter ARST_VALUE = 0; 1875 1876input CLK, ARST; 1877input [WIDTH-1:0] D; 1878output reg [WIDTH-1:0] Q; 1879wire pos_clk = CLK == CLK_POLARITY; 1880wire pos_arst = ARST == ARST_POLARITY; 1881 1882always @(posedge pos_clk, posedge pos_arst) begin 1883 if (pos_arst) 1884 Q <= ARST_VALUE; 1885 else 1886 Q <= D; 1887end 1888 1889endmodule 1890 1891// -------------------------------------------------------- 1892 1893module \$aldff (CLK, ALOAD, AD, D, Q); 1894 1895parameter WIDTH = 0; 1896parameter CLK_POLARITY = 1'b1; 1897parameter ALOAD_POLARITY = 1'b1; 1898 1899input CLK, ALOAD; 1900input [WIDTH-1:0] AD; 1901input [WIDTH-1:0] D; 1902output reg [WIDTH-1:0] Q; 1903wire pos_clk = CLK == CLK_POLARITY; 1904wire pos_aload = ALOAD == ALOAD_POLARITY; 1905 1906always @(posedge pos_clk, posedge pos_aload) begin 1907 if (pos_aload) 1908 Q <= AD; 1909 else 1910 Q <= D; 1911end 1912 1913endmodule 1914 1915// -------------------------------------------------------- 1916 1917module \$sdff (CLK, SRST, D, Q); 1918 1919parameter WIDTH = 0; 1920parameter CLK_POLARITY = 1'b1; 1921parameter SRST_POLARITY = 1'b1; 1922parameter SRST_VALUE = 0; 1923 1924input CLK, SRST; 1925input [WIDTH-1:0] D; 1926output reg [WIDTH-1:0] Q; 1927wire pos_clk = CLK == CLK_POLARITY; 1928wire pos_srst = SRST == SRST_POLARITY; 1929 1930always @(posedge pos_clk) begin 1931 if (pos_srst) 1932 Q <= SRST_VALUE; 1933 else 1934 Q <= D; 1935end 1936 1937endmodule 1938 1939// -------------------------------------------------------- 1940 1941module \$adffe (CLK, ARST, EN, D, Q); 1942 1943parameter WIDTH = 0; 1944parameter CLK_POLARITY = 1'b1; 1945parameter EN_POLARITY = 1'b1; 1946parameter ARST_POLARITY = 1'b1; 1947parameter ARST_VALUE = 0; 1948 1949input CLK, ARST, EN; 1950input [WIDTH-1:0] D; 1951output reg [WIDTH-1:0] Q; 1952wire pos_clk = CLK == CLK_POLARITY; 1953wire pos_arst = ARST == ARST_POLARITY; 1954 1955always @(posedge pos_clk, posedge pos_arst) begin 1956 if (pos_arst) 1957 Q <= ARST_VALUE; 1958 else if (EN == EN_POLARITY) 1959 Q <= D; 1960end 1961 1962endmodule 1963 1964// -------------------------------------------------------- 1965 1966module \$aldffe (CLK, ALOAD, AD, EN, D, Q); 1967 1968parameter WIDTH = 0; 1969parameter CLK_POLARITY = 1'b1; 1970parameter EN_POLARITY = 1'b1; 1971parameter ALOAD_POLARITY = 1'b1; 1972 1973input CLK, ALOAD, EN; 1974input [WIDTH-1:0] D; 1975input [WIDTH-1:0] AD; 1976output reg [WIDTH-1:0] Q; 1977wire pos_clk = CLK == CLK_POLARITY; 1978wire pos_aload = ALOAD == ALOAD_POLARITY; 1979 1980always @(posedge pos_clk, posedge pos_aload) begin 1981 if (pos_aload) 1982 Q <= AD; 1983 else if (EN == EN_POLARITY) 1984 Q <= D; 1985end 1986 1987endmodule 1988 1989// -------------------------------------------------------- 1990 1991module \$sdffe (CLK, SRST, EN, D, Q); 1992 1993parameter WIDTH = 0; 1994parameter CLK_POLARITY = 1'b1; 1995parameter EN_POLARITY = 1'b1; 1996parameter SRST_POLARITY = 1'b1; 1997parameter SRST_VALUE = 0; 1998 1999input CLK, SRST, EN; 2000input [WIDTH-1:0] D; 2001output reg [WIDTH-1:0] Q; 2002wire pos_clk = CLK == CLK_POLARITY; 2003wire pos_srst = SRST == SRST_POLARITY; 2004 2005always @(posedge pos_clk) begin 2006 if (pos_srst) 2007 Q <= SRST_VALUE; 2008 else if (EN == EN_POLARITY) 2009 Q <= D; 2010end 2011 2012endmodule 2013 2014// -------------------------------------------------------- 2015 2016module \$sdffce (CLK, SRST, EN, D, Q); 2017 2018parameter WIDTH = 0; 2019parameter CLK_POLARITY = 1'b1; 2020parameter EN_POLARITY = 1'b1; 2021parameter SRST_POLARITY = 1'b1; 2022parameter SRST_VALUE = 0; 2023 2024input CLK, SRST, EN; 2025input [WIDTH-1:0] D; 2026output reg [WIDTH-1:0] Q; 2027wire pos_clk = CLK == CLK_POLARITY; 2028wire pos_srst = SRST == SRST_POLARITY; 2029 2030always @(posedge pos_clk) begin 2031 if (EN == EN_POLARITY) begin 2032 if (pos_srst) 2033 Q <= SRST_VALUE; 2034 else 2035 Q <= D; 2036 end 2037end 2038 2039endmodule 2040 2041// -------------------------------------------------------- 2042 2043module \$dlatch (EN, D, Q); 2044 2045parameter WIDTH = 0; 2046parameter EN_POLARITY = 1'b1; 2047 2048input EN; 2049input [WIDTH-1:0] D; 2050output reg [WIDTH-1:0] Q; 2051 2052always @* begin 2053 if (EN == EN_POLARITY) 2054 Q = D; 2055end 2056 2057endmodule 2058 2059// -------------------------------------------------------- 2060 2061module \$adlatch (EN, ARST, D, Q); 2062 2063parameter WIDTH = 0; 2064parameter EN_POLARITY = 1'b1; 2065parameter ARST_POLARITY = 1'b1; 2066parameter ARST_VALUE = 0; 2067 2068input EN, ARST; 2069input [WIDTH-1:0] D; 2070output reg [WIDTH-1:0] Q; 2071 2072always @* begin 2073 if (ARST == ARST_POLARITY) 2074 Q = ARST_VALUE; 2075 else if (EN == EN_POLARITY) 2076 Q = D; 2077end 2078 2079endmodule 2080 2081// -------------------------------------------------------- 2082`ifndef SIMLIB_NOSR 2083 2084module \$dlatchsr (EN, SET, CLR, D, Q); 2085 2086parameter WIDTH = 0; 2087parameter EN_POLARITY = 1'b1; 2088parameter SET_POLARITY = 1'b1; 2089parameter CLR_POLARITY = 1'b1; 2090 2091input EN; 2092input [WIDTH-1:0] SET, CLR, D; 2093output reg [WIDTH-1:0] Q; 2094 2095wire pos_en = EN == EN_POLARITY; 2096wire [WIDTH-1:0] pos_set = SET_POLARITY ? SET : ~SET; 2097wire [WIDTH-1:0] pos_clr = CLR_POLARITY ? CLR : ~CLR; 2098 2099genvar i; 2100generate 2101 for (i = 0; i < WIDTH; i = i+1) begin:bitslices 2102 always @* 2103 if (pos_clr[i]) 2104 Q[i] = 0; 2105 else if (pos_set[i]) 2106 Q[i] = 1; 2107 else if (pos_en) 2108 Q[i] = D[i]; 2109 end 2110endgenerate 2111 2112endmodule 2113 2114`endif 2115// -------------------------------------------------------- 2116 2117module \$fsm (CLK, ARST, CTRL_IN, CTRL_OUT); 2118 2119parameter NAME = ""; 2120 2121parameter CLK_POLARITY = 1'b1; 2122parameter ARST_POLARITY = 1'b1; 2123 2124parameter CTRL_IN_WIDTH = 1; 2125parameter CTRL_OUT_WIDTH = 1; 2126 2127parameter STATE_BITS = 1; 2128parameter STATE_NUM = 1; 2129parameter STATE_NUM_LOG2 = 1; 2130parameter STATE_RST = 0; 2131parameter STATE_TABLE = 1'b0; 2132 2133parameter TRANS_NUM = 1; 2134parameter TRANS_TABLE = 4'b0x0x; 2135 2136input CLK, ARST; 2137input [CTRL_IN_WIDTH-1:0] CTRL_IN; 2138output reg [CTRL_OUT_WIDTH-1:0] CTRL_OUT; 2139 2140wire pos_clk = CLK == CLK_POLARITY; 2141wire pos_arst = ARST == ARST_POLARITY; 2142 2143reg [STATE_BITS-1:0] state; 2144reg [STATE_BITS-1:0] state_tmp; 2145reg [STATE_BITS-1:0] next_state; 2146 2147reg [STATE_BITS-1:0] tr_state_in; 2148reg [STATE_BITS-1:0] tr_state_out; 2149reg [CTRL_IN_WIDTH-1:0] tr_ctrl_in; 2150reg [CTRL_OUT_WIDTH-1:0] tr_ctrl_out; 2151 2152integer i; 2153 2154task tr_fetch; 2155 input [31:0] tr_num; 2156 reg [31:0] tr_pos; 2157 reg [STATE_NUM_LOG2-1:0] state_num; 2158 begin 2159 tr_pos = (2*STATE_NUM_LOG2+CTRL_IN_WIDTH+CTRL_OUT_WIDTH)*tr_num; 2160 tr_ctrl_out = TRANS_TABLE >> tr_pos; 2161 tr_pos = tr_pos + CTRL_OUT_WIDTH; 2162 state_num = TRANS_TABLE >> tr_pos; 2163 tr_state_out = STATE_TABLE >> (STATE_BITS*state_num); 2164 tr_pos = tr_pos + STATE_NUM_LOG2; 2165 tr_ctrl_in = TRANS_TABLE >> tr_pos; 2166 tr_pos = tr_pos + CTRL_IN_WIDTH; 2167 state_num = TRANS_TABLE >> tr_pos; 2168 tr_state_in = STATE_TABLE >> (STATE_BITS*state_num); 2169 tr_pos = tr_pos + STATE_NUM_LOG2; 2170 end 2171endtask 2172 2173always @(posedge pos_clk, posedge pos_arst) begin 2174 if (pos_arst) begin 2175 state_tmp = STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST]; 2176 for (i = 0; i < STATE_BITS; i = i+1) 2177 if (state_tmp[i] === 1'bz) 2178 state_tmp[i] = 0; 2179 state <= state_tmp; 2180 end else begin 2181 state_tmp = next_state; 2182 for (i = 0; i < STATE_BITS; i = i+1) 2183 if (state_tmp[i] === 1'bz) 2184 state_tmp[i] = 0; 2185 state <= state_tmp; 2186 end 2187end 2188 2189always @(state, CTRL_IN) begin 2190 next_state <= STATE_TABLE[STATE_BITS*(STATE_RST+1)-1:STATE_BITS*STATE_RST]; 2191 CTRL_OUT <= 'bx; 2192 // $display("---"); 2193 // $display("Q: %b %b", state, CTRL_IN); 2194 for (i = 0; i < TRANS_NUM; i = i+1) begin 2195 tr_fetch(i); 2196 // $display("T: %b %b -> %b %b [%d]", tr_state_in, tr_ctrl_in, tr_state_out, tr_ctrl_out, i); 2197 casez ({state, CTRL_IN}) 2198 {tr_state_in, tr_ctrl_in}: begin 2199 // $display("-> %b %b <- MATCH", state, CTRL_IN); 2200 {next_state, CTRL_OUT} <= {tr_state_out, tr_ctrl_out}; 2201 end 2202 endcase 2203 end 2204end 2205 2206endmodule 2207 2208// -------------------------------------------------------- 2209`ifndef SIMLIB_NOMEM 2210 2211module \$memrd (CLK, EN, ADDR, DATA); 2212 2213parameter MEMID = ""; 2214parameter ABITS = 8; 2215parameter WIDTH = 8; 2216 2217parameter CLK_ENABLE = 0; 2218parameter CLK_POLARITY = 0; 2219parameter TRANSPARENT = 0; 2220 2221input CLK, EN; 2222input [ABITS-1:0] ADDR; 2223output [WIDTH-1:0] DATA; 2224 2225initial begin 2226 if (MEMID != "") begin 2227 $display("ERROR: Found non-simulatable instance of $memrd!"); 2228 $finish; 2229 end 2230end 2231 2232endmodule 2233 2234module \$memrd_v2 (CLK, EN, ARST, SRST, ADDR, DATA); 2235 2236parameter MEMID = ""; 2237parameter ABITS = 8; 2238parameter WIDTH = 8; 2239 2240parameter CLK_ENABLE = 0; 2241parameter CLK_POLARITY = 0; 2242parameter TRANSPARENCY_MASK = 0; 2243parameter COLLISION_X_MASK = 0; 2244parameter ARST_VALUE = 0; 2245parameter SRST_VALUE = 0; 2246parameter INIT_VALUE = 0; 2247parameter CE_OVER_SRST = 0; 2248 2249input CLK, EN, ARST, SRST; 2250input [ABITS-1:0] ADDR; 2251output [WIDTH-1:0] DATA; 2252 2253initial begin 2254 if (MEMID != "") begin 2255 $display("ERROR: Found non-simulatable instance of $memrd_v2!"); 2256 $finish; 2257 end 2258end 2259 2260endmodule 2261 2262// -------------------------------------------------------- 2263 2264module \$memwr (CLK, EN, ADDR, DATA); 2265 2266parameter MEMID = ""; 2267parameter ABITS = 8; 2268parameter WIDTH = 8; 2269 2270parameter CLK_ENABLE = 0; 2271parameter CLK_POLARITY = 0; 2272parameter PRIORITY = 0; 2273 2274input CLK; 2275input [WIDTH-1:0] EN; 2276input [ABITS-1:0] ADDR; 2277input [WIDTH-1:0] DATA; 2278 2279initial begin 2280 if (MEMID != "") begin 2281 $display("ERROR: Found non-simulatable instance of $memwr!"); 2282 $finish; 2283 end 2284end 2285 2286endmodule 2287 2288module \$memwr_v2 (CLK, EN, ADDR, DATA); 2289 2290parameter MEMID = ""; 2291parameter ABITS = 8; 2292parameter WIDTH = 8; 2293 2294parameter CLK_ENABLE = 0; 2295parameter CLK_POLARITY = 0; 2296parameter PORTID = 0; 2297parameter PRIORITY_MASK = 0; 2298 2299input CLK; 2300input [WIDTH-1:0] EN; 2301input [ABITS-1:0] ADDR; 2302input [WIDTH-1:0] DATA; 2303 2304initial begin 2305 if (MEMID != "") begin 2306 $display("ERROR: Found non-simulatable instance of $memwr_v2!"); 2307 $finish; 2308 end 2309end 2310 2311endmodule 2312 2313// -------------------------------------------------------- 2314 2315module \$meminit (ADDR, DATA); 2316 2317parameter MEMID = ""; 2318parameter ABITS = 8; 2319parameter WIDTH = 8; 2320parameter WORDS = 1; 2321 2322parameter PRIORITY = 0; 2323 2324input [ABITS-1:0] ADDR; 2325input [WORDS*WIDTH-1:0] DATA; 2326 2327initial begin 2328 if (MEMID != "") begin 2329 $display("ERROR: Found non-simulatable instance of $meminit!"); 2330 $finish; 2331 end 2332end 2333 2334endmodule 2335 2336// -------------------------------------------------------- 2337 2338module \$meminit_v2 (ADDR, DATA, EN); 2339 2340parameter MEMID = ""; 2341parameter ABITS = 8; 2342parameter WIDTH = 8; 2343parameter WORDS = 1; 2344 2345parameter PRIORITY = 0; 2346 2347input [ABITS-1:0] ADDR; 2348input [WORDS*WIDTH-1:0] DATA; 2349input [WIDTH-1:0] EN; 2350 2351initial begin 2352 if (MEMID != "") begin 2353 $display("ERROR: Found non-simulatable instance of $meminit_v2!"); 2354 $finish; 2355 end 2356end 2357 2358endmodule 2359 2360// -------------------------------------------------------- 2361 2362module \$mem (RD_CLK, RD_EN, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA); 2363 2364parameter MEMID = ""; 2365parameter signed SIZE = 4; 2366parameter signed OFFSET = 0; 2367parameter signed ABITS = 2; 2368parameter signed WIDTH = 8; 2369parameter signed INIT = 1'bx; 2370 2371parameter signed RD_PORTS = 1; 2372parameter RD_CLK_ENABLE = 1'b1; 2373parameter RD_CLK_POLARITY = 1'b1; 2374parameter RD_TRANSPARENT = 1'b1; 2375 2376parameter signed WR_PORTS = 1; 2377parameter WR_CLK_ENABLE = 1'b1; 2378parameter WR_CLK_POLARITY = 1'b1; 2379 2380input [RD_PORTS-1:0] RD_CLK; 2381input [RD_PORTS-1:0] RD_EN; 2382input [RD_PORTS*ABITS-1:0] RD_ADDR; 2383output reg [RD_PORTS*WIDTH-1:0] RD_DATA; 2384 2385input [WR_PORTS-1:0] WR_CLK; 2386input [WR_PORTS*WIDTH-1:0] WR_EN; 2387input [WR_PORTS*ABITS-1:0] WR_ADDR; 2388input [WR_PORTS*WIDTH-1:0] WR_DATA; 2389 2390reg [WIDTH-1:0] memory [SIZE-1:0]; 2391 2392integer i, j; 2393reg [WR_PORTS-1:0] LAST_WR_CLK; 2394reg [RD_PORTS-1:0] LAST_RD_CLK; 2395 2396function port_active; 2397 input clk_enable; 2398 input clk_polarity; 2399 input last_clk; 2400 input this_clk; 2401 begin 2402 casez ({clk_enable, clk_polarity, last_clk, this_clk}) 2403 4'b0???: port_active = 1; 2404 4'b1101: port_active = 1; 2405 4'b1010: port_active = 1; 2406 default: port_active = 0; 2407 endcase 2408 end 2409endfunction 2410 2411initial begin 2412 for (i = 0; i < SIZE; i = i+1) 2413 memory[i] = INIT >>> (i*WIDTH); 2414end 2415 2416always @(RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA) begin 2417`ifdef SIMLIB_MEMDELAY 2418 #`SIMLIB_MEMDELAY; 2419`endif 2420 for (i = 0; i < RD_PORTS; i = i+1) begin 2421 if (!RD_TRANSPARENT[i] && RD_CLK_ENABLE[i] && RD_EN[i] && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) begin 2422 // $display("Read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]); 2423 RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; 2424 end 2425 end 2426 2427 for (i = 0; i < WR_PORTS; i = i+1) begin 2428 if (port_active(WR_CLK_ENABLE[i], WR_CLK_POLARITY[i], LAST_WR_CLK[i], WR_CLK[i])) 2429 for (j = 0; j < WIDTH; j = j+1) 2430 if (WR_EN[i*WIDTH+j]) begin 2431 // $display("Write to %s: addr=%b data=%b", MEMID, WR_ADDR[i*ABITS +: ABITS], WR_DATA[i*WIDTH+j]); 2432 memory[WR_ADDR[i*ABITS +: ABITS] - OFFSET][j] = WR_DATA[i*WIDTH+j]; 2433 end 2434 end 2435 2436 for (i = 0; i < RD_PORTS; i = i+1) begin 2437 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 2438 // $display("Transparent read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]); 2439 RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; 2440 end 2441 end 2442 2443 LAST_RD_CLK <= RD_CLK; 2444 LAST_WR_CLK <= WR_CLK; 2445end 2446 2447endmodule 2448 2449module \$mem_v2 (RD_CLK, RD_EN, RD_ARST, RD_SRST, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA); 2450 2451parameter MEMID = ""; 2452parameter signed SIZE = 4; 2453parameter signed OFFSET = 0; 2454parameter signed ABITS = 2; 2455parameter signed WIDTH = 8; 2456parameter signed INIT = 1'bx; 2457 2458parameter signed RD_PORTS = 1; 2459parameter RD_CLK_ENABLE = 1'b1; 2460parameter RD_CLK_POLARITY = 1'b1; 2461parameter RD_TRANSPARENCY_MASK = 1'b0; 2462parameter RD_COLLISION_X_MASK = 1'b0; 2463parameter RD_WIDE_CONTINUATION = 1'b0; 2464parameter RD_CE_OVER_SRST = 1'b0; 2465parameter RD_ARST_VALUE = 1'b0; 2466parameter RD_SRST_VALUE = 1'b0; 2467parameter RD_INIT_VALUE = 1'b0; 2468 2469parameter signed WR_PORTS = 1; 2470parameter WR_CLK_ENABLE = 1'b1; 2471parameter WR_CLK_POLARITY = 1'b1; 2472parameter WR_PRIORITY_MASK = 1'b0; 2473parameter WR_WIDE_CONTINUATION = 1'b0; 2474 2475input [RD_PORTS-1:0] RD_CLK; 2476input [RD_PORTS-1:0] RD_EN; 2477input [RD_PORTS-1:0] RD_ARST; 2478input [RD_PORTS-1:0] RD_SRST; 2479input [RD_PORTS*ABITS-1:0] RD_ADDR; 2480output reg [RD_PORTS*WIDTH-1:0] RD_DATA; 2481 2482input [WR_PORTS-1:0] WR_CLK; 2483input [WR_PORTS*WIDTH-1:0] WR_EN; 2484input [WR_PORTS*ABITS-1:0] WR_ADDR; 2485input [WR_PORTS*WIDTH-1:0] WR_DATA; 2486 2487reg [WIDTH-1:0] memory [SIZE-1:0]; 2488 2489integer i, j, k; 2490reg [WR_PORTS-1:0] LAST_WR_CLK; 2491reg [RD_PORTS-1:0] LAST_RD_CLK; 2492 2493function port_active; 2494 input clk_enable; 2495 input clk_polarity; 2496 input last_clk; 2497 input this_clk; 2498 begin 2499 casez ({clk_enable, clk_polarity, last_clk, this_clk}) 2500 4'b0???: port_active = 1; 2501 4'b1101: port_active = 1; 2502 4'b1010: port_active = 1; 2503 default: port_active = 0; 2504 endcase 2505 end 2506endfunction 2507 2508initial begin 2509 for (i = 0; i < SIZE; i = i+1) 2510 memory[i] = INIT >>> (i*WIDTH); 2511 RD_DATA = RD_INIT_VALUE; 2512end 2513 2514always @(RD_CLK, RD_ARST, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA) begin 2515`ifdef SIMLIB_MEMDELAY 2516 #`SIMLIB_MEMDELAY; 2517`endif 2518 for (i = 0; i < RD_PORTS; i = i+1) begin 2519 if (RD_CLK_ENABLE[i] && RD_EN[i] && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) begin 2520 // $display("Read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]); 2521 RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; 2522 2523 for (j = 0; j < WR_PORTS; j = j+1) begin 2524 if (RD_TRANSPARENCY_MASK[i*WR_PORTS + j] && port_active(WR_CLK_ENABLE[j], WR_CLK_POLARITY[j], LAST_WR_CLK[j], WR_CLK[j]) && RD_ADDR[i*ABITS +: ABITS] == WR_ADDR[j*ABITS +: ABITS]) 2525 for (k = 0; k < WIDTH; k = k+1) 2526 if (WR_EN[j*WIDTH+k]) 2527 RD_DATA[i*WIDTH+k] <= WR_DATA[j*WIDTH+k]; 2528 if (RD_COLLISION_X_MASK[i*WR_PORTS + j] && port_active(WR_CLK_ENABLE[j], WR_CLK_POLARITY[j], LAST_WR_CLK[j], WR_CLK[j]) && RD_ADDR[i*ABITS +: ABITS] == WR_ADDR[j*ABITS +: ABITS]) 2529 for (k = 0; k < WIDTH; k = k+1) 2530 if (WR_EN[j*WIDTH+k]) 2531 RD_DATA[i*WIDTH+k] <= 1'bx; 2532 end 2533 end 2534 end 2535 2536 for (i = 0; i < WR_PORTS; i = i+1) begin 2537 if (port_active(WR_CLK_ENABLE[i], WR_CLK_POLARITY[i], LAST_WR_CLK[i], WR_CLK[i])) 2538 for (j = 0; j < WIDTH; j = j+1) 2539 if (WR_EN[i*WIDTH+j]) begin 2540 // $display("Write to %s: addr=%b data=%b", MEMID, WR_ADDR[i*ABITS +: ABITS], WR_DATA[i*WIDTH+j]); 2541 memory[WR_ADDR[i*ABITS +: ABITS] - OFFSET][j] = WR_DATA[i*WIDTH+j]; 2542 end 2543 end 2544 2545 for (i = 0; i < RD_PORTS; i = i+1) begin 2546 if (!RD_CLK_ENABLE[i]) begin 2547 // $display("Combinatorial read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]); 2548 RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]; 2549 end 2550 end 2551 2552 for (i = 0; i < RD_PORTS; i = i+1) begin 2553 if (RD_SRST[i] && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i]) && (RD_EN[i] || !RD_CE_OVER_SRST[i])) 2554 RD_DATA[i*WIDTH +: WIDTH] <= RD_SRST_VALUE[i*WIDTH +: WIDTH]; 2555 if (RD_ARST[i]) 2556 RD_DATA[i*WIDTH +: WIDTH] <= RD_ARST_VALUE[i*WIDTH +: WIDTH]; 2557 end 2558 2559 LAST_RD_CLK <= RD_CLK; 2560 LAST_WR_CLK <= WR_CLK; 2561end 2562 2563endmodule 2564 2565`endif 2566 2567// -------------------------------------------------------- 2568