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