14 `define FLAG_Z 8'b10000000
 
  15 `define FLAG_N 8'b01000000
 
  16 `define FLAG_H 8'b00100000
 
  17 `define FLAG_C 8'b00010000
 
  19 `define STATE_FETCH                     2'h0
 
  20 `define STATE_DECODE                    2'h1
 
  21 `define STATE_EXECUTE           2'h2
 
  22 `define STATE_WRITEBACK         2'h3
 
  24 `define INSN_LD_reg_imm8        8'b00xxx110
 
  25 `define INSN_HALT                               8'b01110110
 
  26 `define INSN_LD_HL_reg          8'b01110xxx
 
  27 `define INSN_LD_reg_HL          8'b01xxx110
 
  28 `define INSN_LD_reg_reg         8'b01xxxxxx
 
  29 `define INSN_LD_reg_imm16       8'b00xx0001
 
  30 `define INSN_LD_SP_HL           8'b11111001
 
  31 `define INSN_PUSH_reg           8'b11xx0101
 
  32 `define INSN_POP_reg                    8'b11xx0001
 
  33 `define INSN_LDH_AC                     8'b111x0010     // Either LDH A,(C) or LDH (C),A
 
  34 `define INSN_LDx_AHL                    8'b001xx010     // LDD/LDI A,(HL) / (HL),A
 
  35 `define INSN_ALU8                               8'b10xxxxxx     // 10 xxx yyy
 
  36 `define INSN_NOP                                8'b00000000
 
  37 `define INSN_RST                                8'b11xxx111
 
  38 `define INSN_RET                                8'b110x1001     // 1 = RETI, 0 = RET
 
  39 `define INSN_CALL                               8'b11001101
 
  41 `define INSN_reg_A              3'b111
 
  42 `define INSN_reg_B              3'b000
 
  43 `define INSN_reg_C              3'b001
 
  44 `define INSN_reg_D              3'b010
 
  45 `define INSN_reg_E              3'b011
 
  46 `define INSN_reg_H              3'b100
 
  47 `define INSN_reg_L              3'b101
 
  48 `define INSN_reg_dHL    3'b110
 
  49 `define INSN_reg16_BC   2'b00
 
  50 `define INSN_reg16_DE   2'b01
 
  51 `define INSN_reg16_HL   2'b10
 
  52 `define INSN_reg16_SP   2'b11
 
  53 `define INSN_stack_AF   2'b11
 
  54 `define INSN_stack_BC   2'b00
 
  55 `define INSN_stack_DE   2'b01
 
  56 `define INSN_stack_HL   2'b10
 
  57 `define INSN_alu_ADD            3'b000
 
  58 `define INSN_alu_ADC            3'b001
 
  59 `define INSN_alu_SUB            3'b010
 
  60 `define INSN_alu_SBC            3'b011
 
  61 `define INSN_alu_AND            3'b100
 
  62 `define INSN_alu_XOR            3'b101
 
  63 `define INSN_alu_OR             3'b110
 
  64 `define INSN_alu_CP             3'b111          // Oh lawd, is dat some CP?
 
  68         output reg [15:0] busaddress,   /* BUS_* is latched on STATE_FETCH. */
 
  70         output reg buswr, output reg busrd);
 
  72         reg [1:0] state = 0;                                    /* State within this bus cycle (see STATE_*). */
 
  73         reg [2:0] cycle = 0;                                    /* Cycle for instructions. */
 
  75         reg [7:0] registers[11:0];
 
  77         reg [15:0] address;                             /* Address for the next bus operation. */
 
  79         reg [7:0] opcode;                               /* Opcode from the current machine cycle. */
 
  81         reg [7:0] rdata, wdata;         /* Read data from this bus cycle, or write data for the next. */
 
  82         reg rd = 1, wr = 0, newcycle = 1;
 
  84         reg [7:0] tmp, tmp2;                    /* Generic temporary regs. */
 
  87         assign busdata = buswr ? buswdata : 8'bzzzzzzzz;
 
 112         always @(posedge clk)
 
 116                                 busaddress <= {registers[`REG_PCH], registers[`REG_PCL]};
 
 120                                 busaddress <= address;
 
 126                         state <= `STATE_DECODE;
 
 135                                 if (rd) rdata <= busdata;
 
 142                         address <= 16'bxxxxxxxxxxxxxxxx;        // Make it obvious if something of type has happened.
 
 143                         wdata <= 8'bxxxxxxxx;
 
 144                         state <= `STATE_EXECUTE;
 
 146                 `STATE_EXECUTE: begin
 
 147 `define EXEC_INC_PC \
 
 148         {registers[`REG_PCH], registers[`REG_PCL]} <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
 
 149 `define EXEC_NEXTADDR_PCINC \
 
 150         address <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
 
 151 `define EXEC_NEWCYCLE \
 
 152         newcycle <= 1; rd <= 1; wr <= 0
 
 154                         `INSN_LD_reg_imm8: begin
 
 158                                                 `EXEC_NEXTADDR_PCINC;
 
 163                                                 if (opcode[5:3] == `INSN_reg_dHL) begin
 
 164                                                         address <= {registers[`REG_H], registers[`REG_L]};
 
 179                                 /* XXX Interrupts needed for HALT. */
 
 181                         `INSN_LD_HL_reg: begin
 
 185                                                 `INSN_reg_A:    wdata <= registers[`REG_A];
 
 186                                                 `INSN_reg_B:    wdata <= registers[`REG_B];
 
 187                                                 `INSN_reg_C:    wdata <= registers[`REG_C];
 
 188                                                 `INSN_reg_D:    wdata <= registers[`REG_D];
 
 189                                                 `INSN_reg_E:    wdata <= registers[`REG_E];
 
 190                                                 `INSN_reg_H:    wdata <= registers[`REG_H];
 
 191                                                 `INSN_reg_L:    wdata <= registers[`REG_L];
 
 193                                                 address <= {registers[`REG_H], registers[`REG_L]};
 
 202                         `INSN_LD_reg_HL: begin
 
 205                                                 address <= {registers[`REG_H], registers[`REG_L]};
 
 215                         `INSN_LD_reg_reg: begin
 
 219                                 `INSN_reg_A:    tmp <= registers[`REG_A];
 
 220                                 `INSN_reg_B:    tmp <= registers[`REG_B];
 
 221                                 `INSN_reg_C:    tmp <= registers[`REG_C];
 
 222                                 `INSN_reg_D:    tmp <= registers[`REG_D];
 
 223                                 `INSN_reg_E:    tmp <= registers[`REG_E];
 
 224                                 `INSN_reg_H:    tmp <= registers[`REG_H];
 
 225                                 `INSN_reg_L:    tmp <= registers[`REG_L];
 
 228                         `INSN_LD_reg_imm16: begin
 
 232                                                 `EXEC_NEXTADDR_PCINC;
 
 236                                                 `EXEC_NEXTADDR_PCINC;
 
 239                                 2: begin `EXEC_NEWCYCLE; end
 
 242                         `INSN_LD_SP_HL: begin
 
 245                                                 tmp <= registers[`REG_H];
 
 250                                                 tmp <= registers[`REG_L];
 
 254                         `INSN_PUSH_reg: begin   /* PUSH is 16 cycles! */
 
 258                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
 
 260                                                 `INSN_stack_AF: wdata <= registers[`REG_A];
 
 261                                                 `INSN_stack_BC: wdata <= registers[`REG_B];
 
 262                                                 `INSN_stack_DE: wdata <= registers[`REG_D];
 
 263                                                 `INSN_stack_HL: wdata <= registers[`REG_H];
 
 268                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
 
 270                                                 `INSN_stack_AF: wdata <= registers[`REG_F];
 
 271                                                 `INSN_stack_BC: wdata <= registers[`REG_C];
 
 272                                                 `INSN_stack_DE: wdata <= registers[`REG_E];
 
 273                                                 `INSN_stack_HL: wdata <= registers[`REG_L];
 
 276                                 2:      begin /* TWIDDLE OUR FUCKING THUMBS! */ end
 
 283                         `INSN_POP_reg: begin    /* POP is 12 cycles! */
 
 287                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]};
 
 291                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]};
 
 302                                                 address <= {8'hFF,registers[`REG_C]};
 
 303                                                 if (opcode[4]) begin    // LD A,(C)
 
 307                                                         wdata <= registers[`REG_A];
 
 319                                                 address <= {registers[`REG_H],registers[`REG_L]};
 
 320                                                 if (opcode[3]) begin    // LDx A, (HL)
 
 324                                                         wdata <= registers[`REG_A];
 
 334                                 if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) begin
 
 335                                         // fffffffff fuck your shit, read from (HL) :(
 
 337                                         address <= {registers[`REG_H], registers[`REG_L]};
 
 342                                         `INSN_reg_A:    tmp <= registers[`REG_A];
 
 343                                         `INSN_reg_B:    tmp <= registers[`REG_B];
 
 344                                         `INSN_reg_C:    tmp <= registers[`REG_C];
 
 345                                         `INSN_reg_D:    tmp <= registers[`REG_D];
 
 346                                         `INSN_reg_E:    tmp <= registers[`REG_E];
 
 347                                         `INSN_reg_H:    tmp <= registers[`REG_H];
 
 348                                         `INSN_reg_L:    tmp <= registers[`REG_L];
 
 349                                         `INSN_reg_dHL:  tmp <= rdata;
 
 360                                                 `EXEC_INC_PC;           // This goes FIRST in RST
 
 364                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
 
 365                                                 wdata <= registers[`REG_PCH];
 
 369                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]}-2;
 
 370                                                 wdata <= registers[`REG_PCL];
 
 374                                                 {registers[`REG_PCH],registers[`REG_PCL]} <=
 
 375                                                         {10'b0,opcode[5:3],3'b0};
 
 383                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]};
 
 387                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]} + 1;
 
 389                                 2:      begin /* twiddle thumbs */ end
 
 392                                                 // do NOT increment PC!
 
 400                                                 `EXEC_NEXTADDR_PCINC;
 
 405                                                 `EXEC_NEXTADDR_PCINC;
 
 412                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]} - 1;
 
 413                                                 wdata <= registers[`REG_PCH];
 
 417                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]} - 2;
 
 418                                                 wdata <= registers[`REG_PCL];
 
 422                                                 `EXEC_NEWCYCLE; /* do NOT increment the PC */
 
 429                         state <= `STATE_WRITEBACK;
 
 431                 `STATE_WRITEBACK: begin
 
 436                                 1:      case (opcode[5:3])
 
 437                                         `INSN_reg_A:    begin registers[`REG_A] <= rdata; end
 
 438                                         `INSN_reg_B:    begin registers[`REG_B] <= rdata; end
 
 439                                         `INSN_reg_C:    begin registers[`REG_C] <= rdata; end
 
 440                                         `INSN_reg_D:    begin registers[`REG_D] <= rdata; end
 
 441                                         `INSN_reg_E:    begin registers[`REG_E] <= rdata; end
 
 442                                         `INSN_reg_H:    begin registers[`REG_H] <= rdata; end
 
 443                                         `INSN_reg_L:    begin registers[`REG_L] <= rdata; end
 
 444                                         `INSN_reg_dHL:  begin /* Go off to cycle 2 */ end
 
 449                                 /* Nothing needs happen here. */
 
 450                                 /* XXX Interrupts needed for HALT. */
 
 452                         `INSN_LD_HL_reg: begin
 
 453                                 /* Nothing of interest here */
 
 455                         `INSN_LD_reg_HL: begin
 
 460                                                 `INSN_reg_A:    registers[`REG_A] <= tmp;
 
 461                                                 `INSN_reg_B:    registers[`REG_B] <= tmp;
 
 462                                                 `INSN_reg_C:    registers[`REG_C] <= tmp;
 
 463                                                 `INSN_reg_D:    registers[`REG_D] <= tmp;
 
 464                                                 `INSN_reg_E:    registers[`REG_E] <= tmp;
 
 465                                                 `INSN_reg_H:    registers[`REG_H] <= tmp;
 
 466                                                 `INSN_reg_L:    registers[`REG_L] <= tmp;
 
 471                         `INSN_LD_reg_reg: begin
 
 473                                 `INSN_reg_A:    registers[`REG_A] <= tmp;
 
 474                                 `INSN_reg_B:    registers[`REG_B] <= tmp;
 
 475                                 `INSN_reg_C:    registers[`REG_C] <= tmp;
 
 476                                 `INSN_reg_D:    registers[`REG_D] <= tmp;
 
 477                                 `INSN_reg_E:    registers[`REG_E] <= tmp;
 
 478                                 `INSN_reg_H:    registers[`REG_H] <= tmp;
 
 479                                 `INSN_reg_L:    registers[`REG_L] <= tmp;
 
 482                         `INSN_LD_reg_imm16: begin
 
 487                                                 `INSN_reg16_BC: registers[`REG_C] <= rdata;
 
 488                                                 `INSN_reg16_DE: registers[`REG_E] <= rdata;
 
 489                                                 `INSN_reg16_HL: registers[`REG_L] <= rdata;
 
 490                                                 `INSN_reg16_SP: registers[`REG_SPL] <= rdata;
 
 495                                                 `INSN_reg16_BC: registers[`REG_B] <= rdata;
 
 496                                                 `INSN_reg16_DE: registers[`REG_D] <= rdata;
 
 497                                                 `INSN_reg16_HL: registers[`REG_H] <= rdata;
 
 498                                                 `INSN_reg16_SP: registers[`REG_SPH] <= rdata;
 
 503                         `INSN_LD_SP_HL: begin
 
 505                                 0:      registers[`REG_SPH] <= tmp;
 
 506                                 1: registers[`REG_SPL] <= tmp;
 
 509                         `INSN_PUSH_reg: begin   /* PUSH is 16 cycles! */
 
 511                                 0:      {registers[`REG_SPH],registers[`REG_SPL]} <=
 
 512                                                 {registers[`REG_SPH],registers[`REG_SPL]} - 1;
 
 513                                 1:      {registers[`REG_SPH],registers[`REG_SPL]} <=
 
 514                                                 {registers[`REG_SPH],registers[`REG_SPL]} - 1;
 
 515                                 2:      begin /* type F */ end
 
 516                                 3:      begin /* type F */ end
 
 519                         `INSN_POP_reg: begin    /* POP is 12 cycles! */
 
 521                                 0:      {registers[`REG_SPH],registers[`REG_SPL]} <=
 
 522                                                 {registers[`REG_SPH],registers[`REG_SPL]} + 1;
 
 525                                                 `INSN_stack_AF: registers[`REG_F] <= rdata;
 
 526                                                 `INSN_stack_BC: registers[`REG_C] <= rdata;
 
 527                                                 `INSN_stack_DE: registers[`REG_E] <= rdata;
 
 528                                                 `INSN_stack_HL: registers[`REG_L] <= rdata;
 
 530                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
 
 531                                                         {registers[`REG_SPH],registers[`REG_SPL]} + 1;
 
 535                                                 `INSN_stack_AF: registers[`REG_A] <= rdata;
 
 536                                                 `INSN_stack_BC: registers[`REG_B] <= rdata;
 
 537                                                 `INSN_stack_DE: registers[`REG_D] <= rdata;
 
 538                                                 `INSN_stack_HL: registers[`REG_H] <= rdata;
 
 545                                 0:      begin /* Type F */ end
 
 547                                                 registers[`REG_A] <= rdata;
 
 552                                 0:      begin /* Type F */ end
 
 555                                                         registers[`REG_A] <= rdata;
 
 556                                                 {registers[`REG_H],registers[`REG_L]} <=
 
 557                                                         opcode[4] ? // if set, LDD, else LDI
 
 558                                                         ({registers[`REG_H],registers[`REG_L]} - 1) :
 
 559                                                         ({registers[`REG_H],registers[`REG_L]} + 1);
 
 564                                 if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) begin
 
 565                                         /* Sit on our asses. */
 
 566                                 end else begin          /* Actually do the computation! */
 
 570                                                         registers[`REG_A] + tmp;
 
 572                                                         { /* Z */ ((registers[`REG_A] + tmp) == 0) ? 1'b1 : 1'b0,
 
 574                                                           /* H */ (({1'b0,registers[`REG_A][3:0]} + {1'b0,tmp[3:0]}) >> 4 == 1) ? 1'b1 : 1'b0,
 
 575                                                           /* C */ (({1'b0,registers[`REG_A]} + {1'b0,tmp}) >> 8 == 1) ? 1'b1 : 1'b0,
 
 576                                                           registers[`REG_F][3:0]
 
 581                                                         registers[`REG_A] + tmp + {7'b0,registers[`REG_F][4]};
 
 583                                                         { /* Z */ ((registers[`REG_A] + tmp + {7'b0,registers[`REG_F][4]}) == 0) ? 1'b1 : 1'b0,
 
 585                                                           /* H */ (({1'b0,registers[`REG_A][3:0]} + {1'b0,tmp[3:0]} + {4'b0,registers[`REG_F][4]}) >> 4 == 1) ? 1'b1 : 1'b0,
 
 586                                                           /* C */ (({1'b0,registers[`REG_A]} + {1'b0,tmp} + {8'b0,registers[`REG_F][4]}) >> 8 == 1) ? 1'b1 : 1'b0,
 
 587                                                           registers[`REG_F][3:0]
 
 592                                                         registers[`REG_A] & tmp;
 
 594                                                         { /* Z */ ((registers[`REG_A] & tmp) == 0) ? 1'b1 : 1'b0,
 
 596                                                           registers[`REG_F][3:0]
 
 601                                                         registers[`REG_A] | tmp;
 
 603                                                         { /* Z */ ((registers[`REG_A] | tmp) == 0) ? 1'b1 : 1'b0,
 
 605                                                           registers[`REG_F][3:0]
 
 610                                                         registers[`REG_A] ^ tmp;
 
 612                                                         { /* Z */ ((registers[`REG_A] ^ tmp) == 0) ? 1'b1 : 1'b0,
 
 614                                                           registers[`REG_F][3:0]
 
 622                         `INSN_NOP: begin /* NOP! */ end
 
 625                                 0:      begin /* type F */ end
 
 626                                 1:      begin /* type F */ end
 
 627                                 2:      begin /* type F */ end
 
 628                                 3:      {registers[`REG_SPH],registers[`REG_SPL]} <=
 
 629                                                 {registers[`REG_SPH],registers[`REG_SPL]}-2;
 
 634                                 0:      begin /* type F */ end
 
 635                                 1:      registers[`REG_PCL] <= rdata;
 
 636                                 2:      registers[`REG_PCH] <= rdata;
 
 638                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
 
 639                                                         {registers[`REG_SPH],registers[`REG_SPL]} + 2;
 
 640                                                 if (opcode[4])  /* RETI */
 
 647                                 0:      begin /* type F */ end
 
 648                                 1:      tmp <= rdata;   // tmp contains newpcl
 
 649                                 2:      tmp2 <= rdata;  // tmp2 contains newpch
 
 650                                 3:      begin /* type F */ end
 
 651                                 4:      registers[`REG_PCH] <= tmp2;
 
 653                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
 
 654                                                         {registers[`REG_SPH],registers[`REG_SPL]} - 2;
 
 655                                                 registers[`REG_PCL] <= tmp;
 
 662                         state <= `STATE_FETCH;
 
 669         input [15:0] address,
 
 674         reg [7:0] rom [2047:0];
 
 675         initial $readmemh("rom.hex", rom);
 
 677         wire decode = address[15:13] == 0;
 
 678         wire [7:0] odata = rom[address[11:0]];
 
 679         assign data = (rd && decode) ? odata : 8'bzzzzzzzz;
 
 680         //assign data = rd ? odata : 8'bzzzzzzzz;
 
 684         input [15:0] address,
 
 689         reg [7:0] ram [8191:0];
 
 691         wire decode = (address >= 16'hC000) && (address < 16'hFE00);
 
 694         assign data = (rd && decode) ? odata : 8'bzzzzzzzz;
 
 696         always @(negedge clk)
 
 699                         odata <= ram[address[12:0]];
 
 700                 else if (decode && wr)
 
 701                         ram[address[12:0]] <= data;
 
 706 //      input [15:0] address,
 
 710 //      input [7:0] switches,
 
 711 //      output reg [7:0] ledout);
 
 713 //      wire decode = address == 16'hFF51;
 
 715 //      wire idata = data;
 
 716 //      assign data = (rd && decode) ? odata : 8'bzzzzzzzz;
 
 718 //      always @(negedge clk)
 
 721 //                      odata <= switches;
 
 722 //              else if (decode && wr)
 
 729         output wire [7:0] leds,
 
 731         output wire [3:0] digits,
 
 732         output wire [7:0] seven);
 
 735         //IBUFG ibuf (.O(clk), .I(iclk));
 
 737         CPUDCM dcm (.CLKIN_IN(xtal), .CLKFX_OUT(clk));
 
 743         assign leds = iclk?{rd,wr,addr[5:0]}:data[7:0];
 
 776 //      wire [7:0] switches;
 
 778         always #10 clk <= ~clk;
 
 815 //              .switches(switches),