
// Benchmark source:
// https://github.com/daveshah1/up5k-demos/tree/master/nes

// ===================================================================

module scan_double(input clk,
            input [14:0] inputpixel,
            input reset_frame,
            input reset_line,
            input [9:0] read_x,
            output reg [14:0] outpixel);
reg [1:0] frac;
reg [14:0] linebuf[0:255];
reg [8:0] write_x;

always @(posedge clk)
begin
  if(reset_line)
  begin
    frac <= 2'b00;
    write_x <= 9'd0;
  end else begin
    frac <= frac + 1;
    if (frac == 2)
      if (write_x < 256)
        write_x <= write_x + 1;
  end
end

wire write_en = ((frac == 2) && (write_x < 256)) ? 1'b1 : 1'b0;

always @(posedge clk)
begin
  outpixel <= linebuf[read_x[8:1]];
  if(write_en)
    linebuf[write_x[7:0]] <= inputpixel;
end



endmodule/**
 * PLL configuration
 *
 * This Verilog module was generated automatically
 * using the icepll tool from the IceStorm project.
 * Use at your own risk.
 *
 * Given input frequency:        16.000 MHz
 * Requested output frequency:   21.477 MHz
 * Achieved output frequency:    21.500 MHz
 */

module pll(
	input  clock_in,
	output clock_out,
	output locked
	);

assign clock_out = clock_in;
assign locked = 1'b1;

endmodule
/*
This memory device contains both system memory
and cartridge data.
*/

module main_mem(
  input clock, reset,
  
  input reload,
  input [3:0] index,
  
  output load_done,
  output [31:0] flags_out,
  //NES interface
  input [21:0] mem_addr,
  input mem_rd_cpu, mem_rd_ppu,
  input mem_wr,
  output reg [7:0] mem_q_cpu, mem_q_ppu,
  input [7:0] mem_d,
  
  //Flash load interface
  output flash_csn,
  output flash_sck,
  output flash_mosi,
  input flash_miso);
  
// Compress the 4MB logical address space to our limited available space
// In the future a more sophisticated memory system will keep games in
// SQI flash to expand the space available

// Also may consider changing this based on mapper to make the most
// of limited memory

wire prgrom_en, chrrom_en, vram_en, cpuram_en, cartram_en;

// Mapping
// 0... : PRG       : lower 64kB SPRAM
// 10.. : CHR       : upper 64kB SPRAM
// 1100 : CHR-VRAM  : dedicated 2kB RAM
// 1110 : CPU-RAM   : dedicated 2kB RAM
// 1111 : CART-RAM  : dedicated 2kB RAM

assign prgrom_en    = !mem_addr[21];
assign chrrom_en    = mem_addr[21] & !mem_addr[20];
assign vram_en      = mem_addr[21] & mem_addr[20] & !mem_addr[19] & !mem_addr[18];
assign cpuram_en    = mem_addr[21] & mem_addr[20] & mem_addr[19] & !mem_addr[18];
assign cartram_en   = mem_addr[21] & mem_addr[20] & mem_addr[19] & mem_addr[18];

wire [20:0] segment_addr = prgrom_en ? mem_addr[20:0] : (chrrom_en ? {1'b0, mem_addr[19:0]} : {3'b0, mem_addr[17:0]});

wire [7:0] cpuram_read_data, vram_read_data, cart_read_data;
wire rden = mem_rd_cpu | mem_rd_ppu;

always@(posedge clock or posedge reset)
begin
  if (reset == 1'b1) begin
    mem_q_cpu <= 0;
    mem_q_ppu <= 0;
  end else begin
    if (mem_rd_cpu)
      mem_q_cpu <= cpuram_en ? cpuram_read_data : (vram_en ? vram_read_data : cart_read_data);
    if (mem_rd_ppu)
      mem_q_ppu <= cpuram_en ? cpuram_read_data : (vram_en ? vram_read_data : cart_read_data);
  end;
end

cart_mem cart_i (
  .clock(clock),
  .reset(reset),
  .reload(reload),
  .index(index),
  .cart_ready(load_done),
  .flags_out(flags_out),
  .address(segment_addr),
  .prg_sel(prgrom_en),
  .chr_sel(chrrom_en),
  .ram_sel(cartram_en),
  .rden(rden),
  .wren(mem_wr),
  .write_data(mem_d),
  .read_data(cart_read_data),
  
  //Flash load interface
  .flash_csn(flash_csn),
  .flash_sck(flash_sck),
  .flash_mosi(flash_mosi),
  .flash_miso(flash_miso)
);

generic_ram #(
  .WIDTH(8),
  .WORDS(2048)
) cpuram_i (
  .clock(clock),
  .reset(reset),
  .address(segment_addr[10:0]), 
  .wren(mem_wr&cpuram_en), 
  .write_data(mem_d), 
  .read_data(cpuram_read_data)
);

generic_ram #(
  .WIDTH(8),
  .WORDS(2048)
) vram_i (
  .clock(clock),
  .reset(reset),
  .address(segment_addr[10:0]), 
  .wren(mem_wr&vram_en), 
  .write_data(mem_d), 
  .read_data(vram_read_data)
);

endmodule// Copyright (c) 2012-2013 Ludvig Strigeus
// This program is GPL Licensed. See COPYING for the full license.

// Module handles updating the loopy scroll register
module LoopyGen (
					 input clk, input ce,
                input is_rendering,
                input [2:0] ain,   // input address from CPU
                input [7:0] din,   // data input
                input read,        // read
                input write,       // write
                input is_pre_render, // Is this the pre-render scanline
                input [8:0] cycle,
                output [14:0] loopy,
                output [2:0] fine_x_scroll);  // Current loopy value
  // Controls how much to increment on each write
  reg ppu_incr; // 0 = 1, 1 = 32
  // Current VRAM address
  reg [14:0] loopy_v;
  // Temporary VRAM address
  reg [14:0] loopy_t;
  // Fine X scroll (3 bits)
  reg [2:0] loopy_x;
  // Latch
  reg ppu_address_latch;
  initial begin
    ppu_incr = 0;
    loopy_v = 0;
    loopy_t = 0;
    loopy_x = 0;
    ppu_address_latch = 0;  
  end
  // Handle updating loopy_t and loopy_v
  always @(posedge clk) if (ce) begin
    if (is_rendering) begin
      // Increment course X scroll right after attribute table byte was fetched.
      if (cycle[2:0] == 3 && (cycle < 256 || cycle >= 320 && cycle < 336)) begin
        loopy_v[4:0] <= loopy_v[4:0] + 1;
        loopy_v[10] <= loopy_v[10] ^ (loopy_v[4:0] == 31);
      end

      // Vertical Increment  
      if (cycle == 251) begin
        loopy_v[14:12] <= loopy_v[14:12] + 1;
        if (loopy_v[14:12] == 7) begin
          if (loopy_v[9:5] == 29) begin
            loopy_v[9:5] <= 0;
            loopy_v[11] <= !loopy_v[11];
          end else begin
            loopy_v[9:5] <= loopy_v[9:5] + 1;
          end
        end
      end
      
      // Horizontal Reset at cycle 257
      if (cycle == 256)
        {loopy_v[10], loopy_v[4:0]} <= {loopy_t[10], loopy_t[4:0]};
  
      // On cycle 256 of each scanline, copy horizontal bits from loopy_t into loopy_v
      // On cycle 304 of the pre-render scanline, copy loopy_t into loopy_v
      if (cycle == 304 && is_pre_render) begin
        loopy_v <= loopy_t;
      end
    end
    if (write && ain == 0) begin
      loopy_t[10] <= din[0];
      loopy_t[11] <= din[1];
      ppu_incr <= din[2];
    end else if (write && ain == 5) begin
      if (!ppu_address_latch) begin
        loopy_t[4:0] <= din[7:3];
        loopy_x <= din[2:0];
      end else begin
        loopy_t[9:5] <= din[7:3];
        loopy_t[14:12] <= din[2:0];
      end
      ppu_address_latch <= !ppu_address_latch;
    end else if (write && ain == 6) begin
      if (!ppu_address_latch) begin
        loopy_t[13:8] <= din[5:0];
        loopy_t[14] <= 0;
      end else begin
        loopy_t[7:0] <= din;
        loopy_v <= {loopy_t[14:8], din};
      end
      ppu_address_latch <= !ppu_address_latch;
    end else if (read && ain == 2) begin
      ppu_address_latch <= 0; //Reset PPU address latch
    end else if ((read || write) && ain == 7 && !is_rendering) begin
      // Increment address every time we accessed a reg
      loopy_v <= loopy_v + (ppu_incr ? 32 : 1);
    end
  end
  assign loopy = loopy_v;
  assign fine_x_scroll = loopy_x;
endmodule
  
  
// Generates the current scanline / cycle counters
module ClockGen(input clk, input ce, input reset,
                input is_rendering,
                output reg [8:0] scanline,
                output reg [8:0] cycle,
                output reg is_in_vblank,
                output end_of_line,
                output at_last_cycle_group,
                output exiting_vblank,
                output entering_vblank,
                output reg is_pre_render);
  reg second_frame;
  
  // Scanline 0..239 = picture scan lines
  // Scanline 240 = dummy scan line
  // Scanline 241..260 = VBLANK
  // Scanline -1 = Pre render scanline (Fetches objects for next line)
  assign at_last_cycle_group = (cycle[8:3] == 42);
  // Every second pre-render frame is only 340 cycles instead of 341.
  assign end_of_line = at_last_cycle_group && cycle[3:0] == (is_pre_render && second_frame && is_rendering ? 3 : 4);
  // Set the clock right before vblank begins
  assign entering_vblank = end_of_line && scanline == 240;
  // Set the clock right before vblank ends
  assign exiting_vblank = end_of_line && scanline == 260;
  // New value for is_in_vblank flag
  wire new_is_in_vblank = entering_vblank ? 1'b1 : exiting_vblank ? 1'b0 : is_in_vblank;
  // Set if the current line is line 0..239
  always @(posedge clk) if (reset) begin
    cycle <= 0;
    is_in_vblank <= 1;
  end else if (ce) begin
    cycle <= end_of_line ? 0 : cycle + 1;
    is_in_vblank <= new_is_in_vblank;
  end
//  always @(posedge clk) if (ce) begin
//    $write("%x %x %x %x %x\n", new_is_in_vblank, entering_vblank, exiting_vblank, is_in_vblank, entering_vblank ? 1'b1 : exiting_vblank ? 1'b0 : is_in_vblank);
    
//  end
  always @(posedge clk) if (reset) begin
    scanline <= 0;
    is_pre_render <= 0;
    second_frame <= 0;
  end else if (ce && end_of_line) begin
    // Once the scanline counter reaches end of 260, it gets reset to -1.
    scanline <= exiting_vblank ? 9'b111111111 : scanline + 1;
    // The pre render flag is set while we're on scanline -1.
    is_pre_render <= exiting_vblank;
    
    if (exiting_vblank)
      second_frame <= !second_frame;
  end
  
endmodule // ClockGen

// 8 of these exist, they are used to output sprites.
module Sprite(input clk, input ce,
              input enable,
              input [3:0] load, 
              input [26:0] load_in,
              output [26:0] load_out,
              output [4:0] bits); // Low 4 bits = pixel, high bit = prio
  reg [1:0] upper_color; // Upper 2 bits of color
  reg [7:0] x_coord;     // X coordinate where we want things
  reg [7:0] pix1, pix2;  // Shift registers, output when x_coord == 0
  reg aprio;             // Current prio
  wire active = (x_coord == 0);
  always @(posedge clk) if (ce) begin
    if (enable) begin
      if (!active) begin
        // Decrease until x_coord is zero.
        x_coord <= x_coord - 8'h01;
      end else begin
        pix1 <= pix1 >> 1;
        pix2 <= pix2 >> 1;
      end
    end
    if (load[3]) pix1 <= load_in[26:19];
    if (load[2]) pix2 <= load_in[18:11];
    if (load[1]) x_coord <= load_in[10:3];
    if (load[0]) {upper_color, aprio} <= load_in[2:0];
  end
  assign bits = {aprio, upper_color, active && pix2[0], active && pix1[0]};
  assign load_out = {pix1, pix2, x_coord, upper_color, aprio};
endmodule  // SpriteGen
					
// This contains all 8 sprites. Will return the pixel value of the highest prioritized sprite.
// When load is set, and clocked, load_in is loaded into sprite 7 and all others are shifted down.
// Sprite 0 has highest prio.
// 226 LUTs, 68 Slices
module SpriteSet(input clk, input ce,   // Input clock
                 input enable,          // Enable pixel generation
                 input [3:0] load,      // Which parts of the state to load/shift.
                 input [26:0] load_in,  // State to load with 
                 output [4:0] bits,     // Output bits
                 output is_sprite0);    // Set to true if sprite #0 was output

  wire [26:0] load_out7, load_out6, load_out5, load_out4, load_out3, load_out2, load_out1, load_out0; 
  wire [4:0] bits7, bits6, bits5, bits4, bits3, bits2, bits1, bits0;
  Sprite sprite7(clk, ce, enable, load, load_in,   load_out7, bits7);
  Sprite sprite6(clk, ce, enable, load, load_out7, load_out6, bits6);
  Sprite sprite5(clk, ce, enable, load, load_out6, load_out5, bits5);
  Sprite sprite4(clk, ce, enable, load, load_out5, load_out4, bits4);
  Sprite sprite3(clk, ce, enable, load, load_out4, load_out3, bits3);
  Sprite sprite2(clk, ce, enable, load, load_out3, load_out2, bits2);
  Sprite sprite1(clk, ce, enable, load, load_out2, load_out1, bits1);
  Sprite sprite0(clk, ce, enable, load, load_out1, load_out0, bits0);          
  // Determine which sprite is visible on this pixel.
  assign bits = bits0[1:0] != 0 ? bits0 : 
                bits1[1:0] != 0 ? bits1 : 
                bits2[1:0] != 0 ? bits2 : 
                bits3[1:0] != 0 ? bits3 : 
                bits4[1:0] != 0 ? bits4 : 
                bits5[1:0] != 0 ? bits5 : 
                bits6[1:0] != 0 ? bits6 : 
                                  bits7;
  assign is_sprite0 = bits0[1:0] != 0;                             
endmodule  // SpriteSet

module SpriteRAM(input clk, input ce,
                 input reset_line,          // OAM evaluator needs to be reset before processing is started.
                 input sprites_enabled,     // Set to 1 if evaluations are enabled
                 input exiting_vblank,      // Set to 1 when exiting vblank so spr_overflow can be reset
                 input obj_size,            // Set to 1 if objects are 16 pixels.
                 input [8:0] scanline,      // Current scan line (compared against Y)
                 input [8:0] cycle,         // Current cycle.
                 output reg [7:0] oam_bus,  // Current value on the OAM bus, returned to NES through $2004.
                 input oam_ptr_load,        // Load oam with specified value, when writing to NES $2003.
                 input oam_load,            // Load oam_ptr with specified value, when writing to NES $2004.
                 input [7:0] data_in,       // New value for oam or oam_ptr
                 output reg spr_overflow,   // Set to true if we had more than 8 objects on a scan line. Reset when exiting vblank.
                 output reg sprite0);       // True if sprite#0 is included on the scan line currently being painted.
  reg [7:0] sprtemp[0:31];   // Sprite Temporary Memory. 32 bytes.
  reg [7:0] oam[0:255];      // Sprite OAM. 256 bytes.
  reg [7:0] oam_ptr;         // Pointer into oam_ptr.
  reg [2:0] p;               // Upper 3 bits of pointer into temp, the lower bits are oam_ptr[1:0].
  reg [1:0] state;           // Current state machine state
  wire [7:0] oam_data = oam[oam_ptr];
  // Compute the current address we read/write in sprtemp.
  reg [4:0] sprtemp_ptr;
  // Check if the current Y coordinate is inside.
  wire [8:0] spr_y_coord = scanline - {1'b0, oam_data};
  wire spr_is_inside = (spr_y_coord[8:4] == 0) && (obj_size || spr_y_coord[3] == 0);
  reg [7:0] new_oam_ptr;     // [wire] New value for oam ptr
  reg [1:0] oam_inc;         // [wire] How much to increment oam ptr
  reg sprite0_curr;          // If sprite0 is included on the line being processed.
  reg oam_wrapped;           // [wire] if new_oam or new_p wrapped.
  
  wire [7:0] sprtemp_data = sprtemp[sprtemp_ptr];
  always @*  begin
    // Compute address to read/write in temp sprite ram
    casez({cycle[8], cycle[2]}) 
    2'b0_?: sprtemp_ptr = {p, oam_ptr[1:0]};
    2'b1_0: sprtemp_ptr = {cycle[5:3], cycle[1:0]}; // 1-4. Read Y, Tile, Attribs
    2'b1_1: sprtemp_ptr = {cycle[5:3], 2'b11};      // 5-8. Keep reading X.
    endcase
  end
    
  always @* begin
    /* verilator lint_off CASEOVERLAP */
    // Compute value to return to cpu through $2004. And also the value that gets written to temp sprite ram.
    casez({sprites_enabled, cycle[8], cycle[6], state, oam_ptr[1:0]})
    7'b1_10_??_??: oam_bus = sprtemp_data;         // At cycle 256-319 we output what's in sprite temp ram
    7'b1_??_00_??: oam_bus = 8'b11111111;                  // On the first 64 cycles (while inside state 0), we output 0xFF.
    7'b1_??_01_00: oam_bus = {4'b0000, spr_y_coord[3:0]};  // Y coord that will get written to temp ram.
    7'b?_??_??_10: oam_bus = {oam_data[7:5], 3'b000, oam_data[1:0]}; // Bits 2-4 of attrib are always zero when reading oam.
    default:       oam_bus = oam_data;                     // Default to outputting from oam.
    endcase
  end

  always @* begin
    // Compute incremented oam counters
    casez ({oam_load, state, oam_ptr[1:0]})
    5'b1_??_??: oam_inc = {oam_ptr[1:0] == 3, 1'b1};       // Always increment by 1 when writing to oam.
    5'b0_00_??: oam_inc = 2'b01;                           // State 0: On the the first 64 cycles we fill temp ram with 0xFF, increment low bits.
    5'b0_01_00: oam_inc = {!spr_is_inside, spr_is_inside}; // State 1: Copy Y coordinate and increment oam by 1 if it's inside, otherwise 4.
    5'b0_01_??: oam_inc = {oam_ptr[1:0] == 3, 1'b1};       // State 1: Copy remaining 3 bytes of the oam.
    // State 3: We've had more than 8 sprites. Set overflow flag if we found a sprite that overflowed.
    // NES BUG: It increments both low and high counters.
    5'b0_11_??: oam_inc = 2'b11;
    // While in the final state, keep incrementing the low bits only until they're zero.
    5'b0_10_??: oam_inc = {1'b0, oam_ptr[1:0] != 0};
    endcase
    /* verilator lint_on CASEOVERLAP */
    new_oam_ptr[1:0] = oam_ptr[1:0] + {1'b0, oam_inc[0]};
    {oam_wrapped, new_oam_ptr[7:2]} = {1'b0, oam_ptr[7:2]} + {6'b0, oam_inc[1]};
  end
  always @(posedge clk) if (ce) begin
     
    // Some bits of the OAM are hardwired to zero.
    if (oam_load)
      oam[oam_ptr] <= (oam_ptr & 3) == 2 ? data_in & 8'hE3: data_in;
    if (cycle[0] && sprites_enabled || oam_load || oam_ptr_load) begin
      oam_ptr <= oam_ptr_load ? data_in : new_oam_ptr;
    end
    // Set overflow flag?
    if (sprites_enabled && state == 2'b11 && spr_is_inside)
      spr_overflow <= 1;
    // Remember if sprite0 is included on the scanline, needed for hit test later.
    sprite0_curr <= (state == 2'b01 && oam_ptr[7:2] == 0 && spr_is_inside || sprite0_curr);
    
//    if (scanline == 0 && cycle[0] && (state == 2'b01 || state == 2'b00))
//      $write("Drawing sprite %d/%d. bus=%d oam_ptr=%X->%X oam_data=%X p=%d (%d %d %d)\n", scanline, cycle, oam_bus, oam_ptr, new_oam_ptr, oam_data, p,
//         cycle[0] && sprites_enabled, oam_load, oam_ptr_load);
    
    // Always writing to temp ram while we're in state 0 or 1.
    if (!state[1]) sprtemp[sprtemp_ptr] <= oam_bus;
    // Update state machine on every second cycle.
    if (cycle[0]) begin
      // Increment p whenever oam_ptr carries in state 0 or 1.
      if (!state[1] && oam_ptr[1:0] == 2'b11) p <= p + 1;
      // Set sprite0 if sprite1 was included on the scan line
      casez({state, (p == 7) && (oam_ptr[1:0] == 2'b11), oam_wrapped})
      4'b00_0_?: state <= 2'b00;  // State #0: Keep filling
      4'b00_1_?: state <= 2'b01;  // State #0: Until we filled 64 items.
      4'b01_?_1: state <= 2'b10;  // State #1: Goto State 2 if processed all OAM
      4'b01_1_0: state <= 2'b11;  // State #1: Goto State 3 if we found 8 sprites
      4'b01_0_0: state <= 2'b01;  // State #1: Keep comparing Y coordinates.
      4'b11_?_1: state <= 2'b10;  // State #3: Goto State 2 if processed all OAM
      4'b11_?_0: state <= 2'b11;  // State #3: Keep comparing Y coordinates
      4'b10_?_?: state <= 2'b10;  // Stuck in state 2.
      endcase
    end
    if (reset_line) begin
      state <= 0;
      p <= 0;
      oam_ptr <= 0;
      sprite0_curr <= 0;
      sprite0 <= sprite0_curr;
    end
    if (exiting_vblank)
      spr_overflow <= 0;
  end
endmodule  // SpriteRAM


// Generates addresses in VRAM where we'll fetch sprite graphics from,
// and populates load, load_in so the SpriteGen can be loaded.
// 10 LUT, 4 Slices
module SpriteAddressGen(input clk, input ce,
                        input enabled,          // If unset, |load| will be all zeros.
                        input obj_size,         // 0: Sprite Height 8, 1: Sprite Height 16.
                        input obj_patt,         // Object pattern table selection
                        input [2:0] cycle,      // Current load cycle. At #4, first bitmap byte is loaded. At #6, second bitmap byte is.
                        input [7:0] temp,       // Input temp data from SpriteTemp. #0 = Y Coord, #1 = Tile, #2 = Attribs, #3 = X Coord
                        output [12:0] vram_addr,// Low bits of address in VRAM that we'd like to read.
                        input [7:0] vram_data,  // Byte of VRAM in the specified address
                        output [3:0] load,      // Which subset of load_in that is now valid, will be loaded into SpritesGen.
                        output [26:0] load_in); // Bits to load into SpritesGen.
  reg [7:0] temp_tile;    // Holds the tile that we will get
  reg [3:0] temp_y;       // Holds the Y coord (will be swapped based on FlipY).
  reg flip_x, flip_y;     // If incoming bitmap data needs to be flipped in the X or Y direction.
  wire load_y =    (cycle == 0);
  wire load_tile = (cycle == 1);
  wire load_attr = (cycle == 2) && enabled;
  wire load_x =    (cycle == 3) && enabled;
  wire load_pix1 = (cycle == 5) && enabled;
  wire load_pix2 = (cycle == 7) && enabled;
  reg dummy_sprite; // Set if attrib indicates the sprite is invalid.
  // Flip incoming vram data based on flipx. Zero out the sprite if it's invalid. The bits are already flipped once.
  wire [7:0] vram_f = dummy_sprite ? 0 : 
                      !flip_x ?      {vram_data[0], vram_data[1], vram_data[2], vram_data[3], vram_data[4], vram_data[5], vram_data[6], vram_data[7]} : 
                                     vram_data;
  wire [3:0] y_f = temp_y ^ {flip_y, flip_y, flip_y, flip_y};
  assign load = {load_pix1, load_pix2, load_x, load_attr};
  assign load_in = {vram_f, vram_f, temp, temp[1:0], temp[5]};
  // If $2000.5 = 0, the tile index data is used as usual, and $2000.3 
  // selects the pattern table to use. If $2000.5 = 1, the MSB of the range 
  // result value become the LSB of the indexed tile, and the LSB of the tile 
  // index value determines pattern table selection. The lower 3 bits of the 
  // range result value are always used as the fine vertical offset into the 
  // selected pattern.
  assign vram_addr = {obj_size ? temp_tile[0] : obj_patt, 
                      temp_tile[7:1], obj_size ? y_f[3] : temp_tile[0], cycle[1], y_f[2:0] };
  always @(posedge clk) if (ce) begin
    if (load_y) temp_y <= temp[3:0];
    if (load_tile) temp_tile <= temp;
    if (load_attr) {flip_y, flip_x, dummy_sprite} <= {temp[7:6], temp[4]};
  end
//  always @(posedge clk) begin
//    if (load[3]) $write("Loading pix1: %x\n", load_in[26:19]);
//    if (load[2]) $write("Loading pix2: %x\n", load_in[18:11]);
//    if (load[1]) $write("Loading x: %x\n", load_in[10:3]);
//
//    if (valid_sprite && enabled)
//      $write("%d. Found %d. Flip:%d%d, Addr: %x, Vram: %x!\n", cycle, temp, flip_x, flip_y, vram_addr, vram_data);
//  end

endmodule  // SpriteAddressGen

module BgPainter(input clk, input ce,
                 input enable,             // Shift registers activated
                 input [2:0] cycle,
                 input [2:0] fine_x_scroll,
                 input [14:0] loopy,
                 output [7:0] name_table,  // VRAM name table to read next.
                 input [7:0] vram_data,
                 output [3:0] pixel);
  reg [15:0] playfield_pipe_1; // Name table pixel pipeline #1
  reg [15:0] playfield_pipe_2; // Name table pixel pipeline #2
  reg [8:0]  playfield_pipe_3; // Attribute table pixel pipe #1
  reg [8:0]  playfield_pipe_4; // Attribute table pixel pipe #2
  reg [7:0] current_name_table;      // Holds the current name table byte
  reg [1:0] current_attribute_table; // Holds the 2 current attribute table bits
  reg [7:0] bg0;                // Pixel data for last loaded background
  wire [7:0] bg1 =  vram_data;
  initial begin
    playfield_pipe_1 = 0;
    playfield_pipe_2 = 0;
    playfield_pipe_3 = 0;
    playfield_pipe_4 = 0;
    current_name_table = 0;
    current_attribute_table = 0;
    bg0 = 0;
  end
  always @(posedge clk) if (ce) begin
    case (cycle[2:0])
    1: current_name_table <= vram_data;
    3: current_attribute_table <= (!loopy[1] && !loopy[6]) ? vram_data[1:0] : 
                                  ( loopy[1] && !loopy[6]) ? vram_data[3:2] :
                                  (!loopy[1] &&  loopy[6]) ? vram_data[5:4] : 
                                                             vram_data[7:6];
    5: bg0 <= vram_data; // Pattern table bitmap #0
//    7: bg1 <= vram_data; // Pattern table bitmap #1
    endcase
    if (enable) begin
      playfield_pipe_1[14:0] <= playfield_pipe_1[15:1];
      playfield_pipe_2[14:0] <= playfield_pipe_2[15:1];
      playfield_pipe_3[7:0] <= playfield_pipe_3[8:1];
      playfield_pipe_4[7:0] <= playfield_pipe_4[8:1];
      // Load the new values into the shift registers at the last pixel.
      if (cycle[2:0] == 7) begin
        playfield_pipe_1[15:8] <= {bg0[0], bg0[1], bg0[2], bg0[3], bg0[4], bg0[5], bg0[6], bg0[7]};
        playfield_pipe_2[15:8] <= {bg1[0], bg1[1], bg1[2], bg1[3], bg1[4], bg1[5], bg1[6], bg1[7]};
        playfield_pipe_3[8] <= current_attribute_table[0];
        playfield_pipe_4[8] <= current_attribute_table[1];
      end
    end
  end
  assign name_table = current_name_table;
  wire [3:0] i = {1'b0, fine_x_scroll};
  assign pixel = {playfield_pipe_4[i], playfield_pipe_3[i],
                  playfield_pipe_2[i], playfield_pipe_1[i]};
endmodule  // BgPainter
 
module PixelMuxer(input [3:0] bg, input [3:0] obj, input obj_prio, output [3:0] out, output is_obj);
  wire bg_flag = bg[0] | bg[1];
  wire obj_flag = obj[0] | obj[1];
  assign is_obj = !(obj_prio && bg_flag) && obj_flag;
  assign out = is_obj ? obj : bg;
endmodule
 

module PaletteRam(input clk, input ce, input [4:0] addr, input [5:0] din, output [5:0] dout, input write);
  reg [5:0] palette [0:31];
  initial begin
        palette[0] = 6'h0F;
        palette[1] = 6'h2C;
        palette[2] = 6'h10;
        palette[3] = 6'h1C;
        palette[4] = 6'h0F;
        palette[5] = 6'h37;
        palette[6] = 6'h27;
        palette[7] = 6'h07;
        palette[8] = 6'h0F;
        palette[9] = 6'h28;
        palette[10] = 6'h16;
        palette[11] = 6'h07;
        palette[12] = 6'h0F;
        palette[13] = 6'h28;
        palette[14] = 6'h0F;
        palette[15] = 6'h2C;
        palette[16] = 6'h0F;
        palette[17] = 6'h0F;
        palette[18] = 6'h2C;
        palette[19] = 6'h11;
        palette[20] = 6'h0F;
        palette[21] = 6'h0F;
        palette[22] = 6'h20;
        palette[23] = 6'h38;
        palette[24] = 6'h0F;
        palette[25] = 6'h0F;
        palette[26] = 6'h15;
        palette[27] = 6'h27;
        palette[28] = 6'h0F;
        palette[29] = 6'h0F;
        palette[30] = 6'h11;
        palette[31] = 6'h3C;
  end
  // Force read from backdrop channel if reading from any addr 0.
  wire [4:0] addr2 = (addr[1:0] == 0) ? 0 : addr;
  assign dout = palette[addr2];
  always @(posedge clk) if (ce && write) begin
    // Allow writing only to x0
    if (!(addr[3:2] != 0 && addr[1:0] == 0))
      palette[addr2] <= din;
  end
endmodule  // PaletteRam
 
module PPU(input clk, input ce, input reset,   // input clock  21.48 MHz / 4. 1 clock cycle = 1 pixel
           output [5:0] color, // output color value, one pixel outputted every clock
           input [7:0] din,   // input data from bus
           output [7:0] dout, // output data to CPU
           input [2:0] ain,   // input address from CPU
           input read,        // read
           input write,       // write
           output nmi,    // one while inside vblank
           output vram_r, // read from vram active
           output vram_w, // write to vram active
           output [13:0] vram_a, // vram address
           input [7:0] vram_din, // vram input
           output [7:0] vram_dout,
           output [8:0] scanline,
           output [8:0] cycle,
           output [19:0] mapper_ppu_flags);
  // These are stored in control register 0
  reg obj_patt; // Object pattern table
  reg bg_patt;  // Background pattern table
  reg obj_size; // 1 if sprites are 16 pixels high, else 0.
  reg vbl_enable;  // Enable VBL flag
  // These are stored in control register 1
  reg grayscale; // Disable color burst
  reg playfield_clip;     // 0: Left side 8 pixels playfield clipping
  reg object_clip;        // 0: Left side 8 pixels object clipping
  reg enable_playfield;   // Enable playfield display
  reg enable_objects;     // Enable objects display
  reg [2:0] color_intensity; // Color intensity
  
  initial begin
    obj_patt = 0;
    bg_patt = 0;
    obj_size = 0;
    vbl_enable = 0;
    grayscale = 0;
    playfield_clip = 0;
    object_clip = 0;
    enable_playfield = 0;
    enable_objects = 0;
    color_intensity = 0;
  end
  
  reg nmi_occured;         // True if NMI has occured but not cleared.
  reg [7:0] vram_latch;
  // Clock generator
  wire is_in_vblank;        // True if we're in VBLANK
  //wire [8:0] scanline;      // Current scanline
  //wire [8:0] cycle;         // Current cycle inside of the line
  wire end_of_line;         // At the last pixel of a line
  wire at_last_cycle_group; // At the very last cycle group of the scan line.
  wire exiting_vblank;      // At the very last cycle of the vblank
  wire entering_vblank;     // 
  wire is_pre_render_line;  // True while we're on the pre render scanline
  wire is_rendering = (enable_playfield || enable_objects) && !is_in_vblank && scanline != 240;
  
  ClockGen clock(clk, ce, reset, is_rendering, scanline, cycle, is_in_vblank, end_of_line, at_last_cycle_group,
                 exiting_vblank, entering_vblank, is_pre_render_line);
  
  
  // The loopy module handles updating of the loopy address
  wire [14:0] loopy;
  wire [2:0] fine_x_scroll;
  LoopyGen loopy0(clk, ce, is_rendering, ain, din, read, write, is_pre_render_line, cycle, loopy, fine_x_scroll);
  // Set to true if the current ppu_addr pointer points into
  // palette ram.
  wire is_pal_address = (loopy[13:8] == 6'b111111);

  // Paints background
  wire [7:0] bg_name_table;
  wire [3:0] bg_pixel_noblank;
  BgPainter bg_painter(clk, ce, !at_last_cycle_group, cycle[2:0], fine_x_scroll, loopy, bg_name_table, vram_din, bg_pixel_noblank);
  
  // Blank out BG in the leftmost 8 pixels?
  wire show_bg_on_pixel = (playfield_clip || (cycle[7:3] != 0)) && enable_playfield;
  wire [3:0] bg_pixel = {bg_pixel_noblank[3:2], show_bg_on_pixel ? bg_pixel_noblank[1:0] : 2'b00};

  // This will set oam_ptr to 0 right before the scanline 240 and keep it there throughout vblank.
  wire before_line = (enable_playfield || enable_objects) && (exiting_vblank || end_of_line && !is_in_vblank);
  wire [7:0] oam_bus;
  wire sprite_overflow;
  wire obj0_on_line;                        // True if sprite#0 is included on the current line
  SpriteRAM sprite_ram(clk, ce,
                       before_line,         // Condition for resetting the sprite line state.
                       is_rendering,        // Condition for enabling sprite ram logic. Check so we're not on 
                       exiting_vblank,
                       obj_size,
                       scanline, cycle,
                       oam_bus,
                       write && (ain == 3), // Write to oam_ptr
                       write && (ain == 4), // Write to oam[oam_ptr]
                       din,
                       sprite_overflow,
                       obj0_on_line);
  wire [4:0] obj_pixel_noblank;
  wire [12:0] sprite_vram_addr;
  wire is_obj0_pixel;               // True if obj_pixel originates from sprite0.
  wire [3:0] spriteset_load;          // Which subset of the |load_in| to load into SpriteSet
  wire [26:0] spriteset_load_in;      // Bits to load into SpriteSet
  // Between 256..319 (64 cycles), fetches bitmap data for the 8 sprites and fills in the SpriteSet
  // so that it can start drawing on the next frame.
  SpriteAddressGen address_gen(clk, ce,
                               cycle[8] && !cycle[6],     // Load sprites between 256..319
                               obj_size, obj_patt,        // Object size and pattern table
                               cycle[2:0],                // Cycle counter
                               oam_bus,                   // Info from temp buffer.
                               sprite_vram_addr,          // [out] VRAM Address that we want data from
                               vram_din,                  // [in] Data at the specified address
                               spriteset_load,
                               spriteset_load_in);        // Which parts of SpriteGen to load
  // Between 0..255 (256 cycles), draws pixels.
  // Between 256..319 (64 cycles), will be populated for next line
  SpriteSet sprite_gen(clk, ce, !cycle[8], spriteset_load, spriteset_load_in, obj_pixel_noblank, is_obj0_pixel);
  // Blank out obj in the leftmost 8 pixels?    
  wire show_obj_on_pixel = (object_clip || (cycle[7:3] != 0)) && enable_objects;
  wire [4:0] obj_pixel = {obj_pixel_noblank[4:2], show_obj_on_pixel ? obj_pixel_noblank[1:0] : 2'b00};
  
  reg sprite0_hit_bg;            // True if sprite#0 has collided with the BG in the last frame.
  always @(posedge clk) if (ce) begin
    if (exiting_vblank)
      sprite0_hit_bg <= 0;
    else if (is_rendering &&         // Object rendering is enabled
             !cycle[8] &&            // X Pixel 0..255
             cycle[7:0] != 255 &&    // X pixel != 255
             !is_pre_render_line &&  // Y Pixel 0..239
             obj0_on_line &&         // True if sprite#0 is included on the scan line.
             is_obj0_pixel &&        // True if the pixel came from tempram #0.
             show_obj_on_pixel &&
             bg_pixel[1:0] != 0) begin // Background pixel nonzero.
      sprite0_hit_bg <= 1;
      
    end

//    if (!cycle[8] && is_visible_line && obj0_on_line && is_obj0_pixel)
//      $write("Sprite0 hit bg scan %d!!\n", scanline);

//    if (is_obj0_pixel)
//      $write("drawing obj0 pixel %d/%d\n", scanline, cycle);
  end
 
  wire [3:0] pixel;
  wire pixel_is_obj;
  PixelMuxer pixel_muxer(bg_pixel, obj_pixel[3:0], obj_pixel[4], pixel, pixel_is_obj);
 
  // Compute the value to put on the VRAM address bus
  assign vram_a = !is_rendering    ? loopy[13:0] : // VRAM
                  (cycle[2:1] == 0)     ? {2'b10, loopy[11:0]} : // Name table
                  (cycle[2:1] == 1)     ? {2'b10, loopy[11:10], 4'b1111, loopy[9:7], loopy[4:2]} : // Attribute table
                  cycle[8] && !cycle[6] ? {1'b0, sprite_vram_addr} : 
                                          {1'b0, bg_patt, bg_name_table, cycle[1], loopy[14:12]}; // Pattern table bitmap #0, #1
  // Read from VRAM, either when user requested a manual read, or when we're generating pixels.
  assign vram_r = read && (ain == 7) ||
                  is_rendering && cycle[0] == 0 && !end_of_line;
  
  // Write to VRAM?
  assign vram_w = write && (ain == 7) && !is_pal_address && !is_rendering;

  wire [5:0] color2;
  PaletteRam palette_ram(clk, ce, 
                         is_rendering ? {pixel_is_obj, pixel[3:0]} : (is_pal_address ? loopy[4:0] : 5'b0000), // Read addr
                         din[5:0], // Value to write
                         color2,    // Output color
                         write && (ain == 7) && is_pal_address); // Condition for writing
  assign color = grayscale ? {color2[5:4], 4'b0} : color2;
//  always @(posedge clk)  
//  if (scanline == 194 && cycle < 8 && color == 15) begin
//    $write("Pixel black %x %x %x %x %x\n", bg_pixel,obj_pixel,pixel,pixel_is_obj,color);
//  end

 
  always @(posedge clk) if (ce) begin
//    if (!is_in_vblank && write)
//      $write("%d/%d: $200%d <= %x\n", scanline, cycle, ain, din);
    if (write) begin
      case (ain)
      0: begin // PPU Control Register 1
      // t:....BA.. ........ = d:......BA
        obj_patt <= din[3];
        bg_patt <= din[4];
        obj_size <= din[5];
        vbl_enable <= din[7];
        
        //$write("PPU Control #0 <= %X\n", din);
      end
      1: begin // PPU Control Register 2
        grayscale <= din[0];
        playfield_clip <= din[1];
        object_clip <= din[2];
        enable_playfield <= din[3];
        enable_objects <= din[4];
        color_intensity <= din[7:5];
        if (!din[3] && scanline == 59)
          $write("Disabling playfield at cycle %d\n", cycle);
      end
      endcase
    end
     
    // Reset frame specific counters upon exiting vblank
    if (exiting_vblank)
      nmi_occured <= 0;
    // Set the 
    if (entering_vblank)
      nmi_occured <= 1;
    // Reset NMI register when reading from Status
    if (read && ain == 2)
      nmi_occured <= 0;
  end
  
  // If we're triggering a VBLANK NMI 
  assign nmi = nmi_occured && vbl_enable;

  // One cycle after vram_r was asserted, the value
  // is available on the bus.
  reg vram_read_delayed;
  always @(posedge clk) if (ce) begin
    if (vram_read_delayed)
      vram_latch <= vram_din;
    vram_read_delayed = vram_r;
  end
  
  // Value currently being written to video ram
  assign vram_dout = din;

  reg [7:0] latched_dout;
  always @* begin
    case (ain)
    2: latched_dout = {nmi_occured,
               sprite0_hit_bg,
               sprite_overflow,
               5'b00000};
    4: latched_dout = oam_bus;
    default: if (is_pal_address) begin
        latched_dout = {2'b00, color};
      end else begin
        latched_dout = vram_latch;
      end 
    endcase
  end
  
  assign dout = latched_dout;
  
  
  assign mapper_ppu_flags = {scanline, cycle, obj_size, is_rendering};

endmodule  // PPU
// Copyright (c) 2012-2013 Ludvig Strigeus
// This program is GPL Licensed. See COPYING for the full license.

//`include "cpu.v"
//`include "apu.v"
//`include "ppu.v"
//`include "mmu.v"

// Sprite DMA Works as follows.
// When the CPU writes to $4014 DMA is initiated ASAP.
// DMA runs for 512 cycles, the first cycle it reads from address
// xx00 - xxFF, into a latch, and the second cycle it writes to $2004.

// Facts:
// 1) Sprite DMA always does reads on even cycles and writes on odd cycles.
// 2) There are 1-2 cycles of cpu_read=1 after cpu_read=0 until Sprite DMA starts (pause_cpu=1, aout_enable=0)
// 3) Sprite DMA reads the address value on the last clock of cpu_read=0

/*

=== DMC State Machine ===

// 
if (dmc_state == 0 && dmc_trigger && cpu_read && !odd_cycle) dmc_state <= 1;
if (dmc_state == 1) dmc_state <= (spr_state[1] ? 3 : 2);
pause_cpu = dmc_state[1] && cpu_read;
if (dmc_state == 2 && cpu_read && !odd_cycle) dmc_state <= 3;
aout_enable = (dmc_state == 3 && !odd_cycle)
dmc_ack     = (dmc_state == 3 && !odd_cycle)
read        = 1
if (dmc_state == 3 && !odd_cycle) dmc_state <= 0;

== Sprite State Machine ==
if (sprite_trigger) { sprite_dma_addr <= data_from_cpu; spr_state <= 1; }
pause_cpu = spr_state[0] && cpu_read;
if (spr_state == 1 && cpu_read && odd_cycle) spr_state <= 3;
if (spr_state == 3 && !odd_cycle) { if (dmc_state == 3) spr_state <= 1; else DO_READ; }
if (spr_state == 3 && odd_cycle) { DO_WRITE; }


// 4) If DMC interrupts Sprite, then it runs on the even cycle, and the odd cycle will be idle (pause_cpu=1, aout_enable=0)
// 5) When DMC triggers && interrupts CPU, there will be 2-3 cycles (pause_cpu=1, aout_enable=0) before DMC DMA starts.
*/


module DmaController(input clk, input ce, input reset,
                     input odd_cycle,               // Current cycle even or odd?
                     input sprite_trigger,          // Sprite DMA trigger?
                     input dmc_trigger,             // DMC DMA trigger?
                     input cpu_read,                // CPU is in a read cycle?
                     input [7:0] data_from_cpu,     // Data written by CPU?
                     input [7:0] data_from_ram,     // Data read from RAM?
                     input [15:0] dmc_dma_addr,     // DMC DMA Address
                     output [15:0] aout,            // Address to access
                     output aout_enable,            // DMA controller wants bus control
                     output read,                   // 1 = read, 0 = write
                     output [7:0] data_to_ram,      // Value to write to RAM
                     output dmc_ack,                // ACK the DMC DMA
                     output pause_cpu);             // CPU is paused
  reg dmc_state;
  reg [1:0] spr_state;
  reg [7:0] sprite_dma_lastval;
  reg [15:0] sprite_dma_addr;     // sprite dma source addr
  wire [8:0] new_sprite_dma_addr = sprite_dma_addr[7:0] + 8'h01;
  always @(posedge clk) if (reset) begin
    dmc_state <= 0;
    spr_state <= 0;    
    sprite_dma_lastval <= 0;
    sprite_dma_addr <= 0;
  end else if (ce) begin
    if (dmc_state == 0 && dmc_trigger && cpu_read && !odd_cycle) dmc_state <= 1;
    if (dmc_state == 1 && !odd_cycle) dmc_state <= 0;
    
    if (sprite_trigger) begin sprite_dma_addr <= {data_from_cpu, 8'h00}; spr_state <= 1; end
    if (spr_state == 1 && cpu_read && odd_cycle) spr_state <= 3;
    if (spr_state[1] && !odd_cycle && dmc_state == 1) spr_state <= 1;
    if (spr_state[1] && odd_cycle) sprite_dma_addr[7:0] <= new_sprite_dma_addr[7:0];
    if (spr_state[1] && odd_cycle && new_sprite_dma_addr[8]) spr_state <= 0;
    if (spr_state[1]) sprite_dma_lastval <= data_from_ram;
  end
  assign pause_cpu = (spr_state[0] || dmc_trigger) && cpu_read;
  assign dmc_ack   = (dmc_state == 1 && !odd_cycle);
  assign aout_enable = dmc_ack || spr_state[1];
  assign read = !odd_cycle;
  assign data_to_ram = sprite_dma_lastval;
  assign aout = dmc_ack ? dmc_dma_addr : !odd_cycle ? sprite_dma_addr : 16'h2004;
endmodule

// Multiplexes accesses by the PPU and the PRG into a single memory, used for both
// ROM and internal memory.
// PPU has priority, its read/write will be honored asap, while the CPU's reads
// will happen only every second cycle when the PPU is idle.
// Data read by PPU will be available on the next clock cycle.
// Data read by CPU will be available within at most 2 clock cycles.

module MemoryMultiplex(input clk, input ce, input reset,
                       input [21:0] prg_addr, input prg_read, input prg_write, input [7:0] prg_din,
                       input [21:0] chr_addr, input chr_read, input chr_write, input [7:0] chr_din,
                       // Access signals for the SRAM.
                       output [21:0] memory_addr,   // address to access
                       output memory_read_cpu,      // read into CPU latch
                       output memory_read_ppu,      // read into PPU latch
                       output memory_write,         // is a write operation
                       output [7:0] memory_dout);
  reg saved_prg_read, saved_prg_write;
  assign memory_addr = (chr_read || chr_write) ? chr_addr : prg_addr;
  assign memory_write = (chr_read || chr_write) ? chr_write : saved_prg_write;
  assign memory_read_ppu = chr_read;
  assign memory_read_cpu = !(chr_read || chr_write) && (prg_read || saved_prg_read);
  assign memory_dout = chr_write ? chr_din : prg_din;
  always @(posedge clk) if (reset) begin
		saved_prg_read <= 0;
		saved_prg_write <= 0;
  end else if (ce) begin
    if (chr_read || chr_write) begin
      saved_prg_read <= prg_read || saved_prg_read;
      saved_prg_write <= prg_write || saved_prg_write;
    end else begin
      saved_prg_read <= 0;
      saved_prg_write <= prg_write;
    end
  end
endmodule


module NES(input clk, input reset, input ce,
           input [31:0] mapper_flags,
           output [15:0] sample, // sample generated from APU
           output [5:0] color,  // pixel generated from PPU
           output joypad_strobe,// Set to 1 to strobe joypads. Then set to zero to keep the value.
           output [1:0] joypad_clock, // Set to 1 for each joypad to clock it.
           input [3:0] joypad_data, // Data for each joypad + 1 powerpad.
           input [4:0] audio_channels, // Enabled audio channels

           
           // Access signals for the SRAM.
           output [21:0] memory_addr,   // address to access
           output memory_read_cpu,      // read into CPU latch
           input [7:0] memory_din_cpu,  // next cycle, contents of latch A (CPU's data)
           output memory_read_ppu,      // read into CPU latch
           input [7:0] memory_din_ppu,  // next cycle, contents of latch B (PPU's data)
           output memory_write,         // is a write operation
           output [7:0] memory_dout,
           
           output [8:0] cycle,
           output [8:0] scanline,
           
           output reg [31:0] dbgadr,
           output [1:0] dbgctr
           );
  reg [7:0] from_data_bus;
  wire [7:0] cpu_dout;
  wire odd_or_even; // Is this an odd or even clock cycle?

  // The CPU runs at one third the speed of the PPU.
  // CPU is clocked at cycle #2. PPU is clocked at cycle #0, #1, #2.
  // CPU does its memory I/O on cycle #0. It will be available in time for cycle #2.
  reg [1:0] cpu_cycle_counter;
  always @(posedge clk) begin
    if (reset)
      cpu_cycle_counter <= 0;
    else if (ce)
      cpu_cycle_counter <= (cpu_cycle_counter == 2) ? 0 : cpu_cycle_counter + 1;
  end

  // Sample the NMI flag on cycle #0, otherwise if NMI happens on cycle #0 or #1,
  // the CPU will use it even though it shouldn't be used until the next CPU cycle.
  wire nmi;
  reg nmi_active;
  always @(posedge clk) begin
    if (reset)
      nmi_active <= 0;
    else if (ce && cpu_cycle_counter == 0)
      nmi_active <= nmi;
  end

  wire apu_ce =        ce && (cpu_cycle_counter == 2);

  // -- CPU
  wire [15:0] cpu_addr;
  wire cpu_mr, cpu_mw;
  wire pause_cpu;
  reg apu_irq_delayed;
  reg mapper_irq_delayed;
  CPU cpu(clk, apu_ce && !pause_cpu, reset, from_data_bus, apu_irq_delayed | mapper_irq_delayed, nmi_active, cpu_dout, cpu_addr, cpu_mr, cpu_mw);

  // -- DMA
  wire [15:0] dma_aout;
  wire dma_aout_enable;
  wire dma_read;
  wire [7:0] dma_data_to_ram;
  wire apu_dma_request, apu_dma_ack;
  wire [15:0] apu_dma_addr;

  // Determine the values on the bus outgoing from the CPU chip (after DMA / APU)
  wire [15:0] addr = dma_aout_enable ? dma_aout : cpu_addr;
  wire [7:0]  dbus = dma_aout_enable ? dma_data_to_ram : cpu_dout;
  wire mr_int      = dma_aout_enable ? dma_read : cpu_mr;
  wire mw_int      = dma_aout_enable ? !dma_read : cpu_mw;

  DmaController dma(clk, apu_ce, reset, 
                    odd_or_even,                    // Even or odd cycle
                    (addr == 'h4014 && mw_int),     // Sprite trigger
                    apu_dma_request,                // DMC Trigger
                    cpu_mr,                         // CPU in a read cycle?
                    cpu_dout,                       // Data from cpu
                    from_data_bus,                  // Data from RAM etc.
                    apu_dma_addr,                   // DMC addr
                    dma_aout,
                    dma_aout_enable, 
                    dma_read,
                    dma_data_to_ram,
                    apu_dma_ack,
                    pause_cpu);

  // -- Audio Processing Unit  
  wire apu_cs = addr >= 'h4000 && addr < 'h4018;
  wire [7:0] apu_dout;
  wire apu_irq;
  APU apu(clk, apu_ce, reset,
          addr[4:0], dbus, apu_dout, 
          mw_int && apu_cs, mr_int && apu_cs,
          audio_channels,
          sample,
          apu_dma_request,
          apu_dma_ack,
          apu_dma_addr,
          from_data_bus,
          odd_or_even,
          apu_irq);

  // Joypads are mapped into the APU's range.
  wire joypad1_cs = (addr == 'h4016);
  wire joypad2_cs = (addr == 'h4017);
  assign joypad_strobe = (joypad1_cs && mw_int && cpu_dout[0]);
  assign joypad_clock =  {joypad2_cs && mr_int, joypad1_cs && mr_int};

      
  // -- PPU
  // PPU _reads_ need to happen on the same cycle the cpu runs on, to guarantee we
  // see proper values of register $2002.
  wire mr_ppu     = mr_int && (cpu_cycle_counter == 2);
  wire mw_ppu     = mw_int && (cpu_cycle_counter == 0);
  wire ppu_cs = addr >= 'h2000 && addr < 'h4000;
  wire [7:0] ppu_dout;           // Data from PPU to CPU
  wire chr_read, chr_write;      // If PPU reads/writes from VRAM
  wire [13:0] chr_addr;          // Address PPU accesses in VRAM
  wire [7:0] chr_from_ppu;       // Data from PPU to VRAM
  wire [7:0] chr_to_ppu;
  wire [19:0] mapper_ppu_flags;  // PPU flags for mapper cheating
  PPU ppu(clk, ce, reset, color, dbus, ppu_dout, addr[2:0],
          ppu_cs && mr_ppu, ppu_cs && mw_ppu,
          nmi,
          chr_read, chr_write, chr_addr, chr_to_ppu, chr_from_ppu,
          scanline, cycle, mapper_ppu_flags);

  // -- Memory mapping logic
  wire [15:0] prg_addr = addr;
  wire [7:0] prg_din = dbus;
  wire prg_read = mr_int && (cpu_cycle_counter == 0) && !apu_cs && !ppu_cs;
  wire prg_write = mw_int && (cpu_cycle_counter == 0) && !apu_cs && !ppu_cs;
  wire prg_allow, vram_a10, vram_ce, chr_allow;
  wire [21:0] prg_linaddr, chr_linaddr;
  wire [7:0] prg_dout_mapper, chr_from_ppu_mapper;
  wire cart_ce = (cpu_cycle_counter == 0) && ce;
  wire mapper_irq;
  wire has_chr_from_ppu_mapper;
  MultiMapper multi_mapper(clk, cart_ce, ce, reset, mapper_ppu_flags, mapper_flags, 
                           prg_addr, prg_linaddr, prg_read, prg_write, prg_din, prg_dout_mapper, from_data_bus, prg_allow,
                           chr_read, chr_addr, chr_linaddr, chr_from_ppu_mapper, has_chr_from_ppu_mapper, chr_allow, vram_a10, vram_ce, mapper_irq);
  assign chr_to_ppu = has_chr_from_ppu_mapper ? chr_from_ppu_mapper : memory_din_ppu;
                             
  // Mapper IRQ seems to be delayed by one PPU clock.   
  // APU IRQ seems delayed by one APU clock.
  always @(posedge clk) if (reset) begin
    mapper_irq_delayed <= 0;
    apu_irq_delayed <= 0;
  end else begin
    if (ce)
      mapper_irq_delayed <= mapper_irq;
    if (apu_ce)
      apu_irq_delayed <= apu_irq;
  end
   
  // -- Multiplexes CPU and PPU accesses into one single RAM
  MemoryMultiplex mem(clk, ce, reset, prg_linaddr, prg_read && prg_allow, prg_write && prg_allow, prg_din, 
                               chr_linaddr, chr_read,              chr_write && (chr_allow || vram_ce), chr_from_ppu,
                               memory_addr, memory_read_cpu, memory_read_ppu, memory_write, memory_dout);

  always @* begin
    if (reset)
		from_data_bus <= 0;
    else if (apu_cs) begin
      if (joypad1_cs)
        from_data_bus = {7'b0100000, joypad_data[0]};
      else if (joypad2_cs)
        from_data_bus = {3'b010, joypad_data[3:2] ,2'b00, joypad_data[1]};
      else
        from_data_bus = apu_dout;
    end else if (ppu_cs) begin
      from_data_bus = ppu_dout;
    end else if (prg_allow) begin
      from_data_bus = memory_din_cpu;
    end else begin
      from_data_bus = prg_dout_mapper;
    end
  end
  
endmodule
// Copyright (c) 2012-2013 Ludvig Strigeus
// This program is GPL Licensed. See COPYING for the full license.

//`include "MicroCode.v"

module MyAddSub(input [7:0] A,B,
                input CI,ADD,
                output [7:0] S,
                output CO,OFL);
  wire C0,C1,C2,C3,C4,C5,C6;
  wire C6O;
  wire [7:0] I = A ^ B ^ {8{~ADD}};
  MUXCY_L MUXCY_L0 (.LO(C0),.CI(CI),.DI(A[0]),.S(I[0]) );
  MUXCY_L MUXCY_L1 (.LO(C1),.CI(C0),.DI(A[1]),.S(I[1]) );
  MUXCY_L MUXCY_L2 (.LO(C2),.CI(C1),.DI(A[2]),.S(I[2]) );
  MUXCY_L MUXCY_L3 (.LO(C3),.CI(C2),.DI(A[3]),.S(I[3]) );
  MUXCY_L MUXCY_L4 (.LO(C4),.CI(C3),.DI(A[4]),.S(I[4]) );
  MUXCY_L MUXCY_L5 (.LO(C5),.CI(C4),.DI(A[5]),.S(I[5]) );
  MUXCY_D MUXCY_D6 (.LO(C6),.O(C6O),.CI(C5),.DI(A[6]),.S(I[6]) );
  MUXCY   MUXCY_7  (.O(CO),.CI(C6),.DI(A[7]),.S(I[7]) );
  XORCY XORCY0 (.O(S[0]),.CI(CI),.LI(I[0]));
  XORCY XORCY1 (.O(S[1]),.CI(C0),.LI(I[1]));
  XORCY XORCY2 (.O(S[2]),.CI(C1),.LI(I[2]));
  XORCY XORCY3 (.O(S[3]),.CI(C2),.LI(I[3]));
  XORCY XORCY4 (.O(S[4]),.CI(C3),.LI(I[4]));
  XORCY XORCY5 (.O(S[5]),.CI(C4),.LI(I[5]));
  XORCY XORCY6 (.O(S[6]),.CI(C5),.LI(I[6]));
  XORCY XORCY7 (.O(S[7]),.CI(C6),.LI(I[7]));
  XOR2_nes X1(.O(OFL),.I0(C6O),.I1(CO));
endmodule

module NewAlu(input  [10:0] OP, // ALU Operation
           input  [7:0] A,   // Registers input
           input  [7:0] X,   //       ""
           input  [7:0] Y,   //       ""
           input  [7:0] S,   //       ""
           input  [7:0] M,  // Secondary input to ALU
           input  [7:0] T,  // Secondary input to ALU
                             // -- Flags Input
           input        CI,  // Carry In
           input        VI,  // Overflow In
                             // -- Flags output
           output reg   CO,  // Carry out
           output reg   VO,  // Overflow out
           output reg   SO,  // Sign out
           output reg   ZO,  // zero out
                             // -- Result output
           output reg [7:0] Result,// Result out
           output reg [7:0] IntR); // Intermediate result out
  // Crack the ALU Operation
  wire [1:0] o_left_input, o_right_input;
  wire [2:0] o_first_op, o_second_op;
  wire o_fc;
  assign {o_left_input, o_right_input, o_first_op, o_second_op, o_fc} = OP;
  
  // Determine left, right inputs to Add/Sub ALU.
  reg [7:0] L, R;
  reg CR;
  always begin
    casez(o_left_input)
    0: L = A;
    1: L = Y;
    2: L = X;
    3: L = A & X;
    endcase
    casez(o_right_input)
    0: R = M;
    1: R = T;
    2: R = L;
    3: R = S;
    endcase
    CR = CI;
    casez(o_first_op[2:1])
    0: {CR, IntR} = {R, CI & o_first_op[0]};  // SHL, ROL
    1: {IntR, CR} = {CI & o_first_op[0], R};  // SHR, ROR
    2: IntR = R;                              // Passthrough
    3: IntR = R + (o_first_op[0] ? 8'b1 : 8'b11111111); // INC/DEC
    endcase
  end
  wire [7:0] AddR;
  wire AddCO, AddVO;
  MyAddSub addsub(.A(L),.B(IntR),.CI(o_second_op[0] ? CR : 1'b1),.ADD(!o_second_op[2]), .S(AddR), .CO(AddCO), .OFL(AddVO));
  // Produce the output of the second stage.
  always begin
    casez(o_second_op)
    0:       {CO, Result} = {CR,    L | IntR};
    1:       {CO, Result} = {CR,    L & IntR};
    2:       {CO, Result} = {CR,    L ^ IntR};
    3, 6, 7: {CO, Result} = {AddCO, AddR};
    4, 5:    {CO, Result} = {CR,    IntR};
    endcase
    // Final result
    ZO = (Result == 0);
    // Compute overflow flag
    VO = VI;
    casez(o_second_op)
    1: if (!o_fc) VO = IntR[6]; // Set V to 6th bit for BIT
    3: VO = AddVO;              // ADC always sets V
    7: if (o_fc) VO = AddVO;    // Only SBC sets V.
    endcase
    // Compute sign flag. It's always the uppermost bit of the result,
    // except for BIT that sets it to the 7th input bit
    SO = (o_second_op == 1 && !o_fc) ? IntR[7] : Result[7];
  end
endmodule

module AddressGenerator(input clk, input ce,
                        input [4:0] Operation, 
                        input [1:0] MuxCtrl,
                        input [7:0] DataBus, T, X, Y,
                        output [15:0] AX,
                        output Carry);
  // Actual contents of registers
  reg [7:0] AL, AH;
  // Last operation generated a carry?
  reg SavedCarry;
  assign AX = {AH, AL};

  wire [2:0] ALCtrl = Operation[4:2];
  wire [1:0] AHCtrl = Operation[1:0];

  // Possible new value for AL.
  wire [7:0] NewAL;
  assign {Carry,NewAL} = {1'b0, (MuxCtrl[1] ? T : AL)} + {1'b0, (MuxCtrl[0] ? Y : X)};
  
  // The other one
  wire TmpVal = (!AHCtrl[1] | SavedCarry);
  wire [7:0] TmpAdd = (AHCtrl[1] ? AH : AL) + {7'b0, TmpVal};
  
  always @(posedge clk) if (ce) begin
    SavedCarry <= Carry;
    if (ALCtrl[2])
      case(ALCtrl[1:0])
      0: AL <= NewAL;
      1: AL <= DataBus;
      2: AL <= TmpAdd;
      3: AL <= T;
      endcase
     
    case(AHCtrl[1:0])
    0: AH <= AH;
    1: AH <= 0;
    2: AH <= TmpAdd;
    3: AH <= DataBus;
    endcase
  end
endmodule

module ProgramCounter(input clk, input ce,
                      input [1:0] LoadPC,
                      input GotInterrupt,
                      input [7:0] DIN,
                      input [7:0] T,
                      output reg [15:0] PC, output JumpNoOverflow);
  reg [15:0] NewPC;
  assign JumpNoOverflow = ((PC[8] ^ NewPC[8]) == 0) & LoadPC[0] & LoadPC[1];

  always begin
    // Load PC Control
    case (LoadPC) 
    0,1: NewPC = PC + {15'b0, (LoadPC[0] & ~GotInterrupt)};
    2:   NewPC = {DIN,T};
    3:   NewPC = PC + {{8{T[7]}},T};
    endcase
  end
  
  always @(posedge clk)
    if (ce)
      PC <= NewPC;    
endmodule


module CPU(input clk, input ce, input reset,
           input [7:0] DIN,
           input irq,
           input nmi,
           output reg [7:0] dout, output reg [15:0] aout,
           output reg mr,
           output reg mw);
  reg [7:0] A, X, Y;
  reg [7:0] SP, T, P;
  reg [7:0] IR;
  reg [2:0] State;
  reg GotInterrupt;
  
  reg IsResetInterrupt;
  wire [15:0] PC;
  reg JumpTaken;
  wire JumpNoOverflow;

  // De-multiplex microcode
  wire [37:0] MicroCode;
  wire [1:0] LoadSP = MicroCode[1:0];            // 7 LUT
  wire [1:0] LoadPC = MicroCode[3:2];            // 12 LUT
  wire [1:0] AddrBus = MicroCode[5:4];           // 18 LUT
  wire [2:0] MemWrite = MicroCode[8:6];          // 10 LUT
  wire [4:0] AddrCtrl = MicroCode[13:9];       
  wire       FlagCtrl = MicroCode[14];           // RegWrite + FlagCtrl = 22 LUT
  wire [1:0] LoadT = MicroCode[16:15];           // 13 LUT
  wire [1:0] StateCtrl = MicroCode[18:17];
  wire [2:0] FlagsCtrl = MicroCode[21:19];
  wire [15:0] IrFlags = MicroCode[37:22];

  // Load Instruction Register? Force BRK on Interrupt.
  wire [7:0] NextIR = (State == 0) ? (GotInterrupt ? 8'd0 : DIN) : IR;
  wire IsBranchCycle1 = (IR[4:0] == 5'b10000) && State[0];

  // Compute next state.
  reg [2:0] NextState;
  always begin
    case (StateCtrl)
    0: NextState = State + 3'd1;
    1: NextState = (AXCarry ? 3'd4 : 3'd5);
    2: NextState = (IsBranchCycle1 && JumpTaken) ? 2 : 0; // Override next state if the branch is taken.
    3: NextState = (JumpNoOverflow ? 3'd0 : 3'd4);
    endcase
  end

  wire [15:0] AX;
  wire AXCarry;
AddressGenerator addgen(clk, ce, AddrCtrl, {IrFlags[0], IrFlags[1]}, DIN, T, X, Y, AX, AXCarry);

// Microcode table has a 1 clock latency (block ram).
MicroCodeTable micro2(clk, ce, reset, NextIR, NextState, MicroCode);

  wire [7:0] AluR;
  wire [7:0] AluIntR;
  wire CO, VO, SO,ZO;
NewAlu new_alu(IrFlags[15:5], A,X,Y,SP,DIN,T, P[0], P[6], CO, VO, SO, ZO, AluR, AluIntR);

// Registers
always @(posedge clk or posedge reset) if (reset) begin
  A <= 0;
  X <= 0;
  Y <= 0;
end else if (ce) begin
  if (FlagCtrl & IrFlags[2]) X <= AluR;
  if (FlagCtrl & IrFlags[3]) A <= AluR;
  if (FlagCtrl & IrFlags[4]) Y <= AluR;
end

// Program counter
ProgramCounter pc(clk, ce, LoadPC, GotInterrupt, DIN, T, PC, JumpNoOverflow);

reg IsNMIInterrupt;
reg LastNMI;
// NMI is triggered at any time, except during reset, or when we're in the middle of
// reading the vector address
wire turn_nmi_on = (AddrBus != 3) && !IsResetInterrupt && nmi && !LastNMI;
// Controls whether we'll remember the state in LastNMI
wire nmi_remembered = (AddrBus != 3) && !IsResetInterrupt ? nmi : LastNMI;
// NMI flag is cleared right after we read the vector address
wire turn_nmi_off = (AddrBus == 3) && (State[0] == 0);
// Controls whether IsNmiInterrupt will get set
wire nmi_active = turn_nmi_on ? 1 : turn_nmi_off ? 0 : IsNMIInterrupt;
always @(posedge clk or posedge reset) begin
  if (reset) begin
    IsNMIInterrupt <= 0;
    LastNMI <= 0;
  end else if (ce) begin
    IsNMIInterrupt <= nmi_active;
    LastNMI <= nmi_remembered;
  end
end

// Generate outputs from module...
always begin
  dout = 8'bX;
  case (MemWrite[1:0])
  'b00: dout = T;
  'b01: dout = AluR;
  'b10: dout = {P[7:6], 1'b1, !GotInterrupt, P[3:0]};
  'b11: dout = State[0] ? PC[7:0] : PC[15:8];
  endcase
  mw = MemWrite[2] && !IsResetInterrupt; // Prevent writing while handling a reset
  mr = !mw;
end

always begin
  case (AddrBus)
  0: aout = PC;
  1: aout = AX;
  2: aout = {8'h01, SP};
  // irq/BRK vector FFFE
  // nmi vector FFFA
  // Reset vector FFFC
  3: aout = {13'b1111_1111_1111_1, !IsNMIInterrupt, !IsResetInterrupt, ~State[0]};
  endcase 
end

 
always @(posedge clk) begin
  if (reset) begin
    // Reset runs the BRK instruction as usual.
    State <= 0;
    IR <= 0;
    GotInterrupt <= 1;
    IsResetInterrupt <= 1;
    P <= 'h24;
    SP <= 0;
    T <= 0;
    JumpTaken <= 0;
  end else if (ce) begin      
    // Stack pointer control.
    // The operand is an optimization that either
    // returns -1,0,1 depending on LoadSP 
    case (LoadSP)
    0,2,3: SP <= SP + { {7{LoadSP[0]}}, LoadSP[1] };
    1: SP <= X;
    endcase 

    // LoadT control
    case (LoadT)
    2: T <= DIN;
    3: T <= AluIntR;
    endcase

    if (FlagCtrl) begin
      case(FlagsCtrl)
      0: P <= P;      // No Op
      1: {P[0], P[1], P[6], P[7]} <= {CO, ZO, VO, SO}; // ALU
      2: P[2] <= 1;     // BRK
      3: P[6] <= 0;     // CLV
      4: {P[7:6],P[3:0]} <= {DIN[7:6], DIN[3:0]}; // RTI/PLP
      5: P[0] <= IR[5]; // CLC/SEC
      6: P[2] <= IR[5]; // CLI/SEI
      7: P[3] <= IR[5]; // CLD/SED
      endcase
    end

    // Compute if the jump is to be taken. Result is stored in a flipflop, so
    // it won't be available until next cycle.
    // NOTE: Using DIN here. DIN is IR at cycle 0. This means JumpTaken will
    // contain the Jump status at cycle 1.
    case (DIN[7:5])
    0: JumpTaken <= ~P[7]; // BPL
    1: JumpTaken <=  P[7]; // BMI
    2: JumpTaken <= ~P[6]; // BVC
    3: JumpTaken <=  P[6]; // BVS
    4: JumpTaken <= ~P[0]; // BCC
    5: JumpTaken <=  P[0]; // BCS
    6: JumpTaken <= ~P[1]; // BNE
    7: JumpTaken <=  P[1]; // BEQ
    endcase
    
    // Check the interrupt status on the last cycle of the current instruction,
    // (or on cycle #1 of any branch instruction)
    if (StateCtrl == 2'b10) begin
      GotInterrupt <= (irq & ~P[2]) | nmi_active;
      IsResetInterrupt <= 0;
    end

    IR <= NextIR;
    State <= NextState;
  end
end
endmodule
// Copyright (c) 2012-2013 Ludvig Strigeus
// This program is GPL Licensed. See COPYING for the full license.
 
module LenCtr_Lookup(input [4:0] X, output [7:0] Yout);
reg [6:0] Y;
always @*
begin
  case(X)
  0: Y = 7'h05;
  1: Y = 7'h7F;
  2: Y = 7'h0A;
  3: Y = 7'h01;
  4: Y = 7'h14;
  5: Y = 7'h02;
  6: Y = 7'h28;
  7: Y = 7'h03;
  8: Y = 7'h50;
  9: Y = 7'h04;
  10: Y = 7'h1E;
  11: Y = 7'h05;
  12: Y = 7'h07;
  13: Y = 7'h06;
  14: Y = 7'h0D;
  15: Y = 7'h07;
  16: Y = 7'h06;
  17: Y = 7'h08;
  18: Y = 7'h0C;
  19: Y = 7'h09;
  20: Y = 7'h18;
  21: Y = 7'h0A;
  22: Y = 7'h30;
  23: Y = 7'h0B;
  24: Y = 7'h60;
  25: Y = 7'h0C;
  26: Y = 7'h24;
  27: Y = 7'h0D;
  28: Y = 7'h08;
  29: Y = 7'h0E;
  30: Y = 7'h10;
  31: Y = 7'h0F;
  endcase
end
assign Yout = {Y, 1'b0};
endmodule

module SquareChan(input clk, input ce, input reset, input sq2,
                  input [1:0] Addr,
                  input [7:0] DIN,
                  input MW,
                  input LenCtr_Clock,
                  input Env_Clock,
                  input Enabled,
                  input [7:0] LenCtr_In,
                  output reg [3:0] Sample,
                  output IsNonZero);
reg [7:0] LenCtr;

// Register 1
reg [1:0] Duty;
reg EnvLoop, EnvDisable, EnvDoReset;
reg [3:0] Volume, Envelope, EnvDivider;
wire LenCtrHalt = EnvLoop; // Aliased bit
assign IsNonZero = (LenCtr != 0);
// Register 2
reg SweepEnable, SweepNegate, SweepReset;
reg [2:0] SweepPeriod, SweepDivider, SweepShift;

reg [10:0] Period;
reg [11:0] TimerCtr;
reg [2:0] SeqPos;
wire [10:0] ShiftedPeriod = (Period >> SweepShift);
wire [10:0] PeriodRhs = (SweepNegate ? (~ShiftedPeriod + {10'b0, sq2}) : ShiftedPeriod);
wire [11:0] NewSweepPeriod = Period + PeriodRhs;
wire ValidFreq = Period[10:3] >= 8 && (SweepNegate || !NewSweepPeriod[11]);

always @(posedge clk) if (reset) begin
    LenCtr <= 0;
    Duty <= 0;
    EnvDoReset <= 0;
    EnvLoop <= 0;
    EnvDisable <= 0;
    Volume <= 0;
    Envelope <= 0;
    EnvDivider <= 0;
    SweepEnable <= 0;
    SweepNegate <= 0;
    SweepReset <= 0;
    SweepPeriod <= 0;
    SweepDivider <= 0;
    SweepShift <= 0;    
    Period <= 0;
    TimerCtr <= 0;
    SeqPos <= 0;
  end else if (ce) begin
  // Check if writing to the regs of this channel
  // NOTE: This needs to be done before the clocking below.
  if (MW) begin
    case(Addr)
    0: begin
//      if (sq2) $write("SQ0: Duty=%d, EnvLoop=%d, EnvDisable=%d, Volume=%d\n", DIN[7:6], DIN[5], DIN[4], DIN[3:0]);
      Duty <= DIN[7:6];
      EnvLoop <= DIN[5];
      EnvDisable <= DIN[4];
      Volume <= DIN[3:0];
    end
    1: begin
//      if (sq2) $write("SQ1: SweepEnable=%d, SweepPeriod=%d, SweepNegate=%d, SweepShift=%d, DIN=%X\n", DIN[7], DIN[6:4], DIN[3], DIN[2:0], DIN);
      SweepEnable <= DIN[7];
      SweepPeriod <= DIN[6:4];
      SweepNegate <= DIN[3];
      SweepShift <= DIN[2:0];
      SweepReset <= 1;
    end
    2: begin
//      if (sq2) $write("SQ2: Period=%d. DIN=%X\n", DIN, DIN);
      Period[7:0] <= DIN;
    end
    3: begin
      // Upper bits of the period
//      if (sq2) $write("SQ3: PeriodUpper=%d LenCtr=%x DIN=%X\n", DIN[2:0], LenCtr_In, DIN);
      Period[10:8] <= DIN[2:0];
      LenCtr <= LenCtr_In;
      EnvDoReset <= 1;
      SeqPos <= 0;
    end
    endcase
  end

  
  // Count down the square timer...
  if (TimerCtr == 0) begin
    // Timer was clocked
    TimerCtr <= {Period, 1'b0};
    SeqPos <= SeqPos - 1;
  end else begin
    TimerCtr <= TimerCtr - 1;
  end

  // Clock the length counter?
  if (LenCtr_Clock && LenCtr != 0 && !LenCtrHalt) begin
    LenCtr <= LenCtr - 1;
  end
  
  // Clock the sweep unit?
  if (LenCtr_Clock) begin
    if (SweepDivider == 0) begin
      SweepDivider <= SweepPeriod;
      if (SweepEnable && SweepShift != 0 && ValidFreq)
        Period <= NewSweepPeriod[10:0];
    end else begin
      SweepDivider <= SweepDivider - 1;
    end
    if (SweepReset)
      SweepDivider <= SweepPeriod;
    SweepReset <= 0;
  end
  
  // Clock the envelope generator?
  if (Env_Clock) begin
    if (EnvDoReset) begin
      EnvDivider <= Volume;
      Envelope <= 15;
      EnvDoReset <= 0;
    end else if (EnvDivider == 0) begin
      EnvDivider <= Volume;
      if (Envelope != 0 || EnvLoop)
        Envelope <= Envelope - 1;
    end else begin
      EnvDivider <= EnvDivider - 1;
    end
  end
 
  // Length counter forced to zero if disabled.
  if (!Enabled)
    LenCtr <= 0;
end

reg DutyEnabled;  
always @* begin
  // Determine if the duty is enabled or not
  case (Duty)
  0: DutyEnabled = (SeqPos == 7);
  1: DutyEnabled = (SeqPos >= 6);
  2: DutyEnabled = (SeqPos >= 4);
  3: DutyEnabled = (SeqPos < 6);
  endcase

  // Compute the output
  if (LenCtr == 0 || !ValidFreq || !DutyEnabled)
    Sample = 0;
  else
    Sample = EnvDisable ? Volume : Envelope;
end
endmodule



module TriangleChan(input clk, input ce, input reset,
                    input [1:0] Addr,
                    input [7:0] DIN,
                    input MW,
                    input LenCtr_Clock,
                    input LinCtr_Clock,
                    input Enabled,
                    input [7:0] LenCtr_In,
                    output [3:0] Sample,
                    output IsNonZero);
  //
  reg [10:0] Period, TimerCtr;
  reg [4:0] SeqPos;
  //
  // Linear counter state
  reg [6:0] LinCtrPeriod, LinCtr;
  reg LinCtrl, LinHalt;
  wire LinCtrZero = (LinCtr == 0);
  //
  // Length counter state
  reg [7:0] LenCtr;
  wire LenCtrHalt = LinCtrl; // Aliased bit
  wire LenCtrZero = (LenCtr == 0);
  assign IsNonZero = !LenCtrZero;
  //
  always @(posedge clk) if (reset) begin
    Period <= 0;
    TimerCtr <= 0;
    SeqPos <= 0;
    LinCtrPeriod <= 0;
    LinCtr <= 0;
    LinCtrl <= 0;
    LinHalt <= 0;
    LenCtr <= 0;
  end else if (ce) begin
    // Check if writing to the regs of this channel 
    if (MW) begin
      case (Addr)
      0: begin
        LinCtrl <= DIN[7];
        LinCtrPeriod <= DIN[6:0];
      end
      2: begin
        Period[7:0] <= DIN;
      end
      3: begin
        Period[10:8] <= DIN[2:0];
        LenCtr <= LenCtr_In;
        LinHalt <= 1;
      end
      endcase
    end

    // Count down the period timer...
    if (TimerCtr == 0) begin
      TimerCtr <= Period;
    end else begin
      TimerCtr <= TimerCtr - 1;
    end
    //
    // Clock the length counter?
    if (LenCtr_Clock && !LenCtrZero && !LenCtrHalt) begin
      LenCtr <= LenCtr - 1;
    end
    //
    // Clock the linear counter?
    if (LinCtr_Clock) begin
      if (LinHalt)
        LinCtr <= LinCtrPeriod;
      else if (!LinCtrZero)
        LinCtr <= LinCtr - 1;
      if (!LinCtrl)
        LinHalt <= 0;
    end
    //
    // Length counter forced to zero if disabled.
    if (!Enabled)
      LenCtr <= 0;
      //
    // Clock the sequencer position
    if (TimerCtr == 0 && !LenCtrZero && !LinCtrZero)
      SeqPos <= SeqPos + 1;
  end
  // Generate the output
  assign Sample = SeqPos[3:0] ^ {4{~SeqPos[4]}};
  //
endmodule


module NoiseChan(input clk, input ce, input reset,
                 input [1:0] Addr,
                 input [7:0] DIN,
                 input MW,
                 input LenCtr_Clock,
                 input Env_Clock,
                 input Enabled,
                 input [7:0] LenCtr_In,
                 output [3:0] Sample,
                 output IsNonZero);
  //
  // Envelope volume
  reg EnvLoop, EnvDisable, EnvDoReset;
  reg [3:0] Volume, Envelope, EnvDivider;
  // Length counter
  wire LenCtrHalt = EnvLoop; // Aliased bit
  reg [7:0] LenCtr;
  //
  reg ShortMode;
  reg [14:0] Shift = 1;
  
  assign IsNonZero = (LenCtr != 0);
  //
  // Period stuff
  reg [3:0] Period;
  reg [11:0] NoisePeriod, TimerCtr;
  always @* begin
    case (Period)
    0: NoisePeriod = 12'h004;
    1: NoisePeriod = 12'h008;
    2: NoisePeriod = 12'h010;
    3: NoisePeriod = 12'h020;
    4: NoisePeriod = 12'h040;
    5: NoisePeriod = 12'h060;
    6: NoisePeriod = 12'h080;
    7: NoisePeriod = 12'h0A0;
    8: NoisePeriod = 12'h0CA;
    9: NoisePeriod = 12'h0FE;
    10: NoisePeriod = 12'h17C;
    11: NoisePeriod = 12'h1FC;
    12: NoisePeriod = 12'h2FA;
    13: NoisePeriod = 12'h3F8;
    14: NoisePeriod = 12'h7F2;
    15: NoisePeriod = 12'hFE4;  
    endcase
  end
  //
  always @(posedge clk) if (reset) begin
    EnvLoop <= 0;
    EnvDisable <= 0;
    EnvDoReset <= 0;
    Volume <= 0;
    Envelope <= 0;
    EnvDivider <= 0;
    LenCtr <= 0;
    ShortMode <= 0;
    Shift <= 1;
    Period <= 0;
    TimerCtr <= 0;
  end else if (ce) begin
    // Check if writing to the regs of this channel 
    if (MW) begin
      case (Addr)
      0: begin
        EnvLoop <= DIN[5];
        EnvDisable <= DIN[4];
        Volume <= DIN[3:0];
      end
      2: begin
        ShortMode <= DIN[7];
        Period <= DIN[3:0];
      end
      3: begin
        LenCtr <= LenCtr_In;
        EnvDoReset <= 1;
      end
      endcase
    end
    // Count down the period timer...
    if (TimerCtr == 0) begin
      TimerCtr <= NoisePeriod;
      // Clock the shift register. Use either 
      // bit 1 or 6 as the tap.
      Shift <= { 
        Shift[0] ^ (ShortMode ? Shift[6] : Shift[1]), 
        Shift[14:1]}; 
    end else begin
      TimerCtr <= TimerCtr - 1;
    end
    // Clock the length counter?
    if (LenCtr_Clock && LenCtr != 0 && !LenCtrHalt) begin
      LenCtr <= LenCtr - 1;
    end
    // Clock the envelope generator?
    if (Env_Clock) begin
      if (EnvDoReset) begin
        EnvDivider <= Volume;
        Envelope <= 15;
        EnvDoReset <= 0;
      end else if (EnvDivider == 0) begin
        EnvDivider <= Volume;
        if (Envelope != 0)
          Envelope <= Envelope - 1;
        else if (EnvLoop)
          Envelope <= 15;
      end else
        EnvDivider <= EnvDivider - 1;
    end
    if (!Enabled)
      LenCtr <= 0;
  end
  // Produce the output signal
  assign Sample = 
    (LenCtr == 0 || Shift[0]) ?
      0 : 
      (EnvDisable ? Volume : Envelope);
endmodule

module DmcChan(input clk, input ce, input reset,
               input odd_or_even,
               input [2:0] Addr,
               input [7:0] DIN,
               input MW,
               output [6:0] Sample,
               output DmaReq,          // 1 when DMC wants DMA
               input DmaAck,           // 1 when DMC byte is on DmcData. DmcDmaRequested should go low.
               output [15:0] DmaAddr,  // Address DMC wants to read
               input [7:0] DmaData,    // Input data to DMC from memory.
               output Irq,
               output IsDmcActive);
  reg IrqEnable;
  reg IrqActive;
  reg Loop;                 // Looping enabled
  reg [3:0] Freq;           // Current value of frequency register
  reg [6:0] Dac = 0;        // Current value of DAC
  reg [7:0] SampleAddress;  // Base address of sample
  reg [7:0] SampleLen;      // Length of sample
  reg [7:0] ShiftReg;       // Shift register
  reg [8:0] Cycles;         // Down counter, is the period
  reg [14:0] Address;        // 15 bits current address, 0x8000-0xffff
  reg [11:0] BytesLeft;      // 12 bits bytes left counter 0 - 4081.
  reg [2:0] BitsUsed;        // Number of bits left in the SampleBuffer.
  reg [7:0] SampleBuffer;    // Next value to be loaded into shift reg
  reg HasSampleBuffer;       // Sample buffer is nonempty
  reg HasShiftReg;           // Shift reg is non empty
  reg [8:0] NewPeriod[0:15];
  reg DmcEnabled;
  reg [1:0] ActivationDelay;
  assign DmaAddr = {1'b1, Address};
  assign Sample = Dac;
  assign Irq = IrqActive;
  assign IsDmcActive = DmcEnabled;
  
  assign DmaReq = !HasSampleBuffer && DmcEnabled && !ActivationDelay[0];
    
  initial begin
    NewPeriod[0] = 428;
    NewPeriod[1] = 380;
    NewPeriod[2] = 340;
    NewPeriod[3] = 320;
    NewPeriod[4] = 286;
    NewPeriod[5] = 254;
    NewPeriod[6] = 226;
    NewPeriod[7] = 214;
    NewPeriod[8] = 190;
    NewPeriod[9] = 160;
    NewPeriod[10] = 142;
    NewPeriod[11] = 128;
    NewPeriod[12] = 106;
    NewPeriod[13] = 84;
    NewPeriod[14] = 72;
    NewPeriod[15] = 54;
  end
  // Shift register initially loaded with 07
  always @(posedge clk) begin
    if (reset) begin
      IrqEnable <= 0;
      IrqActive <= 0;
      Loop <= 0;
      Freq <= 0;
      Dac <= 0;
      SampleAddress <= 0;
      SampleLen <= 0;
      ShiftReg <= 8'hff;
      Cycles <= 439;
      Address <= 0;
      BytesLeft <= 0;
      BitsUsed <= 0;
      SampleBuffer <= 0;
      HasSampleBuffer <= 0;
      HasShiftReg <= 0;
      DmcEnabled <= 0;
      ActivationDelay <= 0;
    end else if (ce) begin
      if (ActivationDelay == 3 && !odd_or_even) ActivationDelay <= 1;
      if (ActivationDelay == 1) ActivationDelay <= 0;
      
      if (MW) begin
        case (Addr)
        0: begin  // $4010   il-- ffff   IRQ enable, loop, frequency index
            IrqEnable <= DIN[7];
            Loop <= DIN[6];
            Freq <= DIN[3:0];
            if (!DIN[7]) IrqActive <= 0;
          end
        1: begin  // $4011   -ddd dddd   DAC
            // This will get missed if the Dac <= far below runs, that is by design.
            Dac <= DIN[6:0];
          end
        2: begin  // $4012   aaaa aaaa   sample address
            SampleAddress <= DIN[7:0];
          end
        3: begin  // $4013   llll llll   sample length
            SampleLen <= DIN[7:0];
          end
        5: begin // $4015 write	---D NT21  Enable DMC (D)
            IrqActive <= 0;
            DmcEnabled <= DIN[4];
            // If the DMC bit is set, the DMC sample will be restarted only if not already active.
            if (DIN[4] && !DmcEnabled) begin
              Address <= {1'b1, SampleAddress, 6'b000000};
              BytesLeft <= {SampleLen, 4'b0000};
              ActivationDelay <= 3;
            end
          end
        endcase
      end

      Cycles <= Cycles - 1;
      if (Cycles == 1) begin
        Cycles <= NewPeriod[Freq];
        if (HasShiftReg) begin
          if (ShiftReg[0]) begin
            Dac[6:1] <= (Dac[6:1] != 6'b111111) ? Dac[6:1] + 6'b000001 : Dac[6:1];
          end else begin
            Dac[6:1] <= (Dac[6:1] != 6'b000000) ? Dac[6:1] + 6'b111111 : Dac[6:1];
          end
        end
        ShiftReg <= {1'b0, ShiftReg[7:1]};
        BitsUsed <= BitsUsed + 1;
        if (BitsUsed == 7) begin
          HasShiftReg <= HasSampleBuffer;
          ShiftReg <= SampleBuffer;
          HasSampleBuffer <= 0;
        end
      end
      
      // Acknowledge DMA?
      if (DmaAck) begin
        Address <= Address + 1;
        BytesLeft <= BytesLeft - 1;
        HasSampleBuffer <= 1;
        SampleBuffer <= DmaData;
        if (BytesLeft == 0) begin
          Address <= {1'b1, SampleAddress, 6'b000000};
          BytesLeft <= {SampleLen, 4'b0000};
          DmcEnabled <= Loop;
          if (!Loop && IrqEnable)
            IrqActive <= 1;
        end
      end      
    end
  end
endmodule

module ApuLookupTable(input clk, input [7:0] in_a, input [7:0] in_b, output [15:0] out);
  reg [15:0] lookup[0:511];
  reg [15:0] tmp_a, tmp_b;
  initial begin
    lookup[  0] =     0; lookup[  1] =   760; lookup[  2] =  1503; lookup[  3] =  2228;
    lookup[  4] =  2936; lookup[  5] =  3627; lookup[  6] =  4303; lookup[  7] =  4963;
    lookup[  8] =  5609; lookup[  9] =  6240; lookup[ 10] =  6858; lookup[ 11] =  7462;
    lookup[ 12] =  8053; lookup[ 13] =  8631; lookup[ 14] =  9198; lookup[ 15] =  9752;
    lookup[ 16] = 10296; lookup[ 17] = 10828; lookup[ 18] = 11349; lookup[ 19] = 11860;
    lookup[ 20] = 12361; lookup[ 21] = 12852; lookup[ 22] = 13334; lookup[ 23] = 13807;
    lookup[ 24] = 14270; lookup[ 25] = 14725; lookup[ 26] = 15171; lookup[ 27] = 15609;
    lookup[ 28] = 16039; lookup[ 29] = 16461; lookup[ 30] = 16876; lookup[256] =     0;
    lookup[257] =   439; lookup[258] =   874; lookup[259] =  1306; lookup[260] =  1735;
    lookup[261] =  2160; lookup[262] =  2581; lookup[263] =  2999; lookup[264] =  3414;
    lookup[265] =  3826; lookup[266] =  4234; lookup[267] =  4639; lookup[268] =  5041;
    lookup[269] =  5440; lookup[270] =  5836; lookup[271] =  6229; lookup[272] =  6618;
    lookup[273] =  7005; lookup[274] =  7389; lookup[275] =  7769; lookup[276] =  8147;
    lookup[277] =  8522; lookup[278] =  8895; lookup[279] =  9264; lookup[280] =  9631;
    lookup[281] =  9995; lookup[282] = 10356; lookup[283] = 10714; lookup[284] = 11070;
    lookup[285] = 11423; lookup[286] = 11774; lookup[287] = 12122; lookup[288] = 12468;
    lookup[289] = 12811; lookup[290] = 13152; lookup[291] = 13490; lookup[292] = 13825;
    lookup[293] = 14159; lookup[294] = 14490; lookup[295] = 14818; lookup[296] = 15145;
    lookup[297] = 15469; lookup[298] = 15791; lookup[299] = 16110; lookup[300] = 16427;
    lookup[301] = 16742; lookup[302] = 17055; lookup[303] = 17366; lookup[304] = 17675;
    lookup[305] = 17981; lookup[306] = 18286; lookup[307] = 18588; lookup[308] = 18888;
    lookup[309] = 19187; lookup[310] = 19483; lookup[311] = 19777; lookup[312] = 20069;
    lookup[313] = 20360; lookup[314] = 20648; lookup[315] = 20935; lookup[316] = 21219;
    lookup[317] = 21502; lookup[318] = 21783; lookup[319] = 22062; lookup[320] = 22339;
    lookup[321] = 22615; lookup[322] = 22889; lookup[323] = 23160; lookup[324] = 23431;
    lookup[325] = 23699; lookup[326] = 23966; lookup[327] = 24231; lookup[328] = 24494;
    lookup[329] = 24756; lookup[330] = 25016; lookup[331] = 25274; lookup[332] = 25531;
    lookup[333] = 25786; lookup[334] = 26040; lookup[335] = 26292; lookup[336] = 26542;
    lookup[337] = 26791; lookup[338] = 27039; lookup[339] = 27284; lookup[340] = 27529;
    lookup[341] = 27772; lookup[342] = 28013; lookup[343] = 28253; lookup[344] = 28492;
    lookup[345] = 28729; lookup[346] = 28964; lookup[347] = 29198; lookup[348] = 29431;
    lookup[349] = 29663; lookup[350] = 29893; lookup[351] = 30121; lookup[352] = 30349;
    lookup[353] = 30575; lookup[354] = 30800; lookup[355] = 31023; lookup[356] = 31245;
    lookup[357] = 31466; lookup[358] = 31685; lookup[359] = 31904; lookup[360] = 32121;
    lookup[361] = 32336; lookup[362] = 32551; lookup[363] = 32764; lookup[364] = 32976;
    lookup[365] = 33187; lookup[366] = 33397; lookup[367] = 33605; lookup[368] = 33813;
    lookup[369] = 34019; lookup[370] = 34224; lookup[371] = 34428; lookup[372] = 34630;
    lookup[373] = 34832; lookup[374] = 35032; lookup[375] = 35232; lookup[376] = 35430;
    lookup[377] = 35627; lookup[378] = 35823; lookup[379] = 36018; lookup[380] = 36212;
    lookup[381] = 36405; lookup[382] = 36597; lookup[383] = 36788; lookup[384] = 36978;
    lookup[385] = 37166; lookup[386] = 37354; lookup[387] = 37541; lookup[388] = 37727;
    lookup[389] = 37912; lookup[390] = 38095; lookup[391] = 38278; lookup[392] = 38460;
    lookup[393] = 38641; lookup[394] = 38821; lookup[395] = 39000; lookup[396] = 39178;
    lookup[397] = 39355; lookup[398] = 39532; lookup[399] = 39707; lookup[400] = 39881;
    lookup[401] = 40055; lookup[402] = 40228; lookup[403] = 40399; lookup[404] = 40570;
    lookup[405] = 40740; lookup[406] = 40909; lookup[407] = 41078; lookup[408] = 41245;
    lookup[409] = 41412; lookup[410] = 41577; lookup[411] = 41742; lookup[412] = 41906;
    lookup[413] = 42070; lookup[414] = 42232; lookup[415] = 42394; lookup[416] = 42555;
    lookup[417] = 42715; lookup[418] = 42874; lookup[419] = 43032; lookup[420] = 43190;
    lookup[421] = 43347; lookup[422] = 43503; lookup[423] = 43659; lookup[424] = 43813;
    lookup[425] = 43967; lookup[426] = 44120; lookup[427] = 44273; lookup[428] = 44424;
    lookup[429] = 44575; lookup[430] = 44726; lookup[431] = 44875; lookup[432] = 45024;
    lookup[433] = 45172; lookup[434] = 45319; lookup[435] = 45466; lookup[436] = 45612;
    lookup[437] = 45757; lookup[438] = 45902; lookup[439] = 46046; lookup[440] = 46189;
    lookup[441] = 46332; lookup[442] = 46474; lookup[443] = 46615; lookup[444] = 46756;
    lookup[445] = 46895; lookup[446] = 47035; lookup[447] = 47173; lookup[448] = 47312;
    lookup[449] = 47449; lookup[450] = 47586; lookup[451] = 47722; lookup[452] = 47857;
    lookup[453] = 47992; lookup[454] = 48127; lookup[455] = 48260; lookup[456] = 48393;
    lookup[457] = 48526; lookup[458] = 48658;  
  end
  always @(posedge clk) begin
    tmp_a <= lookup[{1'b0, in_a}];
    tmp_b <= lookup[{1'b1, in_b}];
  end
  assign out = tmp_a + tmp_b;
endmodule


module APU(input clk, input ce, input reset,
           input [4:0] ADDR,  // APU Address Line
           input [7:0] DIN,   // Data to APU
           output [7:0] DOUT, // Data from APU
           input MW,          // Writes to APU
           input MR,          // Reads from APU
           input [4:0] audio_channels, // Enabled audio channels
           output [15:0] Sample,

           output DmaReq,      // 1 when DMC wants DMA
           input DmaAck,           // 1 when DMC byte is on DmcData. DmcDmaRequested should go low.
           output [15:0] DmaAddr,  // Address DMC wants to read
           input [7:0] DmaData,    // Input data to DMC from memory.

           output odd_or_even,
           output IRQ);       // IRQ asserted

// Which channels are enabled?
reg [3:0] Enabled;

// Output samples from the 4 channels
wire [3:0] Sq1Sample,Sq2Sample,TriSample,NoiSample;

// Output samples from the DMC channel
wire [6:0] DmcSample;
wire DmcIrq;
wire IsDmcActive;

// Generate internal memory write signals
wire ApuMW0 = MW && ADDR[4:2]==0; // SQ1
wire ApuMW1 = MW && ADDR[4:2]==1; // SQ2
wire ApuMW2 = MW && ADDR[4:2]==2; // TRI
wire ApuMW3 = MW && ADDR[4:2]==3; // NOI
wire ApuMW4 = MW && ADDR[4:2]>=4; // DMC
wire ApuMW5 = MW && ADDR[4:2]==5; // Control registers

wire Sq1NonZero, Sq2NonZero, TriNonZero, NoiNonZero;

// Common input to all channels
wire [7:0] LenCtr_In;
LenCtr_Lookup len(DIN[7:3], LenCtr_In);


// Frame sequencer registers
reg FrameSeqMode;
reg [15:0] Cycles;
reg ClkE, ClkL;
reg Wrote4017;
reg [1:0] IrqCtr;
reg InternalClock; // APU Differentiates between Even or Odd clocks
assign odd_or_even = InternalClock;


// Generate each channel
SquareChan   Sq1(clk, ce, reset, 0, ADDR[1:0], DIN, ApuMW0, ClkL, ClkE, Enabled[0], LenCtr_In, Sq1Sample, Sq1NonZero);
SquareChan   Sq2(clk, ce, reset, 1, ADDR[1:0], DIN, ApuMW1, ClkL, ClkE, Enabled[1], LenCtr_In, Sq2Sample, Sq2NonZero);
TriangleChan Tri(clk, ce, reset, ADDR[1:0], DIN, ApuMW2, ClkL, ClkE, Enabled[2], LenCtr_In, TriSample, TriNonZero);
NoiseChan    Noi(clk, ce, reset, ADDR[1:0], DIN, ApuMW3, ClkL, ClkE, Enabled[3], LenCtr_In, NoiSample, NoiNonZero);
DmcChan      Dmc(clk, ce, reset, odd_or_even, ADDR[2:0], DIN, ApuMW4, DmcSample, DmaReq, DmaAck, DmaAddr, DmaData, DmcIrq, IsDmcActive);

// Reading this register clears the frame interrupt flag (but not the DMC interrupt flag).
// If an interrupt flag was set at the same moment of the read, it will read back as 1 but it will not be cleared.
reg FrameInterrupt, DisableFrameInterrupt;


//mode 0: 4-step  effective rate (approx)
//---------------------------------------
//    - - - f      60 Hz
//    - l - l     120 Hz
//    e e e e     240 Hz


//mode 1: 5-step  effective rate (approx)
//---------------------------------------
//    - - - - -   (interrupt flag never set)
//    l - l - -    96 Hz
//    e e e e -   192 Hz

   
always @(posedge clk) if (reset) begin
  FrameSeqMode <= 0;
  DisableFrameInterrupt <= 0;
  FrameInterrupt <= 0;
  Enabled <= 0;
  InternalClock <= 0;
  Wrote4017 <= 0;
  ClkE <= 0;
  ClkL <= 0;
  Cycles <= 4; // This needs to be 5 for proper power up behavior
  IrqCtr <= 0;
end else if (ce) begin   
  FrameInterrupt <= IrqCtr[1] ? 1 : (ADDR == 5'h15 && MR || ApuMW5 && ADDR[1:0] == 3 && DIN[6]) ? 0 : FrameInterrupt;
  InternalClock <= !InternalClock;
  IrqCtr <= {IrqCtr[0], 1'b0};
  Cycles <= Cycles + 1;
  ClkE <= 0;
  ClkL <= 0;
  if (Cycles == 7457) begin
    ClkE <= 1;
  end else if (Cycles == 14913) begin
    ClkE <= 1;
    ClkL <= 1;
    ClkE <= 1;
    ClkL <= 1;
  end else if (Cycles == 22371) begin
    ClkE <= 1;
  end else if (Cycles == 29829) begin
    if (!FrameSeqMode) begin
      ClkE <= 1;
      ClkL <= 1;
      Cycles <= 0;
      IrqCtr <= 3;
      FrameInterrupt <= 1;
    end
  end else if (Cycles == 37281) begin
    ClkE <= 1;
    ClkL <= 1;
    Cycles <= 0;
  end
  
  // Handle one cycle delayed write to 4017.
  Wrote4017 <= 0;
  if (Wrote4017) begin
    if (FrameSeqMode) begin
      ClkE <= 1;
      ClkL <= 1;
    end
    Cycles <= 0;
  end
  
//  if (ClkE||ClkL) $write("%d: Clocking %s%s\n", Cycles, ClkE?"E":" ", ClkL?"L":" ");

  // Handle writes to control registers
  if (ApuMW5) begin
    case (ADDR[1:0])
    1: begin // Register $4015
      Enabled <= DIN[3:0];
//      $write("$4015 = %X\n", DIN);
    end
    3: begin // Register $4017
      FrameSeqMode <= DIN[7]; // 1 = 5 frames cycle, 0 = 4 frames cycle
      DisableFrameInterrupt <= DIN[6];
     
      // If the internal clock is even, things happen
      // right away.
      if (!InternalClock) begin
        if (DIN[7]) begin
          ClkE <= 1;
          ClkL <= 1;
        end
        Cycles <= 0;
      end
      
      // Otherwise they get delayed one clock
      Wrote4017 <= InternalClock;
    end
    endcase
  end


end

ApuLookupTable lookup(clk, 
                      (audio_channels[0] ? {4'b0, Sq1Sample} : 8'b0) + 
                      (audio_channels[1] ? {4'b0, Sq2Sample} : 8'b0), 
                      (audio_channels[2] ? {4'b0, TriSample} + {3'b0, TriSample, 1'b0} : 8'b0) + 
                      (audio_channels[3] ? {3'b0, NoiSample, 1'b0} : 8'b0) +
                      (audio_channels[4] ? {1'b0, DmcSample} : 8'b0),
                      Sample);

wire frame_irq = FrameInterrupt && !DisableFrameInterrupt;

// Generate bus output
assign DOUT = {DmcIrq, frame_irq, 1'b0, 
               IsDmcActive,
               NoiNonZero,
               TriNonZero,
               Sq2NonZero,
               Sq1NonZero};

assign IRQ = frame_irq || DmcIrq;

endmodule
// Copyright (c) 2012-2013 Ludvig Strigeus
// This program is GPL Licensed. See COPYING for the full license.
module MUXCY(output O, input CI, input DI, input S);
  assign O = S ? CI : DI;
endmodule
module MUXCY_L(output LO, input CI, input DI, input S);
  assign LO = S ? CI : DI;
endmodule
module MUXCY_D(output LO, output O, input CI, input DI, input S);
  assign LO = S ? CI : DI;
  assign O = LO;
endmodule
module XORCY(output O, input CI, input LI);
  assign O = CI ^ LI;
endmodule
module XOR2_nes(output O, input I0, input I1);
  assign O = I0 ^ I1;
endmodule// Simple, platform-agnostic single-ported RAM

module generic_ram(clock, reset, address, wren, write_data, read_data);

parameter integer WIDTH = 8;
parameter integer WORDS = 2048;
localparam ADDR_BITS = $clog2(WORDS-1);

input clock;
input reset;
input [ADDR_BITS-1:0] address;
input wren;
input [WIDTH-1:0] write_data;
output reg [WIDTH-1:0] read_data;

reg [WIDTH-1:0] mem[0:WORDS-1];

reg [ADDR_BITS-1:0] a_prereg;
reg [WIDTH-1:0] d_prereg;
reg wren_prereg;

always @(posedge clock) begin
  if (reset == 1'b1) begin
    wren_prereg <= 0;
    a_prereg <= 0;
    d_prereg <= 0;
  end else begin
    wren_prereg <= wren;
    a_prereg <= address;
    d_prereg <= write_data;
  end

  
  read_data <= mem[a_prereg];
  if (wren_prereg) mem[a_prereg] <= d_prereg;
end

endmodule// SPI flash memory interface, taken from the icosoc project

module icosoc_flashmem (
	input clk, reset,

	input valid,
	output reg ready,
	input [23:0] addr,
	output reg [31:0] rdata,

	output reg spi_cs,
	output reg spi_sclk,
	output reg spi_mosi,
	input spi_miso
);
	reg [7:0] buffer;
	reg [3:0] xfer_cnt;
	reg [3:0] state;

	always @(posedge clk) begin
		ready <= 0;
		if (reset || !valid || ready) begin
			spi_cs <= 1;
			spi_sclk <= 1;
			xfer_cnt <= 0;
			state <= 0;
		end else begin
			spi_cs <= 0;
			if (xfer_cnt) begin
				if (spi_sclk) begin
					spi_sclk <= 0;
					spi_mosi <= buffer[7];
				end else begin
					spi_sclk <= 1;
					buffer <= {buffer, spi_miso};
					xfer_cnt <= xfer_cnt - 1;
				end
			end else
			case (state)
				0: begin
					buffer <= 'h03;
					xfer_cnt <= 8;
					state <= 1;
				end
				1: begin
					buffer <= addr[23:16];
					xfer_cnt <= 8;
					state <= 2;
				end
				2: begin
					buffer <= addr[15:8];
					xfer_cnt <= 8;
					state <= 3;
				end
				3: begin
					buffer <= addr[7:0];
					xfer_cnt <= 8;
					state <= 4;
				end
				4: begin
					xfer_cnt <= 8;
					state <= 5;
				end
				5: begin
					rdata[7:0] <= buffer;
					xfer_cnt <= 8;
					state <= 6;
				end
				6: begin
					rdata[15:8] <= buffer;
					xfer_cnt <= 8;
					state <= 7;
				end
				7: begin
					rdata[23:16] <= buffer;
					xfer_cnt <= 8;
					state <= 8;
				end
				8: begin
					rdata[31:24] <= buffer;
					ready <= 1;
				end
			endcase
		end
	end
endmodule
module MicroCodeTableInner(input clk, input ce, input reset, input [7:0] IR, input [2:0] State, output reg [8:0] M);
  reg [8:0] L[0:2047];
  initial begin
L[0] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2] = 9'b00_10_10100; // ['PCH->[SP--]', 'PCL->[SP--],', 'PCH->[SP--](KEEPAC)', 'PCL->[SP--](KEEPAC)']
L[3] = 9'b00_10_10100; // ['PCH->[SP--]', 'PCL->[SP--],', 'PCH->[SP--](KEEPAC)', 'PCL->[SP--](KEEPAC)']
L[4] = 9'b00_10_10101; // P->[SP--]
L[5] = 9'b00_11_00011; // [VECT]->T
L[6] = 9'b10_11_10011; // [VECT]:T->PC
L[7] = 9'bxx_xx_xxxxx; // []
L[8] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[9] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[10] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[11] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[12] = 9'b00_01_01011; // [AX]->AH,T->AL
L[13] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[14] = 9'bxx_xx_xxxxx; // []
L[15] = 9'bxx_xx_xxxxx; // []
L[16] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[17] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[18] = 9'bxx_xx_xxxxx; // []
L[19] = 9'bxx_xx_xxxxx; // []
L[20] = 9'bxx_xx_xxxxx; // []
L[21] = 9'bxx_xx_xxxxx; // []
L[22] = 9'bxx_xx_xxxxx; // []
L[23] = 9'bxx_xx_xxxxx; // []
L[24] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[25] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[26] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[27] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[28] = 9'b00_01_01011; // [AX]->AH,T->AL
L[29] = 9'b00_01_00011; // [AX]->T
L[30] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[31] = 9'b10_01_00101; // T->[AX]
L[32] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[33] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[34] = 9'bxx_xx_xxxxx; // []
L[35] = 9'bxx_xx_xxxxx; // []
L[36] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[37] = 9'bxx_xx_xxxxx; // []
L[38] = 9'bxx_xx_xxxxx; // []
L[39] = 9'bxx_xx_xxxxx; // []
L[40] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[41] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[42] = 9'bxx_xx_xxxxx; // []
L[43] = 9'bxx_xx_xxxxx; // []
L[44] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[45] = 9'bxx_xx_xxxxx; // []
L[46] = 9'bxx_xx_xxxxx; // []
L[47] = 9'bxx_xx_xxxxx; // []
L[48] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[49] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[50] = 9'bxx_xx_xxxxx; // []
L[51] = 9'bxx_xx_xxxxx; // []
L[52] = 9'b00_01_00011; // [AX]->T
L[53] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[54] = 9'b10_01_00101; // T->[AX]
L[55] = 9'bxx_xx_xxxxx; // []
L[56] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[57] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[58] = 9'bxx_xx_xxxxx; // []
L[59] = 9'bxx_xx_xxxxx; // []
L[60] = 9'b00_01_00011; // [AX]->T
L[61] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[62] = 9'b10_01_00101; // T->[AX]
L[63] = 9'bxx_xx_xxxxx; // []
L[64] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[65] = 9'b00_00_00011; // [PC]->
L[66] = 9'b10_10_01111; // P->[SP--]
L[67] = 9'bxx_xx_xxxxx; // []
L[68] = 9'bxx_xx_xxxxx; // []
L[69] = 9'bxx_xx_xxxxx; // []
L[70] = 9'bxx_xx_xxxxx; // []
L[71] = 9'bxx_xx_xxxxx; // []
L[72] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[73] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[74] = 9'bxx_xx_xxxxx; // []
L[75] = 9'bxx_xx_xxxxx; // []
L[76] = 9'bxx_xx_xxxxx; // []
L[77] = 9'bxx_xx_xxxxx; // []
L[78] = 9'bxx_xx_xxxxx; // []
L[79] = 9'bxx_xx_xxxxx; // []
L[80] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[81] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[82] = 9'bxx_xx_xxxxx; // []
L[83] = 9'bxx_xx_xxxxx; // []
L[84] = 9'bxx_xx_xxxxx; // []
L[85] = 9'bxx_xx_xxxxx; // []
L[86] = 9'bxx_xx_xxxxx; // []
L[87] = 9'bxx_xx_xxxxx; // []
L[88] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[89] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[90] = 9'bxx_xx_xxxxx; // []
L[91] = 9'bxx_xx_xxxxx; // []
L[92] = 9'bxx_xx_xxxxx; // []
L[93] = 9'bxx_xx_xxxxx; // []
L[94] = 9'bxx_xx_xxxxx; // []
L[95] = 9'bxx_xx_xxxxx; // []
L[96] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[97] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[98] = 9'b11_00_00001; // [PC++]->AH
L[99] = 9'bxx_xx_xxxxx; // []
L[100] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[101] = 9'bxx_xx_xxxxx; // []
L[102] = 9'bxx_xx_xxxxx; // []
L[103] = 9'bxx_xx_xxxxx; // []
L[104] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[105] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[106] = 9'b11_00_00001; // [PC++]->AH
L[107] = 9'bxx_xx_xxxxx; // []
L[108] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[109] = 9'bxx_xx_xxxxx; // []
L[110] = 9'bxx_xx_xxxxx; // []
L[111] = 9'bxx_xx_xxxxx; // []
L[112] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[113] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[114] = 9'b11_00_00001; // [PC++]->AH
L[115] = 9'bxx_xx_xxxxx; // []
L[116] = 9'b00_01_00011; // [AX]->T
L[117] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[118] = 9'b10_01_00101; // T->[AX]
L[119] = 9'bxx_xx_xxxxx; // []
L[120] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[121] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[122] = 9'b11_00_00001; // [PC++]->AH
L[123] = 9'bxx_xx_xxxxx; // []
L[124] = 9'b00_01_00011; // [AX]->T
L[125] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[126] = 9'b10_01_00101; // T->[AX]
L[127] = 9'bxx_xx_xxxxx; // []
L[128] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[129] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[130] = 9'b11_00_10001; // PC+T->PC
L[131] = 9'bxx_xx_xxxxx; // []
L[132] = 9'b10_00_00011; // ['NO-OP', '']
L[133] = 9'bxx_xx_xxxxx; // []
L[134] = 9'bxx_xx_xxxxx; // []
L[135] = 9'bxx_xx_xxxxx; // []
L[136] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[137] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[138] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[139] = 9'b01_01_01100; // [AX]->AH,T+Y->AL
L[140] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[141] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[142] = 9'bxx_xx_xxxxx; // []
L[143] = 9'bxx_xx_xxxxx; // []
L[144] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[145] = 9'b10_00_00011; // ['NO-OP', '']
L[146] = 9'bxx_xx_xxxxx; // []
L[147] = 9'bxx_xx_xxxxx; // []
L[148] = 9'bxx_xx_xxxxx; // []
L[149] = 9'bxx_xx_xxxxx; // []
L[150] = 9'bxx_xx_xxxxx; // []
L[151] = 9'bxx_xx_xxxxx; // []
L[152] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[153] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[154] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[155] = 9'b00_01_01100; // [AX]->AH,T+Y->AL
L[156] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[157] = 9'b00_01_00011; // [AX]->T
L[158] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[159] = 9'b10_01_00101; // T->[AX]
L[160] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[161] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[162] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[163] = 9'bxx_xx_xxxxx; // []
L[164] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[165] = 9'bxx_xx_xxxxx; // []
L[166] = 9'bxx_xx_xxxxx; // []
L[167] = 9'bxx_xx_xxxxx; // []
L[168] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[169] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[170] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[171] = 9'bxx_xx_xxxxx; // []
L[172] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[173] = 9'bxx_xx_xxxxx; // []
L[174] = 9'bxx_xx_xxxxx; // []
L[175] = 9'bxx_xx_xxxxx; // []
L[176] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[177] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[178] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[179] = 9'bxx_xx_xxxxx; // []
L[180] = 9'b00_01_00011; // [AX]->T
L[181] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[182] = 9'b10_01_00101; // T->[AX]
L[183] = 9'bxx_xx_xxxxx; // []
L[184] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[185] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[186] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[187] = 9'bxx_xx_xxxxx; // []
L[188] = 9'b00_01_00011; // [AX]->T
L[189] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[190] = 9'b10_01_00101; // T->[AX]
L[191] = 9'bxx_xx_xxxxx; // []
L[192] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[193] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[194] = 9'bxx_xx_xxxxx; // []
L[195] = 9'bxx_xx_xxxxx; // []
L[196] = 9'bxx_xx_xxxxx; // []
L[197] = 9'bxx_xx_xxxxx; // []
L[198] = 9'bxx_xx_xxxxx; // []
L[199] = 9'bxx_xx_xxxxx; // []
L[200] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[201] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[202] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[203] = 9'bxx_xx_xxxxx; // []
L[204] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[205] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[206] = 9'bxx_xx_xxxxx; // []
L[207] = 9'bxx_xx_xxxxx; // []
L[208] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[209] = 9'b10_00_00011; // ['NO-OP', '']
L[210] = 9'bxx_xx_xxxxx; // []
L[211] = 9'bxx_xx_xxxxx; // []
L[212] = 9'bxx_xx_xxxxx; // []
L[213] = 9'bxx_xx_xxxxx; // []
L[214] = 9'bxx_xx_xxxxx; // []
L[215] = 9'bxx_xx_xxxxx; // []
L[216] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[217] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[218] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[219] = 9'bxx_xx_xxxxx; // []
L[220] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[221] = 9'b00_01_00011; // [AX]->T
L[222] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[223] = 9'b10_01_00101; // T->[AX]
L[224] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[225] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[226] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[227] = 9'bxx_xx_xxxxx; // []
L[228] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[229] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[230] = 9'bxx_xx_xxxxx; // []
L[231] = 9'bxx_xx_xxxxx; // []
L[232] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[233] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[234] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[235] = 9'bxx_xx_xxxxx; // []
L[236] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[237] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[238] = 9'bxx_xx_xxxxx; // []
L[239] = 9'bxx_xx_xxxxx; // []
L[240] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[241] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[242] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[243] = 9'bxx_xx_xxxxx; // []
L[244] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[245] = 9'b00_01_00011; // [AX]->T
L[246] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[247] = 9'b10_01_00101; // T->[AX]
L[248] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[249] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[250] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[251] = 9'bxx_xx_xxxxx; // []
L[252] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[253] = 9'b00_01_00011; // [AX]->T
L[254] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[255] = 9'b10_01_00101; // T->[AX]
L[256] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[257] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[258] = 9'b00_10_10100; // ['PCH->[SP--]', 'PCL->[SP--],', 'PCH->[SP--](KEEPAC)', 'PCL->[SP--](KEEPAC)']
L[259] = 9'b00_10_10100; // ['PCH->[SP--]', 'PCL->[SP--],', 'PCH->[SP--](KEEPAC)', 'PCL->[SP--](KEEPAC)']
L[260] = 9'b00_10_00111; // KEEP_AC
L[261] = 9'b10_00_10011; // [PC]:T->PC
L[262] = 9'bxx_xx_xxxxx; // []
L[263] = 9'bxx_xx_xxxxx; // []
L[264] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[265] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[266] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[267] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[268] = 9'b00_01_01011; // [AX]->AH,T->AL
L[269] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[270] = 9'bxx_xx_xxxxx; // []
L[271] = 9'bxx_xx_xxxxx; // []
L[272] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[273] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[274] = 9'bxx_xx_xxxxx; // []
L[275] = 9'bxx_xx_xxxxx; // []
L[276] = 9'bxx_xx_xxxxx; // []
L[277] = 9'bxx_xx_xxxxx; // []
L[278] = 9'bxx_xx_xxxxx; // []
L[279] = 9'bxx_xx_xxxxx; // []
L[280] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[281] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[282] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[283] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[284] = 9'b00_01_01011; // [AX]->AH,T->AL
L[285] = 9'b00_01_00011; // [AX]->T
L[286] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[287] = 9'b10_01_00101; // T->[AX]
L[288] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[289] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[290] = 9'bxx_xx_xxxxx; // []
L[291] = 9'bxx_xx_xxxxx; // []
L[292] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[293] = 9'bxx_xx_xxxxx; // []
L[294] = 9'bxx_xx_xxxxx; // []
L[295] = 9'bxx_xx_xxxxx; // []
L[296] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[297] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[298] = 9'bxx_xx_xxxxx; // []
L[299] = 9'bxx_xx_xxxxx; // []
L[300] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[301] = 9'bxx_xx_xxxxx; // []
L[302] = 9'bxx_xx_xxxxx; // []
L[303] = 9'bxx_xx_xxxxx; // []
L[304] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[305] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[306] = 9'bxx_xx_xxxxx; // []
L[307] = 9'bxx_xx_xxxxx; // []
L[308] = 9'b00_01_00011; // [AX]->T
L[309] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[310] = 9'b10_01_00101; // T->[AX]
L[311] = 9'bxx_xx_xxxxx; // []
L[312] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[313] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[314] = 9'bxx_xx_xxxxx; // []
L[315] = 9'bxx_xx_xxxxx; // []
L[316] = 9'b00_01_00011; // [AX]->T
L[317] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[318] = 9'b10_01_00101; // T->[AX]
L[319] = 9'bxx_xx_xxxxx; // []
L[320] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[321] = 9'b00_00_00011; // [PC]->
L[322] = 9'b00_10_10000; // ['SP++', 'SP+1->SP', '[SP]->T,SP+1->SP']
L[323] = 9'b10_10_00010; // ['ALU([SP])->A', '[SP]->P']
L[324] = 9'bxx_xx_xxxxx; // []
L[325] = 9'bxx_xx_xxxxx; // []
L[326] = 9'bxx_xx_xxxxx; // []
L[327] = 9'bxx_xx_xxxxx; // []
L[328] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[329] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[330] = 9'bxx_xx_xxxxx; // []
L[331] = 9'bxx_xx_xxxxx; // []
L[332] = 9'bxx_xx_xxxxx; // []
L[333] = 9'bxx_xx_xxxxx; // []
L[334] = 9'bxx_xx_xxxxx; // []
L[335] = 9'bxx_xx_xxxxx; // []
L[336] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[337] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[338] = 9'bxx_xx_xxxxx; // []
L[339] = 9'bxx_xx_xxxxx; // []
L[340] = 9'bxx_xx_xxxxx; // []
L[341] = 9'bxx_xx_xxxxx; // []
L[342] = 9'bxx_xx_xxxxx; // []
L[343] = 9'bxx_xx_xxxxx; // []
L[344] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[345] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[346] = 9'bxx_xx_xxxxx; // []
L[347] = 9'bxx_xx_xxxxx; // []
L[348] = 9'bxx_xx_xxxxx; // []
L[349] = 9'bxx_xx_xxxxx; // []
L[350] = 9'bxx_xx_xxxxx; // []
L[351] = 9'bxx_xx_xxxxx; // []
L[352] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[353] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[354] = 9'b11_00_00001; // [PC++]->AH
L[355] = 9'bxx_xx_xxxxx; // []
L[356] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[357] = 9'bxx_xx_xxxxx; // []
L[358] = 9'bxx_xx_xxxxx; // []
L[359] = 9'bxx_xx_xxxxx; // []
L[360] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[361] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[362] = 9'b11_00_00001; // [PC++]->AH
L[363] = 9'bxx_xx_xxxxx; // []
L[364] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[365] = 9'bxx_xx_xxxxx; // []
L[366] = 9'bxx_xx_xxxxx; // []
L[367] = 9'bxx_xx_xxxxx; // []
L[368] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[369] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[370] = 9'b11_00_00001; // [PC++]->AH
L[371] = 9'bxx_xx_xxxxx; // []
L[372] = 9'b00_01_00011; // [AX]->T
L[373] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[374] = 9'b10_01_00101; // T->[AX]
L[375] = 9'bxx_xx_xxxxx; // []
L[376] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[377] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[378] = 9'b11_00_00001; // [PC++]->AH
L[379] = 9'bxx_xx_xxxxx; // []
L[380] = 9'b00_01_00011; // [AX]->T
L[381] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[382] = 9'b10_01_00101; // T->[AX]
L[383] = 9'bxx_xx_xxxxx; // []
L[384] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[385] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[386] = 9'b11_00_10001; // PC+T->PC
L[387] = 9'bxx_xx_xxxxx; // []
L[388] = 9'b10_00_00011; // ['NO-OP', '']
L[389] = 9'bxx_xx_xxxxx; // []
L[390] = 9'bxx_xx_xxxxx; // []
L[391] = 9'bxx_xx_xxxxx; // []
L[392] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[393] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[394] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[395] = 9'b01_01_01100; // [AX]->AH,T+Y->AL
L[396] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[397] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[398] = 9'bxx_xx_xxxxx; // []
L[399] = 9'bxx_xx_xxxxx; // []
L[400] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[401] = 9'b10_00_00011; // ['NO-OP', '']
L[402] = 9'bxx_xx_xxxxx; // []
L[403] = 9'bxx_xx_xxxxx; // []
L[404] = 9'bxx_xx_xxxxx; // []
L[405] = 9'bxx_xx_xxxxx; // []
L[406] = 9'bxx_xx_xxxxx; // []
L[407] = 9'bxx_xx_xxxxx; // []
L[408] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[409] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[410] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[411] = 9'b00_01_01100; // [AX]->AH,T+Y->AL
L[412] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[413] = 9'b00_01_00011; // [AX]->T
L[414] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[415] = 9'b10_01_00101; // T->[AX]
L[416] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[417] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[418] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[419] = 9'bxx_xx_xxxxx; // []
L[420] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[421] = 9'bxx_xx_xxxxx; // []
L[422] = 9'bxx_xx_xxxxx; // []
L[423] = 9'bxx_xx_xxxxx; // []
L[424] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[425] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[426] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[427] = 9'bxx_xx_xxxxx; // []
L[428] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[429] = 9'bxx_xx_xxxxx; // []
L[430] = 9'bxx_xx_xxxxx; // []
L[431] = 9'bxx_xx_xxxxx; // []
L[432] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[433] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[434] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[435] = 9'bxx_xx_xxxxx; // []
L[436] = 9'b00_01_00011; // [AX]->T
L[437] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[438] = 9'b10_01_00101; // T->[AX]
L[439] = 9'bxx_xx_xxxxx; // []
L[440] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[441] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[442] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[443] = 9'bxx_xx_xxxxx; // []
L[444] = 9'b00_01_00011; // [AX]->T
L[445] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[446] = 9'b10_01_00101; // T->[AX]
L[447] = 9'bxx_xx_xxxxx; // []
L[448] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[449] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[450] = 9'bxx_xx_xxxxx; // []
L[451] = 9'bxx_xx_xxxxx; // []
L[452] = 9'bxx_xx_xxxxx; // []
L[453] = 9'bxx_xx_xxxxx; // []
L[454] = 9'bxx_xx_xxxxx; // []
L[455] = 9'bxx_xx_xxxxx; // []
L[456] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[457] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[458] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[459] = 9'bxx_xx_xxxxx; // []
L[460] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[461] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[462] = 9'bxx_xx_xxxxx; // []
L[463] = 9'bxx_xx_xxxxx; // []
L[464] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[465] = 9'b10_00_00011; // ['NO-OP', '']
L[466] = 9'bxx_xx_xxxxx; // []
L[467] = 9'bxx_xx_xxxxx; // []
L[468] = 9'bxx_xx_xxxxx; // []
L[469] = 9'bxx_xx_xxxxx; // []
L[470] = 9'bxx_xx_xxxxx; // []
L[471] = 9'bxx_xx_xxxxx; // []
L[472] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[473] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[474] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[475] = 9'bxx_xx_xxxxx; // []
L[476] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[477] = 9'b00_01_00011; // [AX]->T
L[478] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[479] = 9'b10_01_00101; // T->[AX]
L[480] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[481] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[482] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[483] = 9'bxx_xx_xxxxx; // []
L[484] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[485] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[486] = 9'bxx_xx_xxxxx; // []
L[487] = 9'bxx_xx_xxxxx; // []
L[488] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[489] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[490] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[491] = 9'bxx_xx_xxxxx; // []
L[492] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[493] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[494] = 9'bxx_xx_xxxxx; // []
L[495] = 9'bxx_xx_xxxxx; // []
L[496] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[497] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[498] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[499] = 9'bxx_xx_xxxxx; // []
L[500] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[501] = 9'b00_01_00011; // [AX]->T
L[502] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[503] = 9'b10_01_00101; // T->[AX]
L[504] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[505] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[506] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[507] = 9'bxx_xx_xxxxx; // []
L[508] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[509] = 9'b00_01_00011; // [AX]->T
L[510] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[511] = 9'b10_01_00101; // T->[AX]
L[512] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[513] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[514] = 9'b00_10_10000; // ['SP++', 'SP+1->SP', '[SP]->T,SP+1->SP']
L[515] = 9'b00_10_10110; // [SP]->P,SP+1->SP
L[516] = 9'b00_10_10000; // ['SP++', 'SP+1->SP', '[SP]->T,SP+1->SP']
L[517] = 9'b10_10_10011; // [SP]:T->PC
L[518] = 9'bxx_xx_xxxxx; // []
L[519] = 9'bxx_xx_xxxxx; // []
L[520] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[521] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[522] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[523] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[524] = 9'b00_01_01011; // [AX]->AH,T->AL
L[525] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[526] = 9'bxx_xx_xxxxx; // []
L[527] = 9'bxx_xx_xxxxx; // []
L[528] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[529] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[530] = 9'bxx_xx_xxxxx; // []
L[531] = 9'bxx_xx_xxxxx; // []
L[532] = 9'bxx_xx_xxxxx; // []
L[533] = 9'bxx_xx_xxxxx; // []
L[534] = 9'bxx_xx_xxxxx; // []
L[535] = 9'bxx_xx_xxxxx; // []
L[536] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[537] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[538] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[539] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[540] = 9'b00_01_01011; // [AX]->AH,T->AL
L[541] = 9'b00_01_00011; // [AX]->T
L[542] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[543] = 9'b10_01_00101; // T->[AX]
L[544] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[545] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[546] = 9'bxx_xx_xxxxx; // []
L[547] = 9'bxx_xx_xxxxx; // []
L[548] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[549] = 9'bxx_xx_xxxxx; // []
L[550] = 9'bxx_xx_xxxxx; // []
L[551] = 9'bxx_xx_xxxxx; // []
L[552] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[553] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[554] = 9'bxx_xx_xxxxx; // []
L[555] = 9'bxx_xx_xxxxx; // []
L[556] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[557] = 9'bxx_xx_xxxxx; // []
L[558] = 9'bxx_xx_xxxxx; // []
L[559] = 9'bxx_xx_xxxxx; // []
L[560] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[561] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[562] = 9'bxx_xx_xxxxx; // []
L[563] = 9'bxx_xx_xxxxx; // []
L[564] = 9'b00_01_00011; // [AX]->T
L[565] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[566] = 9'b10_01_00101; // T->[AX]
L[567] = 9'bxx_xx_xxxxx; // []
L[568] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[569] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[570] = 9'bxx_xx_xxxxx; // []
L[571] = 9'bxx_xx_xxxxx; // []
L[572] = 9'b00_01_00011; // [AX]->T
L[573] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[574] = 9'b10_01_00101; // T->[AX]
L[575] = 9'bxx_xx_xxxxx; // []
L[576] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[577] = 9'b00_00_00011; // [PC]->
L[578] = 9'b10_10_01110; // ALU(A)->[SP--]
L[579] = 9'bxx_xx_xxxxx; // []
L[580] = 9'bxx_xx_xxxxx; // []
L[581] = 9'bxx_xx_xxxxx; // []
L[582] = 9'bxx_xx_xxxxx; // []
L[583] = 9'bxx_xx_xxxxx; // []
L[584] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[585] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[586] = 9'bxx_xx_xxxxx; // []
L[587] = 9'bxx_xx_xxxxx; // []
L[588] = 9'bxx_xx_xxxxx; // []
L[589] = 9'bxx_xx_xxxxx; // []
L[590] = 9'bxx_xx_xxxxx; // []
L[591] = 9'bxx_xx_xxxxx; // []
L[592] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[593] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[594] = 9'bxx_xx_xxxxx; // []
L[595] = 9'bxx_xx_xxxxx; // []
L[596] = 9'bxx_xx_xxxxx; // []
L[597] = 9'bxx_xx_xxxxx; // []
L[598] = 9'bxx_xx_xxxxx; // []
L[599] = 9'bxx_xx_xxxxx; // []
L[600] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[601] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[602] = 9'bxx_xx_xxxxx; // []
L[603] = 9'bxx_xx_xxxxx; // []
L[604] = 9'bxx_xx_xxxxx; // []
L[605] = 9'bxx_xx_xxxxx; // []
L[606] = 9'bxx_xx_xxxxx; // []
L[607] = 9'bxx_xx_xxxxx; // []
L[608] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[609] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[610] = 9'bxx_xx_xxxxx; // []
L[611] = 9'bxx_xx_xxxxx; // []
L[612] = 9'b10_00_10011; // [PC]:T->PC
L[613] = 9'bxx_xx_xxxxx; // []
L[614] = 9'bxx_xx_xxxxx; // []
L[615] = 9'bxx_xx_xxxxx; // []
L[616] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[617] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[618] = 9'b11_00_00001; // [PC++]->AH
L[619] = 9'bxx_xx_xxxxx; // []
L[620] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[621] = 9'bxx_xx_xxxxx; // []
L[622] = 9'bxx_xx_xxxxx; // []
L[623] = 9'bxx_xx_xxxxx; // []
L[624] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[625] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[626] = 9'b11_00_00001; // [PC++]->AH
L[627] = 9'bxx_xx_xxxxx; // []
L[628] = 9'b00_01_00011; // [AX]->T
L[629] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[630] = 9'b10_01_00101; // T->[AX]
L[631] = 9'bxx_xx_xxxxx; // []
L[632] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[633] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[634] = 9'b11_00_00001; // [PC++]->AH
L[635] = 9'bxx_xx_xxxxx; // []
L[636] = 9'b00_01_00011; // [AX]->T
L[637] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[638] = 9'b10_01_00101; // T->[AX]
L[639] = 9'bxx_xx_xxxxx; // []
L[640] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[641] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[642] = 9'b11_00_10001; // PC+T->PC
L[643] = 9'bxx_xx_xxxxx; // []
L[644] = 9'b10_00_00011; // ['NO-OP', '']
L[645] = 9'bxx_xx_xxxxx; // []
L[646] = 9'bxx_xx_xxxxx; // []
L[647] = 9'bxx_xx_xxxxx; // []
L[648] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[649] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[650] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[651] = 9'b01_01_01100; // [AX]->AH,T+Y->AL
L[652] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[653] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[654] = 9'bxx_xx_xxxxx; // []
L[655] = 9'bxx_xx_xxxxx; // []
L[656] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[657] = 9'b10_00_00011; // ['NO-OP', '']
L[658] = 9'bxx_xx_xxxxx; // []
L[659] = 9'bxx_xx_xxxxx; // []
L[660] = 9'bxx_xx_xxxxx; // []
L[661] = 9'bxx_xx_xxxxx; // []
L[662] = 9'bxx_xx_xxxxx; // []
L[663] = 9'bxx_xx_xxxxx; // []
L[664] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[665] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[666] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[667] = 9'b00_01_01100; // [AX]->AH,T+Y->AL
L[668] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[669] = 9'b00_01_00011; // [AX]->T
L[670] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[671] = 9'b10_01_00101; // T->[AX]
L[672] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[673] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[674] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[675] = 9'bxx_xx_xxxxx; // []
L[676] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[677] = 9'bxx_xx_xxxxx; // []
L[678] = 9'bxx_xx_xxxxx; // []
L[679] = 9'bxx_xx_xxxxx; // []
L[680] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[681] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[682] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[683] = 9'bxx_xx_xxxxx; // []
L[684] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[685] = 9'bxx_xx_xxxxx; // []
L[686] = 9'bxx_xx_xxxxx; // []
L[687] = 9'bxx_xx_xxxxx; // []
L[688] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[689] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[690] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[691] = 9'bxx_xx_xxxxx; // []
L[692] = 9'b00_01_00011; // [AX]->T
L[693] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[694] = 9'b10_01_00101; // T->[AX]
L[695] = 9'bxx_xx_xxxxx; // []
L[696] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[697] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[698] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[699] = 9'bxx_xx_xxxxx; // []
L[700] = 9'b00_01_00011; // [AX]->T
L[701] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[702] = 9'b10_01_00101; // T->[AX]
L[703] = 9'bxx_xx_xxxxx; // []
L[704] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[705] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[706] = 9'bxx_xx_xxxxx; // []
L[707] = 9'bxx_xx_xxxxx; // []
L[708] = 9'bxx_xx_xxxxx; // []
L[709] = 9'bxx_xx_xxxxx; // []
L[710] = 9'bxx_xx_xxxxx; // []
L[711] = 9'bxx_xx_xxxxx; // []
L[712] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[713] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[714] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[715] = 9'bxx_xx_xxxxx; // []
L[716] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[717] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[718] = 9'bxx_xx_xxxxx; // []
L[719] = 9'bxx_xx_xxxxx; // []
L[720] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[721] = 9'b10_00_00011; // ['NO-OP', '']
L[722] = 9'bxx_xx_xxxxx; // []
L[723] = 9'bxx_xx_xxxxx; // []
L[724] = 9'bxx_xx_xxxxx; // []
L[725] = 9'bxx_xx_xxxxx; // []
L[726] = 9'bxx_xx_xxxxx; // []
L[727] = 9'bxx_xx_xxxxx; // []
L[728] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[729] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[730] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[731] = 9'bxx_xx_xxxxx; // []
L[732] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[733] = 9'b00_01_00011; // [AX]->T
L[734] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[735] = 9'b10_01_00101; // T->[AX]
L[736] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[737] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[738] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[739] = 9'bxx_xx_xxxxx; // []
L[740] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[741] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[742] = 9'bxx_xx_xxxxx; // []
L[743] = 9'bxx_xx_xxxxx; // []
L[744] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[745] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[746] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[747] = 9'bxx_xx_xxxxx; // []
L[748] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[749] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[750] = 9'bxx_xx_xxxxx; // []
L[751] = 9'bxx_xx_xxxxx; // []
L[752] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[753] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[754] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[755] = 9'bxx_xx_xxxxx; // []
L[756] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[757] = 9'b00_01_00011; // [AX]->T
L[758] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[759] = 9'b10_01_00101; // T->[AX]
L[760] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[761] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[762] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[763] = 9'bxx_xx_xxxxx; // []
L[764] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[765] = 9'b00_01_00011; // [AX]->T
L[766] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[767] = 9'b10_01_00101; // T->[AX]
L[768] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[769] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[770] = 9'b11_10_10000; // SP+1->SP
L[771] = 9'bxx_xx_xxxxx; // []
L[772] = 9'b00_10_10000; // ['SP++', 'SP+1->SP', '[SP]->T,SP+1->SP']
L[773] = 9'b00_10_10011; // [SP]:T->PC
L[774] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[775] = 9'bxx_xx_xxxxx; // []
L[776] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[777] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[778] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[779] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[780] = 9'b00_01_01011; // [AX]->AH,T->AL
L[781] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[782] = 9'bxx_xx_xxxxx; // []
L[783] = 9'bxx_xx_xxxxx; // []
L[784] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[785] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[786] = 9'bxx_xx_xxxxx; // []
L[787] = 9'bxx_xx_xxxxx; // []
L[788] = 9'bxx_xx_xxxxx; // []
L[789] = 9'bxx_xx_xxxxx; // []
L[790] = 9'bxx_xx_xxxxx; // []
L[791] = 9'bxx_xx_xxxxx; // []
L[792] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[793] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[794] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[795] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[796] = 9'b00_01_01011; // [AX]->AH,T->AL
L[797] = 9'b00_01_00011; // [AX]->T
L[798] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[799] = 9'b10_01_00101; // T->[AX]
L[800] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[801] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[802] = 9'bxx_xx_xxxxx; // []
L[803] = 9'bxx_xx_xxxxx; // []
L[804] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[805] = 9'bxx_xx_xxxxx; // []
L[806] = 9'bxx_xx_xxxxx; // []
L[807] = 9'bxx_xx_xxxxx; // []
L[808] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[809] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[810] = 9'bxx_xx_xxxxx; // []
L[811] = 9'bxx_xx_xxxxx; // []
L[812] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[813] = 9'bxx_xx_xxxxx; // []
L[814] = 9'bxx_xx_xxxxx; // []
L[815] = 9'bxx_xx_xxxxx; // []
L[816] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[817] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[818] = 9'bxx_xx_xxxxx; // []
L[819] = 9'bxx_xx_xxxxx; // []
L[820] = 9'b00_01_00011; // [AX]->T
L[821] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[822] = 9'b10_01_00101; // T->[AX]
L[823] = 9'bxx_xx_xxxxx; // []
L[824] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[825] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[826] = 9'bxx_xx_xxxxx; // []
L[827] = 9'bxx_xx_xxxxx; // []
L[828] = 9'b00_01_00011; // [AX]->T
L[829] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[830] = 9'b10_01_00101; // T->[AX]
L[831] = 9'bxx_xx_xxxxx; // []
L[832] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[833] = 9'b00_00_00011; // [PC]->
L[834] = 9'b00_10_10000; // ['SP++', 'SP+1->SP', '[SP]->T,SP+1->SP']
L[835] = 9'b10_10_00010; // ['ALU([SP])->A', '[SP]->P']
L[836] = 9'bxx_xx_xxxxx; // []
L[837] = 9'bxx_xx_xxxxx; // []
L[838] = 9'bxx_xx_xxxxx; // []
L[839] = 9'bxx_xx_xxxxx; // []
L[840] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[841] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[842] = 9'bxx_xx_xxxxx; // []
L[843] = 9'bxx_xx_xxxxx; // []
L[844] = 9'bxx_xx_xxxxx; // []
L[845] = 9'bxx_xx_xxxxx; // []
L[846] = 9'bxx_xx_xxxxx; // []
L[847] = 9'bxx_xx_xxxxx; // []
L[848] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[849] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[850] = 9'bxx_xx_xxxxx; // []
L[851] = 9'bxx_xx_xxxxx; // []
L[852] = 9'bxx_xx_xxxxx; // []
L[853] = 9'bxx_xx_xxxxx; // []
L[854] = 9'bxx_xx_xxxxx; // []
L[855] = 9'bxx_xx_xxxxx; // []
L[856] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[857] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[858] = 9'bxx_xx_xxxxx; // []
L[859] = 9'bxx_xx_xxxxx; // []
L[860] = 9'bxx_xx_xxxxx; // []
L[861] = 9'bxx_xx_xxxxx; // []
L[862] = 9'bxx_xx_xxxxx; // []
L[863] = 9'bxx_xx_xxxxx; // []
L[864] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[865] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[866] = 9'b00_00_00001; // [PC++]->AH
L[867] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[868] = 9'b10_01_10011; // [AX]:T->PC
L[869] = 9'bxx_xx_xxxxx; // []
L[870] = 9'bxx_xx_xxxxx; // []
L[871] = 9'bxx_xx_xxxxx; // []
L[872] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[873] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[874] = 9'b11_00_00001; // [PC++]->AH
L[875] = 9'bxx_xx_xxxxx; // []
L[876] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[877] = 9'bxx_xx_xxxxx; // []
L[878] = 9'bxx_xx_xxxxx; // []
L[879] = 9'bxx_xx_xxxxx; // []
L[880] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[881] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[882] = 9'b11_00_00001; // [PC++]->AH
L[883] = 9'bxx_xx_xxxxx; // []
L[884] = 9'b00_01_00011; // [AX]->T
L[885] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[886] = 9'b10_01_00101; // T->[AX]
L[887] = 9'bxx_xx_xxxxx; // []
L[888] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[889] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[890] = 9'b11_00_00001; // [PC++]->AH
L[891] = 9'bxx_xx_xxxxx; // []
L[892] = 9'b00_01_00011; // [AX]->T
L[893] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[894] = 9'b10_01_00101; // T->[AX]
L[895] = 9'bxx_xx_xxxxx; // []
L[896] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[897] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[898] = 9'b11_00_10001; // PC+T->PC
L[899] = 9'bxx_xx_xxxxx; // []
L[900] = 9'b10_00_00011; // ['NO-OP', '']
L[901] = 9'bxx_xx_xxxxx; // []
L[902] = 9'bxx_xx_xxxxx; // []
L[903] = 9'bxx_xx_xxxxx; // []
L[904] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[905] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[906] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[907] = 9'b01_01_01100; // [AX]->AH,T+Y->AL
L[908] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[909] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[910] = 9'bxx_xx_xxxxx; // []
L[911] = 9'bxx_xx_xxxxx; // []
L[912] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[913] = 9'b10_00_00011; // ['NO-OP', '']
L[914] = 9'bxx_xx_xxxxx; // []
L[915] = 9'bxx_xx_xxxxx; // []
L[916] = 9'bxx_xx_xxxxx; // []
L[917] = 9'bxx_xx_xxxxx; // []
L[918] = 9'bxx_xx_xxxxx; // []
L[919] = 9'bxx_xx_xxxxx; // []
L[920] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[921] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[922] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[923] = 9'b00_01_01100; // [AX]->AH,T+Y->AL
L[924] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[925] = 9'b00_01_00011; // [AX]->T
L[926] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[927] = 9'b10_01_00101; // T->[AX]
L[928] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[929] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[930] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[931] = 9'bxx_xx_xxxxx; // []
L[932] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[933] = 9'bxx_xx_xxxxx; // []
L[934] = 9'bxx_xx_xxxxx; // []
L[935] = 9'bxx_xx_xxxxx; // []
L[936] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[937] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[938] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[939] = 9'bxx_xx_xxxxx; // []
L[940] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[941] = 9'bxx_xx_xxxxx; // []
L[942] = 9'bxx_xx_xxxxx; // []
L[943] = 9'bxx_xx_xxxxx; // []
L[944] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[945] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[946] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[947] = 9'bxx_xx_xxxxx; // []
L[948] = 9'b00_01_00011; // [AX]->T
L[949] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[950] = 9'b10_01_00101; // T->[AX]
L[951] = 9'bxx_xx_xxxxx; // []
L[952] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[953] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[954] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[955] = 9'bxx_xx_xxxxx; // []
L[956] = 9'b00_01_00011; // [AX]->T
L[957] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[958] = 9'b10_01_00101; // T->[AX]
L[959] = 9'bxx_xx_xxxxx; // []
L[960] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[961] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[962] = 9'bxx_xx_xxxxx; // []
L[963] = 9'bxx_xx_xxxxx; // []
L[964] = 9'bxx_xx_xxxxx; // []
L[965] = 9'bxx_xx_xxxxx; // []
L[966] = 9'bxx_xx_xxxxx; // []
L[967] = 9'bxx_xx_xxxxx; // []
L[968] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[969] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[970] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[971] = 9'bxx_xx_xxxxx; // []
L[972] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[973] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[974] = 9'bxx_xx_xxxxx; // []
L[975] = 9'bxx_xx_xxxxx; // []
L[976] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[977] = 9'b10_00_00011; // ['NO-OP', '']
L[978] = 9'bxx_xx_xxxxx; // []
L[979] = 9'bxx_xx_xxxxx; // []
L[980] = 9'bxx_xx_xxxxx; // []
L[981] = 9'bxx_xx_xxxxx; // []
L[982] = 9'bxx_xx_xxxxx; // []
L[983] = 9'bxx_xx_xxxxx; // []
L[984] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[985] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[986] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[987] = 9'bxx_xx_xxxxx; // []
L[988] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[989] = 9'b00_01_00011; // [AX]->T
L[990] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[991] = 9'b10_01_00101; // T->[AX]
L[992] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[993] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[994] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[995] = 9'bxx_xx_xxxxx; // []
L[996] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[997] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[998] = 9'bxx_xx_xxxxx; // []
L[999] = 9'bxx_xx_xxxxx; // []
L[1000] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1001] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1002] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1003] = 9'bxx_xx_xxxxx; // []
L[1004] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1005] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1006] = 9'bxx_xx_xxxxx; // []
L[1007] = 9'bxx_xx_xxxxx; // []
L[1008] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1009] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1010] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1011] = 9'bxx_xx_xxxxx; // []
L[1012] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1013] = 9'b00_01_00011; // [AX]->T
L[1014] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1015] = 9'b10_01_00101; // T->[AX]
L[1016] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1017] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1018] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1019] = 9'bxx_xx_xxxxx; // []
L[1020] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1021] = 9'b00_01_00011; // [AX]->T
L[1022] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1023] = 9'b10_01_00101; // T->[AX]
L[1024] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1025] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1026] = 9'bxx_xx_xxxxx; // []
L[1027] = 9'bxx_xx_xxxxx; // []
L[1028] = 9'bxx_xx_xxxxx; // []
L[1029] = 9'bxx_xx_xxxxx; // []
L[1030] = 9'bxx_xx_xxxxx; // []
L[1031] = 9'bxx_xx_xxxxx; // []
L[1032] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1033] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1034] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[1035] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1036] = 9'b00_01_01011; // [AX]->AH,T->AL
L[1037] = 9'b10_01_00110; // ALU()->[AX]
L[1038] = 9'bxx_xx_xxxxx; // []
L[1039] = 9'bxx_xx_xxxxx; // []
L[1040] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1041] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1042] = 9'bxx_xx_xxxxx; // []
L[1043] = 9'bxx_xx_xxxxx; // []
L[1044] = 9'bxx_xx_xxxxx; // []
L[1045] = 9'bxx_xx_xxxxx; // []
L[1046] = 9'bxx_xx_xxxxx; // []
L[1047] = 9'bxx_xx_xxxxx; // []
L[1048] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1049] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1050] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[1051] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1052] = 9'b00_01_01011; // [AX]->AH,T->AL
L[1053] = 9'b10_01_00110; // ALU()->[AX]
L[1054] = 9'bxx_xx_xxxxx; // []
L[1055] = 9'bxx_xx_xxxxx; // []
L[1056] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1057] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1058] = 9'bxx_xx_xxxxx; // []
L[1059] = 9'bxx_xx_xxxxx; // []
L[1060] = 9'b10_01_00110; // ALU()->[AX]
L[1061] = 9'bxx_xx_xxxxx; // []
L[1062] = 9'bxx_xx_xxxxx; // []
L[1063] = 9'bxx_xx_xxxxx; // []
L[1064] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1065] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1066] = 9'bxx_xx_xxxxx; // []
L[1067] = 9'bxx_xx_xxxxx; // []
L[1068] = 9'b10_01_00110; // ALU()->[AX]
L[1069] = 9'bxx_xx_xxxxx; // []
L[1070] = 9'bxx_xx_xxxxx; // []
L[1071] = 9'bxx_xx_xxxxx; // []
L[1072] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1073] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1074] = 9'bxx_xx_xxxxx; // []
L[1075] = 9'bxx_xx_xxxxx; // []
L[1076] = 9'b10_01_00110; // ALU()->[AX]
L[1077] = 9'bxx_xx_xxxxx; // []
L[1078] = 9'bxx_xx_xxxxx; // []
L[1079] = 9'bxx_xx_xxxxx; // []
L[1080] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1081] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1082] = 9'bxx_xx_xxxxx; // []
L[1083] = 9'bxx_xx_xxxxx; // []
L[1084] = 9'b10_01_00110; // ALU()->[AX]
L[1085] = 9'bxx_xx_xxxxx; // []
L[1086] = 9'bxx_xx_xxxxx; // []
L[1087] = 9'bxx_xx_xxxxx; // []
L[1088] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1089] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1090] = 9'bxx_xx_xxxxx; // []
L[1091] = 9'bxx_xx_xxxxx; // []
L[1092] = 9'bxx_xx_xxxxx; // []
L[1093] = 9'bxx_xx_xxxxx; // []
L[1094] = 9'bxx_xx_xxxxx; // []
L[1095] = 9'bxx_xx_xxxxx; // []
L[1096] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1097] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1098] = 9'bxx_xx_xxxxx; // []
L[1099] = 9'bxx_xx_xxxxx; // []
L[1100] = 9'bxx_xx_xxxxx; // []
L[1101] = 9'bxx_xx_xxxxx; // []
L[1102] = 9'bxx_xx_xxxxx; // []
L[1103] = 9'bxx_xx_xxxxx; // []
L[1104] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1105] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1106] = 9'bxx_xx_xxxxx; // []
L[1107] = 9'bxx_xx_xxxxx; // []
L[1108] = 9'bxx_xx_xxxxx; // []
L[1109] = 9'bxx_xx_xxxxx; // []
L[1110] = 9'bxx_xx_xxxxx; // []
L[1111] = 9'bxx_xx_xxxxx; // []
L[1112] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1113] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1114] = 9'bxx_xx_xxxxx; // []
L[1115] = 9'bxx_xx_xxxxx; // []
L[1116] = 9'bxx_xx_xxxxx; // []
L[1117] = 9'bxx_xx_xxxxx; // []
L[1118] = 9'bxx_xx_xxxxx; // []
L[1119] = 9'bxx_xx_xxxxx; // []
L[1120] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1121] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1122] = 9'b11_00_00001; // [PC++]->AH
L[1123] = 9'bxx_xx_xxxxx; // []
L[1124] = 9'b10_01_00110; // ALU()->[AX]
L[1125] = 9'bxx_xx_xxxxx; // []
L[1126] = 9'bxx_xx_xxxxx; // []
L[1127] = 9'bxx_xx_xxxxx; // []
L[1128] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1129] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1130] = 9'b11_00_00001; // [PC++]->AH
L[1131] = 9'bxx_xx_xxxxx; // []
L[1132] = 9'b10_01_00110; // ALU()->[AX]
L[1133] = 9'bxx_xx_xxxxx; // []
L[1134] = 9'bxx_xx_xxxxx; // []
L[1135] = 9'bxx_xx_xxxxx; // []
L[1136] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1137] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1138] = 9'b11_00_00001; // [PC++]->AH
L[1139] = 9'bxx_xx_xxxxx; // []
L[1140] = 9'b10_01_00110; // ALU()->[AX]
L[1141] = 9'bxx_xx_xxxxx; // []
L[1142] = 9'bxx_xx_xxxxx; // []
L[1143] = 9'bxx_xx_xxxxx; // []
L[1144] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1145] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1146] = 9'b11_00_00001; // [PC++]->AH
L[1147] = 9'bxx_xx_xxxxx; // []
L[1148] = 9'b10_01_00110; // ALU()->[AX]
L[1149] = 9'bxx_xx_xxxxx; // []
L[1150] = 9'bxx_xx_xxxxx; // []
L[1151] = 9'bxx_xx_xxxxx; // []
L[1152] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1153] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1154] = 9'b11_00_10001; // PC+T->PC
L[1155] = 9'bxx_xx_xxxxx; // []
L[1156] = 9'b10_00_00011; // ['NO-OP', '']
L[1157] = 9'bxx_xx_xxxxx; // []
L[1158] = 9'bxx_xx_xxxxx; // []
L[1159] = 9'bxx_xx_xxxxx; // []
L[1160] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1161] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1162] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1163] = 9'b00_01_01100; // [AX]->AH,T+Y->AL
L[1164] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1165] = 9'b10_01_00110; // ALU()->[AX]
L[1166] = 9'bxx_xx_xxxxx; // []
L[1167] = 9'bxx_xx_xxxxx; // []
L[1168] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1169] = 9'b10_00_00011; // ['NO-OP', '']
L[1170] = 9'bxx_xx_xxxxx; // []
L[1171] = 9'bxx_xx_xxxxx; // []
L[1172] = 9'bxx_xx_xxxxx; // []
L[1173] = 9'bxx_xx_xxxxx; // []
L[1174] = 9'bxx_xx_xxxxx; // []
L[1175] = 9'bxx_xx_xxxxx; // []
L[1176] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1177] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1178] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1179] = 9'b00_01_01100; // [AX]->AH,T+Y->AL
L[1180] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1181] = 9'b10_01_00110; // ALU()->[AX]
L[1182] = 9'bxx_xx_xxxxx; // []
L[1183] = 9'bxx_xx_xxxxx; // []
L[1184] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1185] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1186] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1187] = 9'bxx_xx_xxxxx; // []
L[1188] = 9'b10_01_00110; // ALU()->[AX]
L[1189] = 9'bxx_xx_xxxxx; // []
L[1190] = 9'bxx_xx_xxxxx; // []
L[1191] = 9'bxx_xx_xxxxx; // []
L[1192] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1193] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1194] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1195] = 9'bxx_xx_xxxxx; // []
L[1196] = 9'b10_01_00110; // ALU()->[AX]
L[1197] = 9'bxx_xx_xxxxx; // []
L[1198] = 9'bxx_xx_xxxxx; // []
L[1199] = 9'bxx_xx_xxxxx; // []
L[1200] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1201] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1202] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1203] = 9'bxx_xx_xxxxx; // []
L[1204] = 9'b10_01_00110; // ALU()->[AX]
L[1205] = 9'bxx_xx_xxxxx; // []
L[1206] = 9'bxx_xx_xxxxx; // []
L[1207] = 9'bxx_xx_xxxxx; // []
L[1208] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1209] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1210] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1211] = 9'bxx_xx_xxxxx; // []
L[1212] = 9'b10_01_00110; // ALU()->[AX]
L[1213] = 9'bxx_xx_xxxxx; // []
L[1214] = 9'bxx_xx_xxxxx; // []
L[1215] = 9'bxx_xx_xxxxx; // []
L[1216] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1217] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1218] = 9'bxx_xx_xxxxx; // []
L[1219] = 9'bxx_xx_xxxxx; // []
L[1220] = 9'bxx_xx_xxxxx; // []
L[1221] = 9'bxx_xx_xxxxx; // []
L[1222] = 9'bxx_xx_xxxxx; // []
L[1223] = 9'bxx_xx_xxxxx; // []
L[1224] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1225] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1226] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1227] = 9'bxx_xx_xxxxx; // []
L[1228] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1229] = 9'b10_01_00110; // ALU()->[AX]
L[1230] = 9'bxx_xx_xxxxx; // []
L[1231] = 9'bxx_xx_xxxxx; // []
L[1232] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1233] = 9'b10_00_10010; // X->S
L[1234] = 9'bxx_xx_xxxxx; // []
L[1235] = 9'bxx_xx_xxxxx; // []
L[1236] = 9'bxx_xx_xxxxx; // []
L[1237] = 9'bxx_xx_xxxxx; // []
L[1238] = 9'bxx_xx_xxxxx; // []
L[1239] = 9'bxx_xx_xxxxx; // []
L[1240] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1241] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1242] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1243] = 9'bxx_xx_xxxxx; // []
L[1244] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1245] = 9'b10_01_00110; // ALU()->[AX]
L[1246] = 9'bxx_xx_xxxxx; // []
L[1247] = 9'bxx_xx_xxxxx; // []
L[1248] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1249] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1250] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1251] = 9'bxx_xx_xxxxx; // []
L[1252] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1253] = 9'b10_01_00110; // ALU()->[AX]
L[1254] = 9'bxx_xx_xxxxx; // []
L[1255] = 9'bxx_xx_xxxxx; // []
L[1256] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1257] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1258] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1259] = 9'bxx_xx_xxxxx; // []
L[1260] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1261] = 9'b10_01_00110; // ALU()->[AX]
L[1262] = 9'bxx_xx_xxxxx; // []
L[1263] = 9'bxx_xx_xxxxx; // []
L[1264] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1265] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1266] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1267] = 9'bxx_xx_xxxxx; // []
L[1268] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1269] = 9'b10_01_00110; // ALU()->[AX]
L[1270] = 9'bxx_xx_xxxxx; // []
L[1271] = 9'bxx_xx_xxxxx; // []
L[1272] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1273] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1274] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1275] = 9'bxx_xx_xxxxx; // []
L[1276] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1277] = 9'b10_01_00110; // ALU()->[AX]
L[1278] = 9'bxx_xx_xxxxx; // []
L[1279] = 9'bxx_xx_xxxxx; // []
L[1280] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1281] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[1282] = 9'bxx_xx_xxxxx; // []
L[1283] = 9'bxx_xx_xxxxx; // []
L[1284] = 9'bxx_xx_xxxxx; // []
L[1285] = 9'bxx_xx_xxxxx; // []
L[1286] = 9'bxx_xx_xxxxx; // []
L[1287] = 9'bxx_xx_xxxxx; // []
L[1288] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1289] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1290] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[1291] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1292] = 9'b00_01_01011; // [AX]->AH,T->AL
L[1293] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1294] = 9'bxx_xx_xxxxx; // []
L[1295] = 9'bxx_xx_xxxxx; // []
L[1296] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1297] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[1298] = 9'bxx_xx_xxxxx; // []
L[1299] = 9'bxx_xx_xxxxx; // []
L[1300] = 9'bxx_xx_xxxxx; // []
L[1301] = 9'bxx_xx_xxxxx; // []
L[1302] = 9'bxx_xx_xxxxx; // []
L[1303] = 9'bxx_xx_xxxxx; // []
L[1304] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1305] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1306] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[1307] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1308] = 9'b00_01_01011; // [AX]->AH,T->AL
L[1309] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1310] = 9'bxx_xx_xxxxx; // []
L[1311] = 9'bxx_xx_xxxxx; // []
L[1312] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1313] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1314] = 9'bxx_xx_xxxxx; // []
L[1315] = 9'bxx_xx_xxxxx; // []
L[1316] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1317] = 9'bxx_xx_xxxxx; // []
L[1318] = 9'bxx_xx_xxxxx; // []
L[1319] = 9'bxx_xx_xxxxx; // []
L[1320] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1321] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1322] = 9'bxx_xx_xxxxx; // []
L[1323] = 9'bxx_xx_xxxxx; // []
L[1324] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1325] = 9'bxx_xx_xxxxx; // []
L[1326] = 9'bxx_xx_xxxxx; // []
L[1327] = 9'bxx_xx_xxxxx; // []
L[1328] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1329] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1330] = 9'bxx_xx_xxxxx; // []
L[1331] = 9'bxx_xx_xxxxx; // []
L[1332] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1333] = 9'bxx_xx_xxxxx; // []
L[1334] = 9'bxx_xx_xxxxx; // []
L[1335] = 9'bxx_xx_xxxxx; // []
L[1336] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1337] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1338] = 9'bxx_xx_xxxxx; // []
L[1339] = 9'bxx_xx_xxxxx; // []
L[1340] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1341] = 9'bxx_xx_xxxxx; // []
L[1342] = 9'bxx_xx_xxxxx; // []
L[1343] = 9'bxx_xx_xxxxx; // []
L[1344] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1345] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1346] = 9'bxx_xx_xxxxx; // []
L[1347] = 9'bxx_xx_xxxxx; // []
L[1348] = 9'bxx_xx_xxxxx; // []
L[1349] = 9'bxx_xx_xxxxx; // []
L[1350] = 9'bxx_xx_xxxxx; // []
L[1351] = 9'bxx_xx_xxxxx; // []
L[1352] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1353] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[1354] = 9'bxx_xx_xxxxx; // []
L[1355] = 9'bxx_xx_xxxxx; // []
L[1356] = 9'bxx_xx_xxxxx; // []
L[1357] = 9'bxx_xx_xxxxx; // []
L[1358] = 9'bxx_xx_xxxxx; // []
L[1359] = 9'bxx_xx_xxxxx; // []
L[1360] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1361] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1362] = 9'bxx_xx_xxxxx; // []
L[1363] = 9'bxx_xx_xxxxx; // []
L[1364] = 9'bxx_xx_xxxxx; // []
L[1365] = 9'bxx_xx_xxxxx; // []
L[1366] = 9'bxx_xx_xxxxx; // []
L[1367] = 9'bxx_xx_xxxxx; // []
L[1368] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1369] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1370] = 9'bxx_xx_xxxxx; // []
L[1371] = 9'bxx_xx_xxxxx; // []
L[1372] = 9'bxx_xx_xxxxx; // []
L[1373] = 9'bxx_xx_xxxxx; // []
L[1374] = 9'bxx_xx_xxxxx; // []
L[1375] = 9'bxx_xx_xxxxx; // []
L[1376] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1377] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1378] = 9'b11_00_00001; // [PC++]->AH
L[1379] = 9'bxx_xx_xxxxx; // []
L[1380] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1381] = 9'bxx_xx_xxxxx; // []
L[1382] = 9'bxx_xx_xxxxx; // []
L[1383] = 9'bxx_xx_xxxxx; // []
L[1384] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1385] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1386] = 9'b11_00_00001; // [PC++]->AH
L[1387] = 9'bxx_xx_xxxxx; // []
L[1388] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1389] = 9'bxx_xx_xxxxx; // []
L[1390] = 9'bxx_xx_xxxxx; // []
L[1391] = 9'bxx_xx_xxxxx; // []
L[1392] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1393] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1394] = 9'b11_00_00001; // [PC++]->AH
L[1395] = 9'bxx_xx_xxxxx; // []
L[1396] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1397] = 9'bxx_xx_xxxxx; // []
L[1398] = 9'bxx_xx_xxxxx; // []
L[1399] = 9'bxx_xx_xxxxx; // []
L[1400] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1401] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1402] = 9'b11_00_00001; // [PC++]->AH
L[1403] = 9'bxx_xx_xxxxx; // []
L[1404] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1405] = 9'bxx_xx_xxxxx; // []
L[1406] = 9'bxx_xx_xxxxx; // []
L[1407] = 9'bxx_xx_xxxxx; // []
L[1408] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1409] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1410] = 9'b11_00_10001; // PC+T->PC
L[1411] = 9'bxx_xx_xxxxx; // []
L[1412] = 9'b10_00_00011; // ['NO-OP', '']
L[1413] = 9'bxx_xx_xxxxx; // []
L[1414] = 9'bxx_xx_xxxxx; // []
L[1415] = 9'bxx_xx_xxxxx; // []
L[1416] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1417] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1418] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1419] = 9'b01_01_01100; // [AX]->AH,T+Y->AL
L[1420] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1421] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1422] = 9'bxx_xx_xxxxx; // []
L[1423] = 9'bxx_xx_xxxxx; // []
L[1424] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1425] = 9'b10_00_00011; // ['NO-OP', '']
L[1426] = 9'bxx_xx_xxxxx; // []
L[1427] = 9'bxx_xx_xxxxx; // []
L[1428] = 9'bxx_xx_xxxxx; // []
L[1429] = 9'bxx_xx_xxxxx; // []
L[1430] = 9'bxx_xx_xxxxx; // []
L[1431] = 9'bxx_xx_xxxxx; // []
L[1432] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1433] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1434] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1435] = 9'b01_01_01100; // [AX]->AH,T+Y->AL
L[1436] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1437] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1438] = 9'bxx_xx_xxxxx; // []
L[1439] = 9'bxx_xx_xxxxx; // []
L[1440] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1441] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1442] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1443] = 9'bxx_xx_xxxxx; // []
L[1444] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1445] = 9'bxx_xx_xxxxx; // []
L[1446] = 9'bxx_xx_xxxxx; // []
L[1447] = 9'bxx_xx_xxxxx; // []
L[1448] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1449] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1450] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1451] = 9'bxx_xx_xxxxx; // []
L[1452] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1453] = 9'bxx_xx_xxxxx; // []
L[1454] = 9'bxx_xx_xxxxx; // []
L[1455] = 9'bxx_xx_xxxxx; // []
L[1456] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1457] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1458] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1459] = 9'bxx_xx_xxxxx; // []
L[1460] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1461] = 9'bxx_xx_xxxxx; // []
L[1462] = 9'bxx_xx_xxxxx; // []
L[1463] = 9'bxx_xx_xxxxx; // []
L[1464] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1465] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1466] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1467] = 9'bxx_xx_xxxxx; // []
L[1468] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1469] = 9'bxx_xx_xxxxx; // []
L[1470] = 9'bxx_xx_xxxxx; // []
L[1471] = 9'bxx_xx_xxxxx; // []
L[1472] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1473] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1474] = 9'bxx_xx_xxxxx; // []
L[1475] = 9'bxx_xx_xxxxx; // []
L[1476] = 9'bxx_xx_xxxxx; // []
L[1477] = 9'bxx_xx_xxxxx; // []
L[1478] = 9'bxx_xx_xxxxx; // []
L[1479] = 9'bxx_xx_xxxxx; // []
L[1480] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1481] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1482] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1483] = 9'bxx_xx_xxxxx; // []
L[1484] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1485] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1486] = 9'bxx_xx_xxxxx; // []
L[1487] = 9'bxx_xx_xxxxx; // []
L[1488] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1489] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1490] = 9'bxx_xx_xxxxx; // []
L[1491] = 9'bxx_xx_xxxxx; // []
L[1492] = 9'bxx_xx_xxxxx; // []
L[1493] = 9'bxx_xx_xxxxx; // []
L[1494] = 9'bxx_xx_xxxxx; // []
L[1495] = 9'bxx_xx_xxxxx; // []
L[1496] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1497] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1498] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1499] = 9'bxx_xx_xxxxx; // []
L[1500] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1501] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1502] = 9'bxx_xx_xxxxx; // []
L[1503] = 9'bxx_xx_xxxxx; // []
L[1504] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1505] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1506] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1507] = 9'bxx_xx_xxxxx; // []
L[1508] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1509] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1510] = 9'bxx_xx_xxxxx; // []
L[1511] = 9'bxx_xx_xxxxx; // []
L[1512] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1513] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1514] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1515] = 9'bxx_xx_xxxxx; // []
L[1516] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1517] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1518] = 9'bxx_xx_xxxxx; // []
L[1519] = 9'bxx_xx_xxxxx; // []
L[1520] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1521] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1522] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1523] = 9'bxx_xx_xxxxx; // []
L[1524] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1525] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1526] = 9'bxx_xx_xxxxx; // []
L[1527] = 9'bxx_xx_xxxxx; // []
L[1528] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1529] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1530] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1531] = 9'bxx_xx_xxxxx; // []
L[1532] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1533] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1534] = 9'bxx_xx_xxxxx; // []
L[1535] = 9'bxx_xx_xxxxx; // []
L[1536] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1537] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[1538] = 9'bxx_xx_xxxxx; // []
L[1539] = 9'bxx_xx_xxxxx; // []
L[1540] = 9'bxx_xx_xxxxx; // []
L[1541] = 9'bxx_xx_xxxxx; // []
L[1542] = 9'bxx_xx_xxxxx; // []
L[1543] = 9'bxx_xx_xxxxx; // []
L[1544] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1545] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1546] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[1547] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1548] = 9'b00_01_01011; // [AX]->AH,T->AL
L[1549] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1550] = 9'bxx_xx_xxxxx; // []
L[1551] = 9'bxx_xx_xxxxx; // []
L[1552] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1553] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1554] = 9'bxx_xx_xxxxx; // []
L[1555] = 9'bxx_xx_xxxxx; // []
L[1556] = 9'bxx_xx_xxxxx; // []
L[1557] = 9'bxx_xx_xxxxx; // []
L[1558] = 9'bxx_xx_xxxxx; // []
L[1559] = 9'bxx_xx_xxxxx; // []
L[1560] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1561] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1562] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[1563] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1564] = 9'b00_01_01011; // [AX]->AH,T->AL
L[1565] = 9'b00_01_00011; // [AX]->T
L[1566] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1567] = 9'b10_01_00101; // T->[AX]
L[1568] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1569] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1570] = 9'bxx_xx_xxxxx; // []
L[1571] = 9'bxx_xx_xxxxx; // []
L[1572] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1573] = 9'bxx_xx_xxxxx; // []
L[1574] = 9'bxx_xx_xxxxx; // []
L[1575] = 9'bxx_xx_xxxxx; // []
L[1576] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1577] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1578] = 9'bxx_xx_xxxxx; // []
L[1579] = 9'bxx_xx_xxxxx; // []
L[1580] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1581] = 9'bxx_xx_xxxxx; // []
L[1582] = 9'bxx_xx_xxxxx; // []
L[1583] = 9'bxx_xx_xxxxx; // []
L[1584] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1585] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1586] = 9'bxx_xx_xxxxx; // []
L[1587] = 9'bxx_xx_xxxxx; // []
L[1588] = 9'b00_01_00011; // [AX]->T
L[1589] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1590] = 9'b10_01_00101; // T->[AX]
L[1591] = 9'bxx_xx_xxxxx; // []
L[1592] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1593] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1594] = 9'bxx_xx_xxxxx; // []
L[1595] = 9'bxx_xx_xxxxx; // []
L[1596] = 9'b00_01_00011; // [AX]->T
L[1597] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1598] = 9'b10_01_00101; // T->[AX]
L[1599] = 9'bxx_xx_xxxxx; // []
L[1600] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1601] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1602] = 9'bxx_xx_xxxxx; // []
L[1603] = 9'bxx_xx_xxxxx; // []
L[1604] = 9'bxx_xx_xxxxx; // []
L[1605] = 9'bxx_xx_xxxxx; // []
L[1606] = 9'bxx_xx_xxxxx; // []
L[1607] = 9'bxx_xx_xxxxx; // []
L[1608] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1609] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[1610] = 9'bxx_xx_xxxxx; // []
L[1611] = 9'bxx_xx_xxxxx; // []
L[1612] = 9'bxx_xx_xxxxx; // []
L[1613] = 9'bxx_xx_xxxxx; // []
L[1614] = 9'bxx_xx_xxxxx; // []
L[1615] = 9'bxx_xx_xxxxx; // []
L[1616] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1617] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1618] = 9'bxx_xx_xxxxx; // []
L[1619] = 9'bxx_xx_xxxxx; // []
L[1620] = 9'bxx_xx_xxxxx; // []
L[1621] = 9'bxx_xx_xxxxx; // []
L[1622] = 9'bxx_xx_xxxxx; // []
L[1623] = 9'bxx_xx_xxxxx; // []
L[1624] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1625] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1626] = 9'bxx_xx_xxxxx; // []
L[1627] = 9'bxx_xx_xxxxx; // []
L[1628] = 9'bxx_xx_xxxxx; // []
L[1629] = 9'bxx_xx_xxxxx; // []
L[1630] = 9'bxx_xx_xxxxx; // []
L[1631] = 9'bxx_xx_xxxxx; // []
L[1632] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1633] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1634] = 9'b11_00_00001; // [PC++]->AH
L[1635] = 9'bxx_xx_xxxxx; // []
L[1636] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1637] = 9'bxx_xx_xxxxx; // []
L[1638] = 9'bxx_xx_xxxxx; // []
L[1639] = 9'bxx_xx_xxxxx; // []
L[1640] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1641] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1642] = 9'b11_00_00001; // [PC++]->AH
L[1643] = 9'bxx_xx_xxxxx; // []
L[1644] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1645] = 9'bxx_xx_xxxxx; // []
L[1646] = 9'bxx_xx_xxxxx; // []
L[1647] = 9'bxx_xx_xxxxx; // []
L[1648] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1649] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1650] = 9'b11_00_00001; // [PC++]->AH
L[1651] = 9'bxx_xx_xxxxx; // []
L[1652] = 9'b00_01_00011; // [AX]->T
L[1653] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1654] = 9'b10_01_00101; // T->[AX]
L[1655] = 9'bxx_xx_xxxxx; // []
L[1656] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1657] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1658] = 9'b11_00_00001; // [PC++]->AH
L[1659] = 9'bxx_xx_xxxxx; // []
L[1660] = 9'b00_01_00011; // [AX]->T
L[1661] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1662] = 9'b10_01_00101; // T->[AX]
L[1663] = 9'bxx_xx_xxxxx; // []
L[1664] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1665] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1666] = 9'b11_00_10001; // PC+T->PC
L[1667] = 9'bxx_xx_xxxxx; // []
L[1668] = 9'b10_00_00011; // ['NO-OP', '']
L[1669] = 9'bxx_xx_xxxxx; // []
L[1670] = 9'bxx_xx_xxxxx; // []
L[1671] = 9'bxx_xx_xxxxx; // []
L[1672] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1673] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1674] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1675] = 9'b01_01_01100; // [AX]->AH,T+Y->AL
L[1676] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1677] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1678] = 9'bxx_xx_xxxxx; // []
L[1679] = 9'bxx_xx_xxxxx; // []
L[1680] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1681] = 9'b10_00_00011; // ['NO-OP', '']
L[1682] = 9'bxx_xx_xxxxx; // []
L[1683] = 9'bxx_xx_xxxxx; // []
L[1684] = 9'bxx_xx_xxxxx; // []
L[1685] = 9'bxx_xx_xxxxx; // []
L[1686] = 9'bxx_xx_xxxxx; // []
L[1687] = 9'bxx_xx_xxxxx; // []
L[1688] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1689] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1690] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1691] = 9'b00_01_01100; // [AX]->AH,T+Y->AL
L[1692] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1693] = 9'b00_01_00011; // [AX]->T
L[1694] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1695] = 9'b10_01_00101; // T->[AX]
L[1696] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1697] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1698] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1699] = 9'bxx_xx_xxxxx; // []
L[1700] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[1701] = 9'bxx_xx_xxxxx; // []
L[1702] = 9'bxx_xx_xxxxx; // []
L[1703] = 9'bxx_xx_xxxxx; // []
L[1704] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1705] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1706] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1707] = 9'bxx_xx_xxxxx; // []
L[1708] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1709] = 9'bxx_xx_xxxxx; // []
L[1710] = 9'bxx_xx_xxxxx; // []
L[1711] = 9'bxx_xx_xxxxx; // []
L[1712] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1713] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1714] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1715] = 9'bxx_xx_xxxxx; // []
L[1716] = 9'b00_01_00011; // [AX]->T
L[1717] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1718] = 9'b10_01_00101; // T->[AX]
L[1719] = 9'bxx_xx_xxxxx; // []
L[1720] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1721] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1722] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1723] = 9'bxx_xx_xxxxx; // []
L[1724] = 9'b00_01_00011; // [AX]->T
L[1725] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1726] = 9'b10_01_00101; // T->[AX]
L[1727] = 9'bxx_xx_xxxxx; // []
L[1728] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1729] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1730] = 9'bxx_xx_xxxxx; // []
L[1731] = 9'bxx_xx_xxxxx; // []
L[1732] = 9'bxx_xx_xxxxx; // []
L[1733] = 9'bxx_xx_xxxxx; // []
L[1734] = 9'bxx_xx_xxxxx; // []
L[1735] = 9'bxx_xx_xxxxx; // []
L[1736] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1737] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1738] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1739] = 9'bxx_xx_xxxxx; // []
L[1740] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1741] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1742] = 9'bxx_xx_xxxxx; // []
L[1743] = 9'bxx_xx_xxxxx; // []
L[1744] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1745] = 9'b10_00_00011; // ['NO-OP', '']
L[1746] = 9'bxx_xx_xxxxx; // []
L[1747] = 9'bxx_xx_xxxxx; // []
L[1748] = 9'bxx_xx_xxxxx; // []
L[1749] = 9'bxx_xx_xxxxx; // []
L[1750] = 9'bxx_xx_xxxxx; // []
L[1751] = 9'bxx_xx_xxxxx; // []
L[1752] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1753] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1754] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1755] = 9'bxx_xx_xxxxx; // []
L[1756] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1757] = 9'b00_01_00011; // [AX]->T
L[1758] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1759] = 9'b10_01_00101; // T->[AX]
L[1760] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1761] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1762] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1763] = 9'bxx_xx_xxxxx; // []
L[1764] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1765] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[1766] = 9'bxx_xx_xxxxx; // []
L[1767] = 9'bxx_xx_xxxxx; // []
L[1768] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1769] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1770] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1771] = 9'bxx_xx_xxxxx; // []
L[1772] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1773] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1774] = 9'bxx_xx_xxxxx; // []
L[1775] = 9'bxx_xx_xxxxx; // []
L[1776] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1777] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1778] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1779] = 9'bxx_xx_xxxxx; // []
L[1780] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1781] = 9'b00_01_00011; // [AX]->T
L[1782] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1783] = 9'b10_01_00101; // T->[AX]
L[1784] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1785] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1786] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1787] = 9'bxx_xx_xxxxx; // []
L[1788] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1789] = 9'b00_01_00011; // [AX]->T
L[1790] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1791] = 9'b10_01_00101; // T->[AX]
L[1792] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1793] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[1794] = 9'bxx_xx_xxxxx; // []
L[1795] = 9'bxx_xx_xxxxx; // []
L[1796] = 9'bxx_xx_xxxxx; // []
L[1797] = 9'bxx_xx_xxxxx; // []
L[1798] = 9'bxx_xx_xxxxx; // []
L[1799] = 9'bxx_xx_xxxxx; // []
L[1800] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1801] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1802] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[1803] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1804] = 9'b00_01_01011; // [AX]->AH,T->AL
L[1805] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1806] = 9'bxx_xx_xxxxx; // []
L[1807] = 9'bxx_xx_xxxxx; // []
L[1808] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1809] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1810] = 9'bxx_xx_xxxxx; // []
L[1811] = 9'bxx_xx_xxxxx; // []
L[1812] = 9'bxx_xx_xxxxx; // []
L[1813] = 9'bxx_xx_xxxxx; // []
L[1814] = 9'bxx_xx_xxxxx; // []
L[1815] = 9'bxx_xx_xxxxx; // []
L[1816] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1817] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1818] = 9'b00_01_00111; // [AX]->?,AL+X->AL
L[1819] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1820] = 9'b00_01_01011; // [AX]->AH,T->AL
L[1821] = 9'b00_01_00011; // [AX]->T
L[1822] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1823] = 9'b10_01_00101; // T->[AX]
L[1824] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1825] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1826] = 9'bxx_xx_xxxxx; // []
L[1827] = 9'bxx_xx_xxxxx; // []
L[1828] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1829] = 9'bxx_xx_xxxxx; // []
L[1830] = 9'bxx_xx_xxxxx; // []
L[1831] = 9'bxx_xx_xxxxx; // []
L[1832] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1833] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1834] = 9'bxx_xx_xxxxx; // []
L[1835] = 9'bxx_xx_xxxxx; // []
L[1836] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1837] = 9'bxx_xx_xxxxx; // []
L[1838] = 9'bxx_xx_xxxxx; // []
L[1839] = 9'bxx_xx_xxxxx; // []
L[1840] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1841] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1842] = 9'bxx_xx_xxxxx; // []
L[1843] = 9'bxx_xx_xxxxx; // []
L[1844] = 9'b00_01_00011; // [AX]->T
L[1845] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1846] = 9'b10_01_00101; // T->[AX]
L[1847] = 9'bxx_xx_xxxxx; // []
L[1848] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1849] = 9'b11_00_00000; // ['[PC++]->AL', '[PC++]->T']
L[1850] = 9'bxx_xx_xxxxx; // []
L[1851] = 9'bxx_xx_xxxxx; // []
L[1852] = 9'b00_01_00011; // [AX]->T
L[1853] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1854] = 9'b10_01_00101; // T->[AX]
L[1855] = 9'bxx_xx_xxxxx; // []
L[1856] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1857] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1858] = 9'bxx_xx_xxxxx; // []
L[1859] = 9'bxx_xx_xxxxx; // []
L[1860] = 9'bxx_xx_xxxxx; // []
L[1861] = 9'bxx_xx_xxxxx; // []
L[1862] = 9'bxx_xx_xxxxx; // []
L[1863] = 9'bxx_xx_xxxxx; // []
L[1864] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1865] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[1866] = 9'bxx_xx_xxxxx; // []
L[1867] = 9'bxx_xx_xxxxx; // []
L[1868] = 9'bxx_xx_xxxxx; // []
L[1869] = 9'bxx_xx_xxxxx; // []
L[1870] = 9'bxx_xx_xxxxx; // []
L[1871] = 9'bxx_xx_xxxxx; // []
L[1872] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1873] = 9'b10_00_00011; // ['NO-OP', '']
L[1874] = 9'bxx_xx_xxxxx; // []
L[1875] = 9'bxx_xx_xxxxx; // []
L[1876] = 9'bxx_xx_xxxxx; // []
L[1877] = 9'bxx_xx_xxxxx; // []
L[1878] = 9'bxx_xx_xxxxx; // []
L[1879] = 9'bxx_xx_xxxxx; // []
L[1880] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1881] = 9'b10_00_01101; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
L[1882] = 9'bxx_xx_xxxxx; // []
L[1883] = 9'bxx_xx_xxxxx; // []
L[1884] = 9'bxx_xx_xxxxx; // []
L[1885] = 9'bxx_xx_xxxxx; // []
L[1886] = 9'bxx_xx_xxxxx; // []
L[1887] = 9'bxx_xx_xxxxx; // []
L[1888] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1889] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1890] = 9'b11_00_00001; // [PC++]->AH
L[1891] = 9'bxx_xx_xxxxx; // []
L[1892] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1893] = 9'bxx_xx_xxxxx; // []
L[1894] = 9'bxx_xx_xxxxx; // []
L[1895] = 9'bxx_xx_xxxxx; // []
L[1896] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1897] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1898] = 9'b11_00_00001; // [PC++]->AH
L[1899] = 9'bxx_xx_xxxxx; // []
L[1900] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1901] = 9'bxx_xx_xxxxx; // []
L[1902] = 9'bxx_xx_xxxxx; // []
L[1903] = 9'bxx_xx_xxxxx; // []
L[1904] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1905] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1906] = 9'b11_00_00001; // [PC++]->AH
L[1907] = 9'bxx_xx_xxxxx; // []
L[1908] = 9'b00_01_00011; // [AX]->T
L[1909] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1910] = 9'b10_01_00101; // T->[AX]
L[1911] = 9'bxx_xx_xxxxx; // []
L[1912] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1913] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1914] = 9'b11_00_00001; // [PC++]->AH
L[1915] = 9'bxx_xx_xxxxx; // []
L[1916] = 9'b00_01_00011; // [AX]->T
L[1917] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1918] = 9'b10_01_00101; // T->[AX]
L[1919] = 9'bxx_xx_xxxxx; // []
L[1920] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1921] = 9'b10_00_00000; // ['[PC++]->?', 'PC+1->PC', '']
L[1922] = 9'b11_00_10001; // PC+T->PC
L[1923] = 9'bxx_xx_xxxxx; // []
L[1924] = 9'b10_00_00011; // ['NO-OP', '']
L[1925] = 9'bxx_xx_xxxxx; // []
L[1926] = 9'bxx_xx_xxxxx; // []
L[1927] = 9'bxx_xx_xxxxx; // []
L[1928] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1929] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1930] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1931] = 9'b01_01_01100; // [AX]->AH,T+Y->AL
L[1932] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1933] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1934] = 9'bxx_xx_xxxxx; // []
L[1935] = 9'bxx_xx_xxxxx; // []
L[1936] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1937] = 9'b10_00_00011; // ['NO-OP', '']
L[1938] = 9'bxx_xx_xxxxx; // []
L[1939] = 9'bxx_xx_xxxxx; // []
L[1940] = 9'bxx_xx_xxxxx; // []
L[1941] = 9'bxx_xx_xxxxx; // []
L[1942] = 9'bxx_xx_xxxxx; // []
L[1943] = 9'bxx_xx_xxxxx; // []
L[1944] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1945] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1946] = 9'b00_01_01010; // [AX]->T,AL+1->AL
L[1947] = 9'b00_01_01100; // [AX]->AH,T+Y->AL
L[1948] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1949] = 9'b00_01_00011; // [AX]->T
L[1950] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1951] = 9'b10_01_00101; // T->[AX]
L[1952] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1953] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1954] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1955] = 9'bxx_xx_xxxxx; // []
L[1956] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[1957] = 9'bxx_xx_xxxxx; // []
L[1958] = 9'bxx_xx_xxxxx; // []
L[1959] = 9'bxx_xx_xxxxx; // []
L[1960] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1961] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1962] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1963] = 9'bxx_xx_xxxxx; // []
L[1964] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1965] = 9'bxx_xx_xxxxx; // []
L[1966] = 9'bxx_xx_xxxxx; // []
L[1967] = 9'bxx_xx_xxxxx; // []
L[1968] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1969] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1970] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1971] = 9'bxx_xx_xxxxx; // []
L[1972] = 9'b00_01_00011; // [AX]->T
L[1973] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1974] = 9'b10_01_00101; // T->[AX]
L[1975] = 9'bxx_xx_xxxxx; // []
L[1976] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1977] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1978] = 9'b11_01_00111; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL']
L[1979] = 9'bxx_xx_xxxxx; // []
L[1980] = 9'b00_01_00011; // [AX]->T
L[1981] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[1982] = 9'b10_01_00101; // T->[AX]
L[1983] = 9'bxx_xx_xxxxx; // []
L[1984] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1985] = 9'b10_00_00010; // ['[PC]->,ALU()->A', 'Setappropriateflags', 'ALU()->X,Y', 'ALU()->A']
L[1986] = 9'bxx_xx_xxxxx; // []
L[1987] = 9'bxx_xx_xxxxx; // []
L[1988] = 9'bxx_xx_xxxxx; // []
L[1989] = 9'bxx_xx_xxxxx; // []
L[1990] = 9'bxx_xx_xxxxx; // []
L[1991] = 9'bxx_xx_xxxxx; // []
L[1992] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1993] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[1994] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[1995] = 9'bxx_xx_xxxxx; // []
L[1996] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[1997] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[1998] = 9'bxx_xx_xxxxx; // []
L[1999] = 9'bxx_xx_xxxxx; // []
L[2000] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2001] = 9'b10_00_00011; // ['NO-OP', '']
L[2002] = 9'bxx_xx_xxxxx; // []
L[2003] = 9'bxx_xx_xxxxx; // []
L[2004] = 9'bxx_xx_xxxxx; // []
L[2005] = 9'bxx_xx_xxxxx; // []
L[2006] = 9'bxx_xx_xxxxx; // []
L[2007] = 9'bxx_xx_xxxxx; // []
L[2008] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2009] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2010] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[2011] = 9'bxx_xx_xxxxx; // []
L[2012] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[2013] = 9'b00_01_00011; // [AX]->T
L[2014] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[2015] = 9'b10_01_00101; // T->[AX]
L[2016] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2017] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2018] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[2019] = 9'bxx_xx_xxxxx; // []
L[2020] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[2021] = 9'b10_01_00011; // ['ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->']
L[2022] = 9'bxx_xx_xxxxx; // []
L[2023] = 9'bxx_xx_xxxxx; // []
L[2024] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2025] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2026] = 9'b01_00_01000; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[2027] = 9'bxx_xx_xxxxx; // []
L[2028] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[2029] = 9'b10_01_00010; // ['ALU([AX])->A', 'ALU([AX])->?']
L[2030] = 9'bxx_xx_xxxxx; // []
L[2031] = 9'bxx_xx_xxxxx; // []
L[2032] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2033] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2034] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[2035] = 9'bxx_xx_xxxxx; // []
L[2036] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[2037] = 9'b00_01_00011; // [AX]->T
L[2038] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[2039] = 9'b10_01_00101; // T->[AX]
L[2040] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2041] = 9'b00_00_00000; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T']
L[2042] = 9'b11_00_01000; // ['[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+Y->AL']
L[2043] = 9'bxx_xx_xxxxx; // []
L[2044] = 9'b00_01_01001; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
L[2045] = 9'b00_01_00011; // [AX]->T
L[2046] = 9'b00_01_00100; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
L[2047] = 9'b10_01_00101; // T->[AX]
  end  
  always @(posedge clk) if (reset) begin
    M <= 0; // Stupid XILINX inferral only allows 0 as reset value.
  end else if (ce) begin
    M <= L[{IR, State}];    
  end
endmodule

module MicroCodeTable(input clk, input ce, input reset, input [7:0] IR, input [2:0] State, output [37:0] Mout);
  wire [8:0] M;
  MicroCodeTableInner inner(clk, ce, reset, IR, State, M);
  reg [14:0] A[0:31];
  reg [18:0] B[0:255];
  initial begin
A[0] = 15'b_10__0_10101_0xx_01_00; // ['[PC++]', '[PC++]->AL', '[PC++]->?', '[PC++]->T', 'PC+1->PC', '']
A[1] = 15'b_xx__0_0xx11_0xx_01_00; // [PC++]->AH
A[2] = 15'b_xx__1_00000_0xx_00_00; // ['ALU([AX])->A', 'ALU([AX])->?', '[PC]->,ALU()->A', 'Setappropriateflags', 'ALU([SP])->A', '[SP]->P', 'ALU()->X,Y', 'ALU()->A']
A[3] = 15'b_10__0_00000_0xx_00_00; // ['[AX]->T', 'ALU([AX])->?', 'ALU([AX])->A', 'ALU([AX])->', '[PC]->', 'NO-OP', '[VECT]->T', '']
A[4] = 15'b_11__1_00000_100_00_00; // ['T->[AX],ALU(T)->T', 'T->[AX],ALU(T)->T:A']
A[5] = 15'b_xx__0_xxxxx_100_00_00; // T->[AX]
A[6] = 15'b_xx__0_00000_101_00_00; // ALU()->[AX]
A[7] = 15'b_0x__0_10000_0xx_00_00; // ['[AX]->?,AL+X->AL', '[AX]->?,AL+X/Y->AL', 'KEEP_AC']
A[8] = 15'b_xx__0_10011_0xx_01_00; // ['[PC++]->AH,AL+X/Y->AL', '[PC++]->AH,AL+X->AL', '[PC++]->AH,AL+Y->AL']
A[9] = 15'b_10__0_0xx10_0xx_00_00; // ['[AX]->?,AH+FIX->AH', '[AX]->T,AH+FIX->AH']
A[10] = 15'b_10__0_11000_0xx_00_00; // [AX]->T,AL+1->AL
A[11] = 15'b_xx__0_11111_0xx_00_00; // [AX]->AH,T->AL
A[12] = 15'b_xx__0_10011_0xx_00_00; // [AX]->AH,T+Y->AL
A[13] = 15'b_xx__1_xxxxx_0xx_01_00; // ['ALU([PC++])->A', 'ALU([PC++])->?', 'ALU([PC++])->Reg']
A[14] = 15'b_xx__0_xxxxx_101_00_11; // ALU(A)->[SP--]
A[15] = 15'b_xx__0_xxxxx_110_00_11; // P->[SP--]
A[16] = 15'b_10__0_xxxxx_0xx_00_10; // ['SP++', 'SP+1->SP', '[SP]->T,SP+1->SP']
A[17] = 15'b_xx__0_xxxxx_0xx_11_00; // PC+T->PC
A[18] = 15'b_xx__0_xxxxx_0xx_00_01; // X->S
A[19] = 15'b_xx__0_xxxxx_0xx_10_00; // ['[PC]:T->PC', '[AX]:T->PC', '[VECT]:T->PC', '[SP]:T->PC']
A[20] = 15'b_0x__0_xxxxx_111_00_11; // ['PCH->[SP--]', 'PCL->[SP--],', 'PCH->[SP--](KEEPAC)', 'PCL->[SP--](KEEPAC)']
A[21] = 15'b_xx__1_xxxxx_110_00_11; // P->[SP--]
A[22] = 15'b_xx__1_xxxxx_0xx_00_10; // [SP]->P,SP+1->SP
A[23] = 15'b_xx__x_xxxxx_xxx_xx_xx; // []
A[24] = 15'b_xx__x_xxxxx_xxx_xx_xx; // []
A[25] = 15'b_xx__x_xxxxx_xxx_xx_xx; // []
A[26] = 15'b_xx__x_xxxxx_xxx_xx_xx; // []
A[27] = 15'b_xx__x_xxxxx_xxx_xx_xx; // []
A[28] = 15'b_xx__x_xxxxx_xxx_xx_xx; // []
A[29] = 15'b_xx__x_xxxxx_xxx_xx_xx; // []
A[30] = 15'b_xx__x_xxxxx_xxx_xx_xx; // []
A[31] = 15'b_xx__x_xxxxx_xxx_xx_xx; // []
B[0] = 19'bxxxxxxxxxx0_000_00_010;
B[32] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[64] = 19'bxxxxxxxxxx0_000_00_100;
B[96] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[128] = 19'b011010x10x0_xxx_00_xxx;
B[160] = 19'bxx0010x10x0_100_00_001;
B[192] = 19'b010010x1100_000_00_001;
B[224] = 19'b100010x1100_000_00_001;
B[1] = 19'b000010x0001_010_00_001;
B[33] = 19'b000010x0011_010_00_001;
B[65] = 19'b000010x0101_010_00_001;
B[97] = 19'b000010x0111_010_00_001;
B[129] = 19'b001010x10x1_xxx_00_xxx;
B[161] = 19'bxx0010x10x1_010_00_001;
B[193] = 19'b000010x1101_000_00_001;
B[225] = 19'b000010x1111_010_00_001;
B[2] = 19'bxx0100010x0_000_00_001;
B[34] = 19'bxx0100110x0_000_00_001;
B[66] = 19'bxx0101010x0_000_00_001;
B[98] = 19'bxx0101110x0_000_00_001;
B[130] = 19'b101010x10x0_xxx_00_xxx;
B[162] = 19'bxx0010x10x0_001_00_001;
B[194] = 19'bxx0111010x0_000_00_001;
B[226] = 19'bxx0111110x0_000_00_001;
B[3] = 19'b00010000001_010_00_001;
B[35] = 19'b00010010011_010_00_001;
B[67] = 19'b00010100101_010_00_001;
B[99] = 19'b00010110111_010_00_001;
B[131] = 19'b111010x10x1_xxx_00_xxx;
B[163] = 19'bxx0010x10x1_011_00_001;
B[195] = 19'b00011101101_000_00_001;
B[227] = 19'b00011111111_010_00_001;
B[4] = 19'b000010x0000_xxx_00_xxx;
B[36] = 19'b000010x0010_000_00_001;
B[68] = 19'b000010x0100_xxx_00_xxx;
B[100] = 19'b000010x0110_xxx_00_xxx;
B[132] = 19'b011010x10x0_xxx_00_xxx;
B[164] = 19'bxx0010x10x0_100_00_001;
B[196] = 19'b010010x1100_000_00_001;
B[228] = 19'b100010x1100_000_00_001;
B[5] = 19'b000010x0001_010_00_001;
B[37] = 19'b000010x0011_010_00_001;
B[69] = 19'b000010x0101_010_00_001;
B[101] = 19'b000010x0111_010_00_001;
B[133] = 19'b001010x10x1_xxx_00_xxx;
B[165] = 19'bxx0010x10x1_010_00_001;
B[197] = 19'b000010x1101_000_00_001;
B[229] = 19'b000010x1111_010_00_001;
B[6] = 19'bxx0100010x0_000_00_001;
B[38] = 19'bxx0100110x0_000_00_001;
B[70] = 19'bxx0101010x0_000_00_001;
B[102] = 19'bxx0101110x0_000_00_001;
B[134] = 19'b101010x10x0_xxx_00_xxx;
B[166] = 19'bxx0010x10x0_001_00_001;
B[198] = 19'bxx0111010x0_000_00_001;
B[230] = 19'bxx0111110x0_000_00_001;
B[7] = 19'b00010000001_010_00_001;
B[39] = 19'b00010010011_010_00_001;
B[71] = 19'b00010100101_010_00_001;
B[103] = 19'b00010110111_010_00_001;
B[135] = 19'b111010x10x1_xxx_00_xxx;
B[167] = 19'bxx0010x10x1_011_00_001;
B[199] = 19'b00011101101_000_00_001;
B[231] = 19'b00011111111_010_00_001;
B[8] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[40] = 19'bxxxxxxxxxx0_000_00_100;
B[72] = 19'b001010x10x0_xxx_00_xxx;
B[104] = 19'bxx0010x10x0_010_00_001;
B[136] = 19'b011011010x0_100_00_001;
B[168] = 19'b001010x10x0_100_00_001;
B[200] = 19'b011011110x0_100_00_001;
B[232] = 19'b101011110x0_001_00_001;
B[9] = 19'b000010x0001_010_00_001;
B[41] = 19'b000010x0011_010_00_001;
B[73] = 19'b000010x0101_010_00_001;
B[105] = 19'b000010x0111_010_00_001;
B[137] = 19'b001010x10x1_xxx_00_xxx;
B[169] = 19'bxx0010x10x1_010_00_001;
B[201] = 19'b000010x1101_000_00_001;
B[233] = 19'b000010x1111_010_00_001;
B[10] = 19'b001000010x0_010_00_001;
B[42] = 19'b001000110x0_010_00_001;
B[74] = 19'b001001010x0_010_00_001;
B[106] = 19'b001001110x0_010_00_001;
B[138] = 19'b101010x10x0_010_00_001;
B[170] = 19'b001010x10x0_001_00_001;
B[202] = 19'b101011010x0_001_00_001;
B[234] = 19'bxx0111110x0_000_00_001;
B[11] = 19'b000010x0001_010_00_001;
B[43] = 19'b000010x0011_010_00_001;
B[75] = 19'b000010x0101_010_00_001;
B[107] = 19'b000010x0111_010_00_001;
B[139] = 19'b111010x10x1_xxx_00_xxx;
B[171] = 19'bxx0010x10x1_011_00_001;
B[203] = 19'b000010x1101_000_00_001;
B[235] = 19'b000010x1111_010_00_001;
B[12] = 19'b000010x0000_xxx_00_xxx;
B[44] = 19'b000010x0010_000_00_001;
B[76] = 19'bxxxxxxxxxx0_000_00_001;
B[108] = 19'bxxxxxxxxxx0_000_00_001;
B[140] = 19'b011010x10x0_xxx_00_xxx;
B[172] = 19'bxx0010x10x0_100_00_001;
B[204] = 19'b010010x1100_000_00_001;
B[236] = 19'b100010x1100_000_00_001;
B[13] = 19'b000010x0001_010_00_001;
B[45] = 19'b000010x0011_010_00_001;
B[77] = 19'b000010x0101_010_00_001;
B[109] = 19'b000010x0111_010_00_001;
B[141] = 19'b001010x10x1_xxx_00_xxx;
B[173] = 19'bxx0010x10x1_010_00_001;
B[205] = 19'b000010x1101_000_00_001;
B[237] = 19'b000010x1111_010_00_001;
B[14] = 19'bxx0100010x0_000_00_001;
B[46] = 19'bxx0100110x0_000_00_001;
B[78] = 19'bxx0101010x0_000_00_001;
B[110] = 19'bxx0101110x0_000_00_001;
B[142] = 19'b101010x10x0_xxx_00_xxx;
B[174] = 19'bxx0010x10x0_001_00_001;
B[206] = 19'bxx0111010x0_000_00_001;
B[238] = 19'bxx0111110x0_000_00_001;
B[15] = 19'b00010000001_010_00_001;
B[47] = 19'b00010010011_010_00_001;
B[79] = 19'b00010100101_010_00_001;
B[111] = 19'b00010110111_010_00_001;
B[143] = 19'b111010x10x1_xxx_00_xxx;
B[175] = 19'bxx0010x10x1_011_00_001;
B[207] = 19'b00011101101_000_00_001;
B[239] = 19'b00011111111_010_00_001;
B[16] = 19'bxxxxxxxxxx0_xxx_11_xxx;
B[48] = 19'bxxxxxxxxxx0_xxx_11_xxx;
B[80] = 19'bxxxxxxxxxx0_xxx_11_xxx;
B[112] = 19'bxxxxxxxxxx0_xxx_11_xxx;
B[144] = 19'b011010x10x0_xxx_11_xxx;
B[176] = 19'bxx0010x10x0_xxx_11_xxx;
B[208] = 19'bxxxxxxxxxx0_xxx_11_xxx;
B[240] = 19'bxxxxxxxxxx0_xxx_11_xxx;
B[17] = 19'b000010x0001_010_11_001;
B[49] = 19'b000010x0011_010_11_001;
B[81] = 19'b000010x0101_010_11_001;
B[113] = 19'b000010x0111_010_11_001;
B[145] = 19'b001010x10x1_xxx_11_xxx;
B[177] = 19'bxx0010x10x1_010_11_001;
B[209] = 19'b000010x1101_000_11_001;
B[241] = 19'b000010x1111_010_11_001;
B[18] = 19'bxx0100010x0_000_11_001;
B[50] = 19'bxx0100110x0_000_11_001;
B[82] = 19'bxx0101010x0_000_11_001;
B[114] = 19'bxx0101110x0_000_11_001;
B[146] = 19'b101010x10x0_xxx_11_xxx;
B[178] = 19'bxx0010x10x0_xxx_11_xxx;
B[210] = 19'bxx0111010x0_000_11_001;
B[242] = 19'bxx0111110x0_000_11_001;
B[19] = 19'b00010000001_010_11_001;
B[51] = 19'b00010010011_010_11_001;
B[83] = 19'b00010100101_010_11_001;
B[115] = 19'b00010110111_010_11_001;
B[147] = 19'b111010x10x1_xxx_11_xxx;
B[179] = 19'bxx0010x10x1_011_11_001;
B[211] = 19'b00011101101_000_11_001;
B[243] = 19'b00011111111_010_11_001;
B[20] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[52] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[84] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[116] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[148] = 19'b011010x10x0_xxx_00_xxx;
B[180] = 19'bxx0010x10x0_100_00_001;
B[212] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[244] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[21] = 19'b000010x0001_010_00_001;
B[53] = 19'b000010x0011_010_00_001;
B[85] = 19'b000010x0101_010_00_001;
B[117] = 19'b000010x0111_010_00_001;
B[149] = 19'b001010x10x1_xxx_00_xxx;
B[181] = 19'bxx0010x10x1_010_00_001;
B[213] = 19'b000010x1101_000_00_001;
B[245] = 19'b000010x1111_010_00_001;
B[22] = 19'bxx0100010x0_000_00_001;
B[54] = 19'bxx0100110x0_000_00_001;
B[86] = 19'bxx0101010x0_000_00_001;
B[118] = 19'bxx0101110x0_000_00_001;
B[150] = 19'b101010x10x0_xxx_10_xxx;
B[182] = 19'bxx0010x10x0_001_10_001;
B[214] = 19'bxx0111010x0_000_00_001;
B[246] = 19'bxx0111110x0_000_00_001;
B[23] = 19'b00010000001_010_00_001;
B[55] = 19'b00010010011_010_00_001;
B[87] = 19'b00010100101_010_00_001;
B[119] = 19'b00010110111_010_00_001;
B[151] = 19'b111010x10x1_xxx_10_xxx;
B[183] = 19'bxx0010x10x1_011_10_001;
B[215] = 19'b00011101101_000_00_001;
B[247] = 19'b00011111111_010_00_001;
B[24] = 19'bxxxxxxxxxx0_000_10_101;
B[56] = 19'bxxxxxxxxxx0_000_10_101;
B[88] = 19'bxxxxxxxxxx0_000_10_110;
B[120] = 19'bxxxxxxxxxx0_000_10_110;
B[152] = 19'b011010x10x0_010_10_001;
B[184] = 19'bxx1110x10x0_000_10_011;
B[216] = 19'bxxxxxxxxxx0_000_10_111;
B[248] = 19'bxxxxxxxxxx0_000_10_111;
B[25] = 19'b000010x0001_010_10_001;
B[57] = 19'b000010x0011_010_10_001;
B[89] = 19'b000010x0101_010_10_001;
B[121] = 19'b000010x0111_010_10_001;
B[153] = 19'b001010x10x1_xxx_10_xxx;
B[185] = 19'bxx0010x10x1_010_10_001;
B[217] = 19'b000010x1101_000_10_001;
B[249] = 19'b000010x1111_010_10_001;
B[26] = 19'bxx0100010x0_000_10_001;
B[58] = 19'bxx0100110x0_000_10_001;
B[90] = 19'bxx0101010x0_000_10_001;
B[122] = 19'bxx0101110x0_000_10_001;
B[154] = 19'b101010x10x0_xxx_10_xxx;
B[186] = 19'bxx1110x10x0_001_10_001;
B[218] = 19'bxx0111010x0_000_10_001;
B[250] = 19'bxx0111110x0_000_10_001;
B[27] = 19'b00010000001_010_10_001;
B[59] = 19'b00010010011_010_10_001;
B[91] = 19'b00010100101_010_10_001;
B[123] = 19'b00010110111_010_10_001;
B[155] = 19'b111010x10x1_xxx_10_xxx;
B[187] = 19'bxx0010x10x1_xxx_10_xxx;
B[219] = 19'b00011101101_000_10_001;
B[251] = 19'b00011111111_010_10_001;
B[28] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[60] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[92] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[124] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[156] = 19'b011010x10x0_xxx_00_xxx;
B[188] = 19'bxx0010x10x0_100_00_001;
B[220] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[252] = 19'bxxxxxxxxxx0_xxx_00_xxx;
B[29] = 19'b000010x0001_010_00_001;
B[61] = 19'b000010x0011_010_00_001;
B[93] = 19'b000010x0101_010_00_001;
B[125] = 19'b000010x0111_010_00_001;
B[157] = 19'b001010x10x1_xxx_00_xxx;
B[189] = 19'bxx0010x10x1_010_00_001;
B[221] = 19'b000010x1101_000_00_001;
B[253] = 19'b000010x1111_010_00_001;
B[30] = 19'bxx0100010x0_000_00_001;
B[62] = 19'bxx0100110x0_000_00_001;
B[94] = 19'bxx0101010x0_000_00_001;
B[126] = 19'bxx0101110x0_000_00_001;
B[158] = 19'b101010x10x0_xxx_10_xxx;
B[190] = 19'bxx0010x10x0_001_10_001;
B[222] = 19'bxx0111010x0_000_00_001;
B[254] = 19'bxx0111110x0_000_00_001;
B[31] = 19'b00010000001_010_00_001;
B[63] = 19'b00010010011_010_00_001;
B[95] = 19'b00010100101_010_00_001;
B[127] = 19'b00010110111_010_00_001;
B[159] = 19'b111010x10x1_xxx_10_xxx;
B[191] = 19'bxx0010x10x1_011_10_001;
B[223] = 19'b00011101101_000_00_001;
B[255] = 19'b00011111111_010_00_001;
  end  
  wire [14:0] R = A[M[4:0]];
  reg [18:0] AluFlags;
  always @(posedge clk) if (reset) begin
    AluFlags <= 0;
  end else if (ce) begin  
    AluFlags <= B[IR];
  end

  assign Mout = {AluFlags,// 19
                 M[8:7],  // NextState // 2
                 R[14:13],// LoadT     // 2
                 R[12],   // FlagCtrl  // 1
                 R[11:7], // AddrCtrl  // 5
                 R[6:4],  // MemWrite  // 3
                 M[6:5],  // AddrBus   // 2
                 R[3:2],  // LoadPC    // 2
                 R[1:0]   // LoadSP    // 2
                 };
endmodule

module sigma_delta_dac(
   output    reg             DACout,   //Average Output feeding analog lowpass
   input          [MSBI:0]    DACin,   //DAC input (excess 2**MSBI)
   input                  CLK,
   input                  CEN,
   input                   RESET
);

parameter MSBI = 7;

reg [MSBI+2:0] DeltaAdder;   //Output of Delta Adder
reg [MSBI+2:0] SigmaAdder;   //Output of Sigma Adder
reg [MSBI+2:0] SigmaLatch;   //Latches output of Sigma Adder
reg [MSBI+2:0] DeltaB;      //B input of Delta Adder

always @ (*)
   DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1);

always @(*)
   DeltaAdder = DACin + DeltaB;
   
always @(*)
   SigmaAdder = DeltaAdder + SigmaLatch;
   
always @(posedge CLK)
    begin
      SigmaLatch <= SigmaAdder;
      DACout <= SigmaLatch[MSBI+2];
   end
endmodule // Copyright (c) 2012-2013 Ludvig Strigeus
// Copyright (c) 2017 David Shah
// This program is GPL Licensed. See COPYING for the full license.

`timescale 1ns / 1ps

module top (  
	// clock input
  input clock_16,
  output led0, led1,
  
  // VGA
  output         vga_HS, // VGA H_SYNC
  output         vga_VS, // VGA V_SYNC
  output [ 3:0]  vga_R, // VGA Red[3:0]
  output [ 3:0]  vga_G, // VGA Green[3:0]
  output [ 3:0]  vga_B, // VGA Blue[3:0]
                                                                                                    

  // audio
  output           audio_o,
  
  // joystick
  output joy_strobe, joy_clock,
  input joy_data,
  
  // flashmem
  output flash_sck,
  output flash_csn,
  output flash_mosi,
  input flash_miso,
  
  input [4:0] buttons
  
);
	wire clock;

wire [4:0] sel_btn;


assign sel_btn = buttons;


  wire scandoubler_disable;

  reg clock_locked;
  wire locked_pre;
  always @(posedge clock)
    clock_locked <= locked_pre;
  
  wire [8:0] cycle;
  wire [8:0] scanline;
  wire [15:0] sample;
  wire [5:0] color;
  
  wire load_done;
  wire [21:0] memory_addr;
  wire memory_read_cpu, memory_read_ppu;
  wire memory_write;
  wire [7:0] memory_din_cpu, memory_din_ppu;
  wire [7:0] memory_dout;
  
  wire [31:0] mapper_flags;
  
  pll pll_i (
  	.clock_in(clock_16),
  	.clock_out(clock),
  	.locked(locked_pre)
  );  
  
  assign led0 = memory_addr[0];
  assign led1 = !load_done;
  
  wire sys_reset = !clock_locked;
  reg reload;
  reg [2:0] last_pressed;
  reg [3:0] btn_dly;
  always @ ( posedge clock ) begin
    //Detect button release and trigger reload
    btn_dly <= sel_btn[3:0];
    if (sel_btn[3:0] == 4'b1111 && btn_dly != 4'b1111)
      reload <= 1'b1;
    else
      reload <= 1'b0;
    // Button 4 is a "shift"
    if(!sel_btn[0])
      last_pressed <= {!sel_btn[4], 2'b00};
    else if(!sel_btn[1])
      last_pressed <= {!sel_btn[4], 2'b01};
    else if(!sel_btn[2])
      last_pressed <= {!sel_btn[4], 2'b10};
    else if(!sel_btn[3])
      last_pressed <= {!sel_btn[4], 2'b11};
  end
  
  main_mem mem (
    .clock(clock),
    .reset(sys_reset),
    .reload(reload),
    .index({1'b0, last_pressed}),
    .load_done(load_done),
    .flags_out(mapper_flags),
    //NES interface
    .mem_addr(memory_addr),
    .mem_rd_cpu(memory_read_cpu),
    .mem_rd_ppu(memory_read_ppu),
    .mem_wr(memory_write),
    .mem_q_cpu(memory_din_cpu),
    .mem_q_ppu(memory_din_ppu),
    .mem_d(memory_dout),
    
    //Flash load interface
    .flash_csn(flash_csn),
    .flash_sck(flash_sck),
    .flash_mosi(flash_mosi),
    .flash_miso(flash_miso)
  );
  
  wire reset_nes = !load_done || sys_reset;
  reg [1:0] nes_ce;
  wire run_nes = (nes_ce == 3);	// keep running even when reset, so that the reset can actually do its job!
  
  wire run_nes_g = run_nes;
  
  // NES is clocked at every 4th cycle.
  always @(posedge clock)
    nes_ce <= nes_ce + 1;
  
  wire [31:0] dbgadr;
  wire [1:0] dbgctr;
  
  NES nes(clock, reset_nes, run_nes_g,
          mapper_flags,
          sample, color,
          joy_strobe, joy_clock, {3'b0,!joy_data},
          5'b11111,  // enable all channels
          memory_addr,
          memory_read_cpu, memory_din_cpu,
          memory_read_ppu, memory_din_ppu,
          memory_write, memory_dout,
          cycle, scanline,
          dbgadr,
          dbgctr);


video video (
	.clk(clock),
		
	.color(color),
	.count_v(scanline),
	.count_h(cycle),
	.mode(1'b0),
	.smoothing(1'b1),
	.scanlines(1'b1),
	.overscan(1'b1),
	.palette(1'b0),
	
	.VGA_HS(vga_HS),
	.VGA_VS(vga_VS),
	.VGA_R(vga_R),
	.VGA_G(vga_G),
	.VGA_B(vga_B)
	
);

wire audio;
sigma_delta_dac sigma_delta_dac (
	.DACout(audio),
	.DACin(sample[15:8]),
	.CLK(clock),
	.RESET(reset_nes),
  .CEN(run_nes)
);
assign audio_o = audio;

endmodule
// Copyright (c) 2012-2013 Ludvig Strigeus
// This program is GPL Licensed. See COPYING for the full license.

// No mapper chip
module MMC0(input clk, input ce,
            input [31:0] flags,
            input [15:0] prg_ain, output [21:0] prg_aout,
            input prg_read, prg_write,                   // Read / write signals
            input [7:0] prg_din,
            output prg_allow,                            // Enable access to memory for the specified operation.
            input [13:0] chr_ain, output [21:0] chr_aout,
            output chr_allow,                      // Allow write
            output vram_a10,                             // Value for A10 address line
            output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.
  assign prg_aout = {7'b00_0000_0, prg_ain[14:0]};
  assign prg_allow = prg_ain[15] && !prg_write;
  assign chr_allow = flags[15];
  assign chr_aout = {9'b10_0000_000, chr_ain[12:0]};
  assign vram_ce = chr_ain[13];
  assign vram_a10 = flags[14] ? chr_ain[10] : chr_ain[11];
endmodule

// MMC1 mapper chip. Maps prg or chr addresses into a linear address.
// If vram_ce is set, {vram_a10, chr_aout[9:0]} are used to access the NES internal VRAM instead.
module MMC1(input clk, input ce, input reset,
            input [31:0] flags,
            input [15:0] prg_ain, output [21:0] prg_aout,
            input prg_read, prg_write,                   // Read / write signals
            input [7:0] prg_din,
            output prg_allow,                            // Enable access to memory for the specified operation.
            input [13:0] chr_ain, output [21:0] chr_aout,
            output chr_allow,                      // Allow write
            output vram_a10,                             // Value for A10 address line
            output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.
  reg [4:0] shift;
  
// CPPMM
// |||||
// |||++- Mirroring (0: one-screen, lower bank; 1: one-screen, upper bank;
// |||               2: vertical; 3: horizontal)
// |++--- PRG ROM bank mode (0, 1: switch 32 KB at $8000, ignoring low bit of bank number;
// |                         2: fix first bank at $8000 and switch 16 KB bank at $C000;
// |                         3: fix last bank at $C000 and switch 16 KB bank at $8000)
// +----- CHR ROM bank mode (0: switch 8 KB at a time; 1: switch two separate 4 KB banks)
  reg [4:0] control;

// CCCCC
// |||||
// +++++- Select 4 KB or 8 KB CHR bank at PPU $0000 (low bit ignored in 8 KB mode)
  reg [4:0] chr_bank_0;

// CCCCC
// |||||
// +++++- Select 4 KB CHR bank at PPU $1000 (ignored in 8 KB mode)
  reg [4:0] chr_bank_1;
  
// RPPPP
// |||||
// |++++- Select 16 KB PRG ROM bank (low bit ignored in 32 KB mode)
// +----- PRG RAM chip enable (0: enabled; 1: disabled; ignored on MMC1A)
  reg [4:0] prg_bank;

  reg delay_ctrl;	// used to prevent fast-write to the control register

  wire [2:0] prg_size = flags[10:8];
   
  // Update shift register
  always @(posedge clk) if (reset) begin
		shift <= 5'b10000;
		control <= 5'b0_11_00;
		chr_bank_0 <= 0;
		chr_bank_1 <= 0;
		prg_bank <= 5'b00000;
		delay_ctrl <= 0;
  end else if (ce) begin
    if (!prg_write)
		delay_ctrl <= 1'b0;
    if (prg_write && prg_ain[15] && !delay_ctrl) begin
	   delay_ctrl <= 1'b1;
      if (prg_din[7]) begin
        shift <= 5'b10000;
        control <= control | 5'b0_11_00;
//        $write("MMC1 RESET!\n");
      end else begin
        if (shift[0]) begin
//          $write("MMC1 WRITE %X to %X!\n", {prg_din[0], shift[4:1]}, prg_ain);
          casez(prg_ain[14:13])
          0: control    <= {prg_din[0], shift[4:1]};
          1: chr_bank_0 <= {prg_din[0], shift[4:1]};
          2: chr_bank_1 <= {prg_din[0], shift[4:1]};
          3: prg_bank   <= {prg_din[0], shift[4:1]};
          endcase
          shift <= 5'b10000;
        end else begin
          shift <= {prg_din[0], shift[4:1]};
        end
      end
    end
  end
  
  // The PRG bank to load. Each increment here is 16kb. So valid values are 0..15.
  // prg_ain[14] selects bank0 ($8000) or bank1 ($C000)
  reg [3:0] prgsel;  
  always @* begin
    casez({control[3:2], prg_ain[14]})
    3'b0?_?: prgsel = {prg_bank[3:1], prg_ain[14]};	// Swap 32Kb
    3'b10_0: prgsel = 4'b0000;								// Swap 16Kb at $C000 with access at $8000, so select page 0 (hardcoded)
    3'b10_1: prgsel = prg_bank[3:0];						// Swap 16Kb at $C000 with $C000 access, so select page based on prg_bank (register 3)
    3'b11_0: prgsel = prg_bank[3:0];						// Swap 16Kb at $8000 with $8000 access, so select page based on prg_bank (register 3)
    3'b11_1: prgsel = 4'b1111;								// Swap 16Kb at $8000 with $C000 access, so select last page (hardcoded)
    endcase
  end
  
  // The CHR bank to load. Each increment here is 4 kb. So valid values are 0..31.
  reg [4:0] chrsel;
  always @* begin
    casez({control[4], chr_ain[12]})
    2'b0_?: chrsel = {chr_bank_0[4:1], chr_ain[12]};
    2'b1_0: chrsel = chr_bank_0;
    2'b1_1: chrsel = chr_bank_1;
    endcase
  end
  assign chr_aout = {5'b100_00, chrsel, chr_ain[11:0]};
  wire [21:0] prg_aout_tmp = prg_size == 5 ? {3'b000, chrsel[4], prgsel, prg_ain[13:0]}	// for large PRG ROM, CHR A16 selects the 256KB PRG bank
														 : {4'b00_00, prgsel, prg_ain[13:0]};
  
  // The a10 VRAM address line. (Used for mirroring)
  reg vram_a10_t;
  always @* begin
    casez(control[1:0])
    2'b00: vram_a10_t = 0;             // One screen, lower bank
    2'b01: vram_a10_t = 1;             // One screen, upper bank
    2'b10: vram_a10_t = chr_ain[10];   // One screen, vertical
    2'b11: vram_a10_t = chr_ain[11];   // One screen, horizontal
    endcase
  end
  assign vram_a10 = vram_a10_t;
  assign vram_ce = chr_ain[13];
  
  wire prg_is_ram = prg_ain >= 'h6000 && prg_ain < 'h8000;
  assign prg_allow = prg_ain[15] && !prg_write || prg_is_ram;
  wire [21:0] prg_ram = {9'b11_1100_000, prg_ain[12:0]};
  
  assign prg_aout = prg_is_ram ? prg_ram : prg_aout_tmp;
  assign chr_allow = flags[15];
endmodule

// MMC2 mapper chip. PRG ROM: 128kB. Bank Size: 8kB. CHR ROM: 128kB
module MMC2(input clk, input ce, input reset,
            input [31:0] flags,
            input [15:0] prg_ain, output [21:0] prg_aout,
            input prg_read, prg_write,                   // Read / write signals
            input [7:0] prg_din,
            output prg_allow,                            // Enable access to memory for the specified operation.
            input chr_read, input [13:0] chr_ain, output [21:0] chr_aout,
            output chr_allow,                      // Allow write
            output vram_a10,                             // Value for A10 address line
            output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.

// PRG ROM bank select ($A000-$AFFF)
// 7  bit  0
// ---- ----
// xxxx PPPP
//      ||||
//      ++++- Select 8 KB PRG ROM bank for CPU $8000-$9FFF
  reg [3:0] prg_bank;

// CHR ROM $FD/0000 bank select ($B000-$BFFF)
// 7  bit  0
// ---- ----
// xxxC CCCC
//    | ||||
//    +-++++- Select 4 KB CHR ROM bank for PPU $0000-$0FFF
//            used when latch 0 = $FD
  reg   [4:0] chr_bank_0a;

// CHR ROM $FE/0000 bank select ($C000-$CFFF)
// 7  bit  0
// ---- ----
// xxxC CCCC
//    | ||||
//    +-++++- Select 4 KB CHR ROM bank for PPU $0000-$0FFF
//            used when latch 0 = $FE
   reg [4:0] chr_bank_0b;
   
// CHR ROM $FD/1000 bank select ($D000-$DFFF)
// 7  bit  0
// ---- ----
// xxxC CCCC
//    | ||||
//    +-++++- Select 4 KB CHR ROM bank for PPU $1000-$1FFF
//            used when latch 1 = $FD
  reg [4:0] chr_bank_1a;
   
// CHR ROM $FE/1000 bank select ($E000-$EFFF)
// 7  bit  0
// ---- ----
// xxxC CCCC
//    | ||||
//    +-++++- Select 4 KB CHR ROM bank for PPU $1000-$1FFF
//            used when latch 1 = $FE
  reg [4:0] chr_bank_1b; 
  
// Mirroring ($F000-$FFFF)
// 7  bit  0
// ---- ----
// xxxx xxxM
//         |
//         +- Select nametable mirroring (0: vertical; 1: horizontal)  
  reg mirroring;
  
  reg latch_0, latch_1;
	
  // Update registers
  always @(posedge clk) if (ce) begin
    if (prg_write && prg_ain[15]) begin
      case(prg_ain[14:12])
      2: prg_bank <= prg_din[3:0];     // $A000
      3: chr_bank_0a <= prg_din[4:0];  // $B000
      4: chr_bank_0b <= prg_din[4:0];  // $C000
      5: chr_bank_1a <= prg_din[4:0];  // $D000
      6: chr_bank_1b <= prg_din[4:0];  // $E000
      7: mirroring <=  prg_din[0];     // $F000
      endcase
    end
  end
  
// PPU reads $0FD8: latch 0 is set to $FD for subsequent reads
// PPU reads $0FE8: latch 0 is set to $FE for subsequent reads
// PPU reads $1FD8 through $1FDF: latch 1 is set to $FD for subsequent reads
// PPU reads $1FE8 through $1FEF: latch 1 is set to $FE for subsequent reads
  always @(posedge clk) if (ce && chr_read) begin
    latch_0 <= (chr_ain & 14'h3fff) == 14'h0fd8 ? 0 : (chr_ain & 14'h3fff) == 14'h0fe8 ? 1 : latch_0;
    latch_1 <= (chr_ain & 14'h3ff8) == 14'h1fd8 ? 0 : (chr_ain & 14'h3ff8) == 14'h1fe8 ? 1 : latch_1;
  end
  
  // The PRG bank to load. Each increment here is 8kb. So valid values are 0..15.
  reg [3:0] prgsel;
  always @* begin
    casez(prg_ain[14:13])
    2'b00:   prgsel = prg_bank;
    default: prgsel = {2'b11, prg_ain[14:13]};
    endcase
  end
  assign prg_aout = {5'b00_000, prgsel, prg_ain[12:0]};

  // The CHR bank to load. Each increment here is 4kb. So valid values are 0..31.
  reg [4:0] chrsel;
  always @* begin
    casez({chr_ain[12], latch_0, latch_1})
    3'b00?: chrsel = chr_bank_0a;
    3'b01?: chrsel = chr_bank_0b;
    3'b1?0: chrsel = chr_bank_1a;
    3'b1?1: chrsel = chr_bank_1b;
    endcase
  end
  assign chr_aout = {5'b100_00, chrsel, chr_ain[11:0]};
  
  // The a10 VRAM address line. (Used for mirroring)
  assign vram_a10 = mirroring ? chr_ain[11] : chr_ain[10];
  assign vram_ce = chr_ain[13];
  
  assign prg_allow = prg_ain[15] && !prg_write;
  assign chr_allow = flags[15];
endmodule

// This mapper also handles mapper 47,118,119 and 206.
module MMC3(input clk, input ce, input reset,
            input [31:0] flags,
            input [15:0] prg_ain, output [21:0] prg_aout,
            input prg_read, prg_write,                   // Read / write signals
            input [7:0] prg_din,
            output prg_allow,                            // Enable access to memory for the specified operation.
            input [13:0] chr_ain, output [21:0] chr_aout,
            output chr_allow,                            // Allow write
            output vram_a10,                             // Value for A10 address line
            output vram_ce,                              // True if the address should be routed to the internal 2kB VRAM.
            output reg irq);
  reg [2:0] bank_select;             // Register to write to next
  reg prg_rom_bank_mode;             // Mode for PRG banking
  reg chr_a12_invert;                // Mode for CHR banking
  reg mirroring;                     // 0 = vertical, 1 = horizontal
  reg irq_enable, irq_reload;        // IRQ enabled, and IRQ reload requested
  reg [7:0] irq_latch, counter;      // IRQ latch value and current counter
  reg ram_enable, ram_protect;       // RAM protection bits
  reg [6:0] chr_bank_0, chr_bank_1;  // Selected CHR banks
  reg [7:0] chr_bank_2, chr_bank_3, chr_bank_4, chr_bank_5;
  reg [5:0] prg_bank_0, prg_bank_1;  // Selected PRG banks
  wire prg_is_ram;
    
  // The alternative behavior has slightly different IRQ counter semantics.
  wire mmc3_alt_behavior = 0;
  
  wire TQROM = (flags[7:0] == 119); 		// TQROM maps 8kB CHR RAM
  wire TxSROM = (flags[7:0] == 118); 		// Connects CHR A17 to CIRAM A10
  wire mapper47 = (flags[7:0] == 47);		// Mapper 47 is a multicart that has 128k for each game. It has no RAM.
  wire DxROM = (flags[7:0] == 206);
  
  wire four_screen_mirroring = flags[16] | DxROM;
  reg mapper47_multicart;
  wire [7:0] new_counter = (counter == 0 || irq_reload) ? irq_latch : counter - 1;
  reg [3:0] a12_ctr; 
   
  always @(posedge clk) if (reset) begin
    irq <= 0;
    bank_select <= 0;
    prg_rom_bank_mode <= 0;
    chr_a12_invert <= 0;
    mirroring <= flags[14];
    {irq_enable, irq_reload} <= 0;
    {irq_latch, counter} <= 0;
    {ram_enable, ram_protect} <= 0;
    {chr_bank_0, chr_bank_1} <= 0;
    {chr_bank_2, chr_bank_3, chr_bank_4, chr_bank_5} <= 0;
    {prg_bank_0, prg_bank_1} <= 0;
    a12_ctr <= 0;
  end else if (ce) begin
    if (prg_write && prg_ain[15]) begin
      case({prg_ain[14], prg_ain[13], prg_ain[0]})
      3'b00_0: {chr_a12_invert, prg_rom_bank_mode, bank_select} <= {prg_din[7], prg_din[6], prg_din[2:0]}; // Bank select ($8000-$9FFE, even)
      3'b00_1: begin // Bank data ($8001-$9FFF, odd)
        case (bank_select) 
        0: chr_bank_0 <= prg_din[7:1];  // Select 2 KB CHR bank at PPU $0000-$07FF (or $1000-$17FF);
        1: chr_bank_1 <= prg_din[7:1];  // Select 2 KB CHR bank at PPU $0800-$0FFF (or $1800-$1FFF);
        2: chr_bank_2 <= prg_din;       // Select 1 KB CHR bank at PPU $1000-$13FF (or $0000-$03FF);
        3: chr_bank_3 <= prg_din;       // Select 1 KB CHR bank at PPU $1400-$17FF (or $0400-$07FF);
        4: chr_bank_4 <= prg_din;       // Select 1 KB CHR bank at PPU $1800-$1BFF (or $0800-$0BFF);
        5: chr_bank_5 <= prg_din;       // Select 1 KB CHR bank at PPU $1C00-$1FFF (or $0C00-$0FFF);
        6: prg_bank_0 <= prg_din[5:0];  // Select 8 KB PRG ROM bank at $8000-$9FFF (or $C000-$DFFF);
        7: prg_bank_1 <= prg_din[5:0];  // Select 8 KB PRG ROM bank at $A000-$BFFF
        endcase
      end
      3'b01_0: mirroring <= prg_din[0];                   // Mirroring ($A000-$BFFE, even)
      3'b01_1: {ram_enable, ram_protect} <= prg_din[7:6]; // PRG RAM protect ($A001-$BFFF, odd)
      3'b10_0: irq_latch <= prg_din;                      // IRQ latch ($C000-$DFFE, even)
      3'b10_1: irq_reload <= 1;                           // IRQ reload ($C001-$DFFF, odd)
      3'b11_0: begin irq_enable <= 0; irq <= 0; end       // IRQ disable ($E000-$FFFE, even)
      3'b11_1: irq_enable <= 1;                           // IRQ enable ($E001-$FFFF, odd)
      endcase
    end
    
    // For Mapper 47
    // $6000-7FFF:  [.... ...B]  Block select
    if (prg_write && prg_is_ram)
      mapper47_multicart <= prg_din[0];
        
    // Trigger IRQ counter on rising edge of chr_ain[12]
    // All MMC3A's and non-Sharp MMC3B's will generate only a single IRQ when $C000 is $00.
    // This is because this version of the MMC3 generates IRQs when the scanline counter is decremented to 0.
    // In addition, writing to $C001 with $C000 still at $00 will result in another single IRQ being generated.
    // In the community, this is known as the "alternate" or "old" behavior.
    // All MMC3C's and Sharp MMC3B's will generate an IRQ on each scanline while $C000 is $00.
    // This is because this version of the MMC3 generates IRQs when the scanline counter is equal to 0.
    // In the community, this is known as the "normal" or "new" behavior.
    if (chr_ain[12] && a12_ctr == 0) begin
      counter <= new_counter;
      if ( (!mmc3_alt_behavior  || counter != 0 || irq_reload) && new_counter == 0 && irq_enable) begin
//        $write("MMC3 SCANLINE IRQ!\n");
        irq <= 1;
      end
      irq_reload <= 0;      
    end
    a12_ctr <= chr_ain[12] ? 4'b1111 : (a12_ctr != 0) ? a12_ctr - 4'b0001 : a12_ctr;
  end

  // The PRG bank to load. Each increment here is 8kb. So valid values are 0..63.
  reg [5:0] prgsel;
  always @* begin
    casez({prg_ain[14:13], prg_rom_bank_mode})
    3'b00_0: prgsel = prg_bank_0;  // $8000 mode 0
    3'b00_1: prgsel = 6'b111110;   // $8000 fixed to second last bank
    3'b01_?: prgsel = prg_bank_1;  // $A000 mode 0,1
    3'b10_0: prgsel = 6'b111110;   // $C000 fixed to second last bank
    3'b10_1: prgsel = prg_bank_0;  // $C000 mode 1
    3'b11_?: prgsel = 6'b111111;   // $E000 fixed to last bank
    endcase
    // mapper47 is limited to 128k PRG, the top bits are controlled by mapper47_multicart instead.
    if (mapper47) prgsel[5:4] = {1'b0, mapper47_multicart};
  end

  // The CHR bank to load. Each increment here is 1kb. So valid values are 0..255.
  reg [7:0] chrsel;
  always @* begin
    casez({chr_ain[12] ^ chr_a12_invert, chr_ain[11], chr_ain[10]})
    3'b00?: chrsel = {chr_bank_0, chr_ain[10]};
    3'b01?: chrsel = {chr_bank_1, chr_ain[10]};
    3'b100: chrsel = chr_bank_2;
    3'b101: chrsel = chr_bank_3;
    3'b110: chrsel = chr_bank_4;
    3'b111: chrsel = chr_bank_5;
    endcase
    // mapper47 is limited to 128k CHR, the top bit is controlled by mapper47_multicart instead.
    if (mapper47) chrsel[7] = mapper47_multicart;
  end

  wire [21:0] prg_aout_tmp = {3'b00_0,  prgsel, prg_ain[12:0]};

  assign {chr_allow, chr_aout} = 
      (TQROM && chrsel[6])   ? {1'b1,    9'b11_1111_111, chrsel[2:0], chr_ain[9:0]} :   // TQROM 8kb CHR-RAM
      (four_screen_mirroring && chr_ain[13]) ? {1'b1,    9'b11_1111_111, chr_ain[13], chr_ain[11:0]} :  // DxROM 8kb CHR-RAM
                             {flags[15], 4'b10_00, chrsel, chr_ain[9:0]};               // Standard MMC3

  assign prg_is_ram = prg_ain >= 'h6000 && prg_ain < 'h8000 && ram_enable && !(ram_protect && prg_write);
  assign prg_allow = prg_ain[15] && !prg_write || prg_is_ram && !mapper47;
  wire [21:0] prg_ram = {9'b11_1100_000, prg_ain[12:0]};
  assign prg_aout = prg_is_ram  && !mapper47 && !DxROM ? prg_ram : prg_aout_tmp;
  assign vram_a10 = !TxSROM ? (mirroring ? chr_ain[11] : chr_ain[10]) :	// TxSROM do not support mirroring
                                    chrsel[7];
  assign vram_ce = chr_ain[13] && !four_screen_mirroring;
endmodule

// MMC4 mapper chip. PRG ROM: 256kB. Bank Size: 16kB. CHR ROM: 128kB
module MMC4(input clk, input ce, input reset,
            input [31:0] flags,
            input [15:0] prg_ain, output [21:0] prg_aout,
            input prg_read, prg_write,                   // Read / write signals
            input [7:0] prg_din,
            output prg_allow,                            // Enable access to memory for the specified operation.
            input chr_read, input [13:0] chr_ain, output [21:0] chr_aout,
            output chr_allow,                      		// Allow write
            output vram_a10,                             // Value for A10 address line
            output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.

// PRG ROM bank select ($A000-$AFFF)
// 7  bit  0
// ---- ----
// xxxx PPPP
//      ||||
//      ++++- Select 16 KB PRG ROM bank for CPU $8000-$BFFF
  reg [3:0] prg_bank;

// CHR ROM $FD/0000 bank select ($B000-$BFFF)
// 7  bit  0
// ---- ----
// xxxC CCCC
//    | ||||
//    +-++++- Select 4 KB CHR ROM bank for PPU $0000-$0FFF
//            used when latch 0 = $FD
  reg   [4:0] chr_bank_0a;

// CHR ROM $FE/0000 bank select ($C000-$CFFF)
// 7  bit  0
// ---- ----
// xxxC CCCC
//    | ||||
//    +-++++- Select 4 KB CHR ROM bank for PPU $0000-$0FFF
//            used when latch 0 = $FE
   reg [4:0] chr_bank_0b;
   
// CHR ROM $FD/1000 bank select ($D000-$DFFF)
// 7  bit  0
// ---- ----
// xxxC CCCC
//    | ||||
//    +-++++- Select 4 KB CHR ROM bank for PPU $1000-$1FFF
//            used when latch 1 = $FD
  reg [4:0] chr_bank_1a;
   
// CHR ROM $FE/1000 bank select ($E000-$EFFF)
// 7  bit  0
// ---- ----
// xxxC CCCC
//    | ||||
//    +-++++- Select 4 KB CHR ROM bank for PPU $1000-$1FFF
//            used when latch 1 = $FE
  reg [4:0] chr_bank_1b; 
  
// Mirroring ($F000-$FFFF)
// 7  bit  0
// ---- ----
// xxxx xxxM
//         |
//         +- Select nametable mirroring (0: vertical; 1: horizontal)  
  reg mirroring;
  
  reg latch_0, latch_1;
  
  // Update registers
  always @(posedge clk) if (ce) begin
    if (reset)
	   prg_bank <= 4'b1110;	  
    else if (prg_write && prg_ain[15]) begin
      case(prg_ain[14:12])
      2: prg_bank <= prg_din[3:0];     // $A000
      3: chr_bank_0a <= prg_din[4:0];  // $B000
      4: chr_bank_0b <= prg_din[4:0];  // $C000
      5: chr_bank_1a <= prg_din[4:0];  // $D000
      6: chr_bank_1b <= prg_din[4:0];  // $E000
      7: mirroring <=  prg_din[0];     // $F000
      endcase
    end
  end
  
// PPU reads $0FD8 through $0FDF: latch 0 is set to $FD for subsequent reads
// PPU reads $0FE8 through $0FEF: latch 0 is set to $FE for subsequent reads
// PPU reads $1FD8 through $1FDF: latch 1 is set to $FD for subsequent reads
// PPU reads $1FE8 through $1FEF: latch 1 is set to $FE for subsequent reads
  always @(posedge clk) if (ce && chr_read) begin
    latch_0 <= (chr_ain & 14'h3ff8) == 14'h0fd8 ? 0 : (chr_ain & 14'h3ff8) == 14'h0fe8 ? 1 : latch_0;
    latch_1 <= (chr_ain & 14'h3ff8) == 14'h1fd8 ? 0 : (chr_ain & 14'h3ff8) == 14'h1fe8 ? 1 : latch_1;
  end
  
  // The PRG bank to load. Each increment here is 16kb. So valid values are 0..15.
  reg [3:0] prgsel;
  always @* begin
    casez(prg_ain[14])
    1'b0:    prgsel = prg_bank;
    default: prgsel = 4'b1111;
    endcase
  end
  wire [21:0] prg_aout_tmp = {4'b00_00, prgsel, prg_ain[13:0]};

  // The CHR bank to load. Each increment here is 4kb. So valid values are 0..31.
  reg [4:0] chrsel;
  always @* begin
    casez({chr_ain[12], latch_0, latch_1})
    3'b00?: chrsel = chr_bank_0a;
    3'b01?: chrsel = chr_bank_0b;
    3'b1?0: chrsel = chr_bank_1a;
    3'b1?1: chrsel = chr_bank_1b;
    endcase
  end
  assign chr_aout = {5'b100_00, chrsel, chr_ain[11:0]};
  
  // The a10 VRAM address line. (Used for mirroring)
  assign vram_a10 = mirroring ? chr_ain[11] : chr_ain[10];
  assign vram_ce = chr_ain[13];
  
  assign chr_allow = flags[15];
  
  wire prg_is_ram = prg_ain >= 'h6000 && prg_ain < 'h8000;
  assign prg_allow = prg_ain[15] && !prg_write ||
                     prg_is_ram;
  wire [21:0] prg_ram = {9'b11_1100_000, prg_ain[12:0]};
  assign prg_aout = prg_is_ram ? prg_ram : prg_aout_tmp;

endmodule

module MMC5(input clk, input ce, input reset,
            input [31:0] flags,
            input [19:0] ppuflags,
            input [15:0] prg_ain, output [21:0] prg_aout,
            input prg_read, prg_write,                   // Read / write signals
            input [7:0] prg_din, output reg [7:0] prg_dout,
            output prg_allow,                            // Enable access to memory for the specified operation.
            input [13:0] chr_ain, output reg [21:0] chr_aout,
            output reg [7:0] chr_dout, output has_chr_dout,
            output chr_allow,                            // Allow write
            output vram_a10,                             // Value for A10 address line
            output vram_ce,                              // True if the address should be routed to the internal 2kB VRAM.
            output irq);
  reg [1:0] prg_mode, chr_mode;
  reg prg_protect_1, prg_protect_2;
  reg [1:0] extended_ram_mode;
  reg [7:0] mirroring;
  reg [7:0] fill_tile;
  reg [1:0] fill_attr;
  reg [2:0] prg_ram_bank;
  reg [7:0] prg_bank_0, prg_bank_1, prg_bank_2;
  reg [6:0] prg_bank_3;
  reg [9:0] chr_bank_0, chr_bank_1, chr_bank_2, chr_bank_3,
            chr_bank_4, chr_bank_5, chr_bank_6, chr_bank_7,
            chr_bank_8, chr_bank_9, chr_bank_a, chr_bank_b;
  reg [1:0] upper_chr_bank_bits;
  reg chr_last; // Which CHR set was written to last?
  
  reg [4:0] vsplit_startstop;
  reg vsplit_enable, vsplit_side;
  reg [7:0] vsplit_scroll, vsplit_bank;
  
  reg [7:0] irq_scanline;
  reg irq_enable;
  reg irq_pending;
  
  reg [7:0] multiplier_1;
  reg [7:0] multiplier_2; 
  wire [15:0] multiply_result = multiplier_1 * multiplier_2;
  
  reg [7:0] expansion_ram[0:1023]; // Block RAM, otherwise we need to time multiplex..
  reg [7:0] last_read_ram;
  
  // unpack ppu flags
  wire ppu_in_frame = ppuflags[0];
  wire ppu_sprite16 = ppuflags[1];
  wire [8:0] ppu_cycle = ppuflags[10:2]; 
  wire [8:0] ppu_scanline = ppuflags[19:11];
  
  // Handle IO register writes  
  always @(posedge clk) begin
    if (ce) begin
      if (prg_write && prg_ain[15:10] == 6'b010100) begin // $5000-$53FF
        if (prg_ain <= 16'h5113)
          $write("%X <= %X (%d)\n", prg_ain, prg_din, ppu_scanline);
        casez(prg_ain[9:0])
        10'h100: prg_mode <= prg_din[1:0];
        10'h101: chr_mode <= prg_din[1:0];
        10'h102: prg_protect_1 <= (prg_din[1:0] == 2'b10);
        10'h103: prg_protect_2 <= (prg_din[1:0] == 2'b01);
        10'h104: extended_ram_mode <= prg_din[1:0];
        10'h105: mirroring <= prg_din;
        10'h106: fill_tile <= prg_din;
        10'h107: fill_attr <= prg_din[1:0];
        10'h113: prg_ram_bank <= prg_din[2:0];
        10'h114: prg_bank_0 <= prg_din;
        10'h115: prg_bank_1 <= prg_din;
        10'h116: prg_bank_2 <= prg_din;
        10'h117: prg_bank_3 <= prg_din[6:0];
        10'h120: chr_bank_0 <= {upper_chr_bank_bits, prg_din};
        10'h121: chr_bank_1 <= {upper_chr_bank_bits, prg_din};
        10'h122: chr_bank_2 <= {upper_chr_bank_bits, prg_din};
        10'h123: chr_bank_3 <= {upper_chr_bank_bits, prg_din};
        10'h124: chr_bank_4 <= {upper_chr_bank_bits, prg_din};
        10'h125: chr_bank_5 <= {upper_chr_bank_bits, prg_din};
        10'h126: chr_bank_6 <= {upper_chr_bank_bits, prg_din};
        10'h127: chr_bank_7 <= {upper_chr_bank_bits, prg_din};
        10'h128: chr_bank_8  <= {upper_chr_bank_bits, prg_din};
        10'h129: chr_bank_9  <= {upper_chr_bank_bits, prg_din};
        10'h12a: chr_bank_a  <= {upper_chr_bank_bits, prg_din};
        10'h12b: chr_bank_b  <= {upper_chr_bank_bits, prg_din};
        10'h130: upper_chr_bank_bits <= prg_din[1:0];
        10'h200: {vsplit_enable, vsplit_side, vsplit_startstop} = {prg_din[7:6], prg_din[4:0]};
        10'h201: vsplit_scroll <= prg_din;
        10'h202: vsplit_bank <= prg_din;
        10'h203: irq_scanline <= prg_din;
        10'h204: irq_enable <= prg_din[7];
        10'h205: multiplier_1 <= prg_din;
        10'h206: multiplier_2 <= prg_din;
        default: begin end
        endcase
        
        // Remember which set of CHR was written to last.
        if (prg_ain[9:0] >= 10'h120 && prg_ain[9:0] < 10'h130)
          chr_last <= prg_ain[3];
      end
      
      // Mode 0/1 - Not readable (returns open bus), can only be written while the PPU is rendering (otherwise, 0 is written)
      // Mode 2 - Readable and writable
      // Mode 3 - Read-only
      if (prg_write && prg_ain[15:10] == 6'b010111) begin // $5C00-$5FFF
        if (extended_ram_mode != 3)
          expansion_ram[prg_ain[9:0]] <= (extended_ram_mode[1] || ppu_in_frame) ? prg_din : 0;
      end
    end
    if (reset) begin
      prg_bank_3 <= 7'h7F;
      prg_mode <= 3;
    end
  end
  
  // Read from MMC5
  always @* begin
    prg_dout = 8'hFF; // By default open bus.
    if (prg_ain[15:10] == 6'b010111 && extended_ram_mode[1]) begin
      prg_dout = last_read_ram;
    end else if (prg_ain == 16'h5204) begin
      prg_dout = {irq_pending, ppu_in_frame, 6'b111111};
    end else if (prg_ain == 16'h5205) begin
      prg_dout = multiply_result[7:0];
    end else if (prg_ain == 16'h5206) begin
      prg_dout = multiply_result[15:8];
    end
  end
  
  // Determine IRQ handling
  reg last_scanline, irq_trig;
  always @(posedge clk) if (ce) begin
    if (prg_read && prg_ain == 16'h5204)
      irq_pending <= 0;
    irq_trig <= (irq_scanline != 0 && irq_scanline < 240 && ppu_scanline == {1'b0, irq_scanline});
    last_scanline <= ppu_scanline[0];
    if (ppu_scanline[0] != last_scanline && irq_trig)
      irq_pending <= 1;
  end
  assign irq = irq_pending && irq_enable;

  // Determine if vertical split is active.
  reg [5:0] cur_tile;     // Current tile the PPU is fetching
  reg [5:0] new_cur_tile; // New value for |cur_tile|
  reg [7:0] vscroll;      // Current y scroll for the split region
  reg last_in_split_area, in_split_area;

  // Compute if we're in the split area right now by counting PPU tiles.
  always @* begin
    new_cur_tile = (ppu_cycle[8:3] == 40) ? 0 : (cur_tile + 6'b1);
    in_split_area = last_in_split_area;
    if (ppu_cycle[2:0] == 0 && ppu_cycle < 336) begin
      if (new_cur_tile == 0)
        in_split_area = !vsplit_side;
      else if (new_cur_tile == {1'b0, vsplit_startstop})
        in_split_area = vsplit_side;
      else if (new_cur_tile == 34)
        in_split_area = 0;
    end
  end
  always @(posedge clk) if (ce) begin
    last_in_split_area <= in_split_area;
    if (ppu_cycle[2:0] == 0 && ppu_cycle < 336)
      cur_tile <= new_cur_tile;
  end
  // Keep track of scroll
  always @(posedge clk) if (ce) begin
    if (ppu_cycle == 319)
      vscroll <= ppu_scanline[8] ? vsplit_scroll : 
                 (vscroll == 239) ? 8'b0 : vscroll + 8'b1;
  end

  // Mirroring bits
  // %00 = NES internal NTA
  // %01 = NES internal NTB
  // %10 = use ExRAM as NT
  // %11 = Fill Mode
  wire [1:0] mirrbits = (chr_ain[11:10] == 0) ? mirroring[1:0] : 
                        (chr_ain[11:10] == 1) ? mirroring[3:2] : 
                        (chr_ain[11:10] == 2) ? mirroring[5:4] : 
                                                mirroring[7:6];

  // Compute the new overriden nametable/attr address the split will read from instead
  // when the VSplit is active.
  // Cycle 0, 1 = nametable
  // Cycle 2, 3 = attribute
  // Named it loopy so I can copypaste from PPU code :)
  wire [9:0] loopy = {vscroll[7:3], cur_tile[4:0]};              
  wire [9:0] split_addr = (ppu_cycle[1] == 0) ? loopy :                            // name table
                                                {4'b1111, loopy[9:7], loopy[4:2]}; // attribute table
  // Selects 2 out of the attr bits read from exram.
  wire [1:0] split_attr = (!loopy[1] && !loopy[6]) ? last_read_ram[1:0] : 
                          ( loopy[1] && !loopy[6]) ? last_read_ram[3:2] :
                          (!loopy[1] &&  loopy[6]) ? last_read_ram[5:4] : 
                                                     last_read_ram[7:6];
  // If splitting is active or not
  wire insplit = in_split_area && vsplit_enable;

  // Currently reading the attribute byte?
  wire exattr_read = (extended_ram_mode == 1) && ppu_cycle[1];
  
  // If the current chr read should be redirected from |chr_dout| instead.
  assign has_chr_dout = chr_ain[13] && (mirrbits[1] || insplit || exattr_read);
  wire [1:0] override_attr = insplit ? split_attr : (extended_ram_mode == 1) ? last_read_ram[7:6] : fill_attr;
  always @* begin
    if (ppu_cycle[1] == 0) begin
      // Name table fetch
      if (insplit || mirrbits[0] == 0) chr_dout = (extended_ram_mode[1] ? 8'b0 : last_read_ram);
      else begin
        $write("Inserting filltile!\n");
        chr_dout = fill_tile;
      end
    end else begin
      // Attribute table fetch
      if (!insplit && !exattr_read && mirrbits[0] == 0) chr_dout = (extended_ram_mode[1] ? 8'b0 : last_read_ram);
      else chr_dout = {override_attr, override_attr, override_attr, override_attr};
    end
  end

  // Handle reading from the expansion ram.
  // 0 - Use as extra nametable (possibly for split mode)
  // 1 - Use as extended attribute data OR an extra nametable
  // 2 - Use as ordinary RAM
  // 3 - Use as ordinary RAM, write protected
  wire [9:0] exram_read_addr = extended_ram_mode[1] ? prg_ain[9:0] : 
                               insplit              ? split_addr :
                                                      chr_ain[9:0];
  always @(posedge clk)
    last_read_ram <= expansion_ram[exram_read_addr];

  // Compute PRG address to read from.
  reg [7:0] prgsel;
  always @* begin
    casez({prg_mode, prg_ain[15:13]})
    5'b??_0??: prgsel = {5'b1xxxx, prg_ram_bank};                // $6000-$7FFF all modes
    5'b00_1??: prgsel = {1'b1, prg_bank_3[6:2], prg_ain[14:13]}; // $8000-$FFFF mode 0, 32kB (prg_bank_3, skip 2 bits)

    5'b01_10?: prgsel = {      prg_bank_1[7:1], prg_ain[13]};    // $8000-$BFFF mode 1, 16kB (prg_bank_1, skip 1 bit)
    5'b01_11?: prgsel = {1'b1, prg_bank_3[6:1], prg_ain[13]};    // $C000-$FFFF mode 1, 16kB (prg_bank_3, skip 1 bit)

    5'b10_10?: prgsel = {      prg_bank_1[7:1], prg_ain[13]};    // $8000-$BFFF mode 2, 16kB (prg_bank_1, skip 1 bit)
    5'b10_110: prgsel = {      prg_bank_2};                      // $C000-$DFFF mode 2, 8kB  (prg_bank_2)
    5'b10_111: prgsel = {1'b1, prg_bank_3};                      // $E000-$FFFF mode 2, 8kB  (prg_bank_3)

    5'b11_100: prgsel = {      prg_bank_0};                      // $8000-$9FFF mode 3, 8kB (prg_bank_0)
    5'b11_101: prgsel = {      prg_bank_1};                      // $A000-$BFFF mode 3, 8kB (prg_bank_1)
    5'b11_110: prgsel = {      prg_bank_2};                      // $C000-$DFFF mode 3, 8kB (prg_bank_2)
    5'b11_111: prgsel = {1'b1, prg_bank_3};                      // $E000-$FFFF mode 3, 8kB (prg_bank_3)
    endcase
    prgsel[7] = !prgsel[7]; // 0 means RAM, doh.
    
    // Limit to 64k RAM.
    if (prgsel[7])
      prgsel[6:3] = 0;
  end
  assign prg_aout = {1'b0, prgsel, prg_ain[12:0]};    // 8kB banks

  // Registers $5120-$5127 apply to sprite graphics and $5128-$512B for background graphics, but ONLY when 8x16 sprites are enabled.
  // Otherwise, the last set of registers written to (either $5120-$5127 or $5128-$512B) will be used for all graphics.
  // 0 if using $5120-$5127, 1 if using $5128-$512F
  wire is_bg_fetch = !(ppu_cycle[8] && !ppu_cycle[6]);
  wire chrset = ppu_sprite16 ? is_bg_fetch : chr_last; 
  reg [9:0] chrsel;
  always @* begin
    casez({chr_mode, chr_ain[12:10], chrset})
    6'b00_???_0: chrsel = {chr_bank_7[6:0], chr_ain[12:10]}; // $0000-$1FFF mode 0, 8 kB
    6'b00_???_1: chrsel = {chr_bank_b[6:0], chr_ain[12:10]}; // $0000-$1FFF mode 0, 8 kB
    
    6'b01_0??_0: chrsel = {chr_bank_3[7:0], chr_ain[11:10]}; // $0000-$0FFF mode 1, 4 kB
    6'b01_1??_0: chrsel = {chr_bank_7[7:0], chr_ain[11:10]}; // $1000-$1FFF mode 1, 4 kB
    6'b01_???_1: chrsel = {chr_bank_b[7:0], chr_ain[11:10]}; // $0000-$0FFF mode 1, 4 kB

    6'b10_00?_0: chrsel = {chr_bank_1[8:0], chr_ain[10]};    // $0000-$07FF mode 2, 2 kB
    6'b10_01?_0: chrsel = {chr_bank_3[8:0], chr_ain[10]};    // $0800-$0FFF mode 2, 2 kB
    6'b10_10?_0: chrsel = {chr_bank_5[8:0], chr_ain[10]};    // $1000-$17FF mode 2, 2 kB
    6'b10_11?_0: chrsel = {chr_bank_7[8:0], chr_ain[10]};    // $1800-$1FFF mode 2, 2 kB
    6'b10_?0?_1: chrsel = {chr_bank_9[8:0], chr_ain[10]};    // $0000-$07FF mode 2, 2 kB
    6'b10_?1?_1: chrsel = {chr_bank_b[8:0], chr_ain[10]};    // $0800-$0FFF mode 2, 2 kB

    6'b11_000_0: chrsel = chr_bank_0;                        // $0000-$03FF mode 3, 1 kB
    6'b11_001_0: chrsel = chr_bank_1;                        // $0400-$07FF mode 3, 1 kB
    6'b11_010_0: chrsel = chr_bank_2;                        // $0800-$0BFF mode 3, 1 kB
    6'b11_011_0: chrsel = chr_bank_3;                        // $0C00-$0FFF mode 3, 1 kB
    6'b11_100_0: chrsel = chr_bank_4;                        // $1000-$13FF mode 3, 1 kB
    6'b11_101_0: chrsel = chr_bank_5;                        // $1400-$17FF mode 3, 1 kB
    6'b11_110_0: chrsel = chr_bank_6;                        // $1800-$1BFF mode 3, 1 kB
    6'b11_111_0: chrsel = chr_bank_7;                        // $1C00-$1FFF mode 3, 1 kB
    6'b11_?00_1: chrsel = chr_bank_8;                        // $0000-$03FF mode 3, 1 kB
    6'b11_?01_1: chrsel = chr_bank_9;                        // $0400-$07FF mode 3, 1 kB
    6'b11_?10_1: chrsel = chr_bank_a;                        // $0800-$0BFF mode 3, 1 kB
    6'b11_?11_1: chrsel = chr_bank_b;                        // $0C00-$0FFF mode 3, 1 kB
    endcase
  
    chr_aout = {2'b10, chrsel, chr_ain[9:0]};    // 1kB banks
    
    // Override |chr_aout| if we're in a vertical split.
    if (insplit) begin
      $write("In vertical split!\n");
      chr_aout = {2'b10, vsplit_bank, chr_ain[11:3], vscroll[2:0]};
    end else if (extended_ram_mode == 1 && is_bg_fetch) begin
      $write("In exram thingy!\n");
      // Extended attribute mode. Replace the page with the page from exram.
      chr_aout = {2'b10, upper_chr_bank_bits, last_read_ram[5:0], chr_ain[11:0]};
    end
      
  end
  
  // The a10 VRAM address line. (Used for mirroring)
  assign vram_a10 = mirrbits[0];
  assign vram_ce = chr_ain[13] && !mirrbits[1];
  
  // Writing to RAM is enabled only when the protect bits say so.  
  wire prg_ram_we = prg_protect_1 && prg_protect_2;
  assign prg_allow = (prg_ain >= 16'h6000) && (!prg_write || prgsel[7] && prg_ram_we);
  
  // MMC5 boards typically have no CHR RAM.
  assign chr_allow = flags[15];
endmodule

// iNES mapper 64 and 158 - Tengen's version of MMC3
module Rambo1(input clk, input ce, input reset,
              input [31:0] flags,
              input [15:0] prg_ain, output [21:0] prg_aout,
              input prg_read, prg_write,                   // Read / write signals
              input [7:0] prg_din,
              output prg_allow,                            // Enable access to memory for the specified operation.
              input [13:0] chr_ain, output [21:0] chr_aout,
              output chr_allow,                            // Allow write
              output vram_a10,                             // Value for A10 address line
              output vram_ce,                              // True if the address should be routed to the internal 2kB VRAM.
              output reg irq);
  reg [3:0] bank_select;             // Register to write to next
  reg prg_rom_bank_mode;             // Mode for PRG banking
  reg chr_K;                         // Mode for CHR banking
  reg chr_a12_invert;                // Mode for CHR banking
  reg mirroring;                     // 0 = vertical, 1 = horizontal
  reg irq_enable, irq_reload;        // IRQ enabled, and IRQ reload requested
  reg [7:0] irq_latch, counter;      // IRQ latch value and current counter
  reg want_irq;
  reg [7:0] chr_bank_0, chr_bank_1;  // Selected CHR banks
  reg [7:0] chr_bank_2, chr_bank_3, chr_bank_4, chr_bank_5;
  reg [7:0] chr_bank_8, chr_bank_9;
  reg [5:0] prg_bank_0, prg_bank_1, prg_bank_2;  // Selected PRG banks
  reg irq_cycle_mode;
  reg [1:0] cycle_counter;
 
  // Mapper has vram_a10 wired to CHR A17
  wire mapper64 = (flags[7:0] == 64);

  reg is_interrupt;  // Not a reg!
  
  // This code detects rising edges on a12.
  reg old_a12_edge;
  reg [1:0] a12_ctr;
  wire a12_edge = (chr_ain[12] && a12_ctr == 0) || old_a12_edge;
  always @(posedge clk) begin
    old_a12_edge <= a12_edge && !ce;
    a12_ctr <= chr_ain[12] ? 2'b11 : (a12_ctr != 0 && ce) ? a12_ctr - 2'b01 : a12_ctr;
  end
  
  always @(posedge clk) if (reset) begin
    bank_select <= 0;
    prg_rom_bank_mode <= 0;
    chr_K <= 0;
    chr_a12_invert <= 0;
    mirroring <= 0;
    {irq_enable, irq_reload} <= 0;
    {irq_latch, counter} <= 0;
    want_irq <= 0;
    {chr_bank_0, chr_bank_1} <= 0;
    {chr_bank_2, chr_bank_3, chr_bank_4, chr_bank_5} <= 0;
    {chr_bank_8, chr_bank_9} <= 0;
    {prg_bank_0, prg_bank_1, prg_bank_2} <= 6'b111111;
    irq_cycle_mode <= 0;
    cycle_counter <= 0;
    irq <= 0;
  end else if (ce) begin
    cycle_counter <= cycle_counter + 1;
        
    if (prg_write && prg_ain[15]) begin
      case({prg_ain[14:13], prg_ain[0]})
      // Bank select ($8000-$9FFE, even)
      3'b00_0: {chr_a12_invert, prg_rom_bank_mode, chr_K, bank_select} <= {prg_din[7:5], prg_din[3:0]}; 
      // Bank data ($8001-$9FFF, odd)
      3'b00_1:
        case (bank_select) 
        0: chr_bank_0 <= prg_din;       // Select 2 (K=0) or 1 (K=1) KB CHR bank at PPU $0000 (or $1000);
        1: chr_bank_1 <= prg_din;       // Select 2 (K=0) or 1 (K=1) KB CHR bank at PPU $0800 (or $1800);
        2: chr_bank_2 <= prg_din;       // Select 1 KB CHR bank at PPU $1000-$13FF (or $0000-$03FF);
        3: chr_bank_3 <= prg_din;       // Select 1 KB CHR bank at PPU $1400-$17FF (or $0400-$07FF);
        4: chr_bank_4 <= prg_din;       // Select 1 KB CHR bank at PPU $1800-$1BFF (or $0800-$0BFF);
        5: chr_bank_5 <= prg_din;       // Select 1 KB CHR bank at PPU $1C00-$1FFF (or $0C00-$0FFF);
        6: prg_bank_0 <= prg_din[5:0];  // Select 8 KB PRG ROM bank at $8000-$9FFF (or $C000-$DFFF);
        7: prg_bank_1 <= prg_din[5:0];  // Select 8 KB PRG ROM bank at $A000-$BFFF
        8: chr_bank_8 <= prg_din;       // If K=1, Select 1 KB CHR bank at PPU $0400 (or $1400);
        9: chr_bank_9 <= prg_din;       // If K=1, Select 1 KB CHR bank at PPU $0C00 (or $1C00)
        15: prg_bank_2 <= prg_din[5:0]; // Select 8 KB PRG ROM bank at $C000-$DFFF (or $8000-$9FFF);
        endcase
      3'b01_0: mirroring <= prg_din[0];                   // Mirroring ($A000-$BFFE, even)
      3'b01_1: begin end
      3'b10_0: irq_latch <= prg_din;                      // IRQ latch ($C000-$DFFE, even)
      3'b10_1: begin 
                 {irq_reload, irq_cycle_mode} <= {1'b1, prg_din[0]}; // IRQ reload ($C001-$DFFF, odd)
                 cycle_counter <= 0;
               end
      3'b11_0: {irq_enable, irq} <= 2'b0;                 // IRQ disable ($E000-$FFFE, even)
      3'b11_1: irq_enable <= 1;                           // IRQ enable ($E001-$FFFF, odd)
      endcase
    end
    is_interrupt = irq_cycle_mode ? (cycle_counter == 3) : a12_edge;
    if (is_interrupt) begin
      if (irq_reload || counter == 0) begin
        counter <= irq_latch;
        want_irq <= irq_reload;
      end else begin
        counter <= counter - 1;
        want_irq <= 1;
      end
      if (counter == 0 && want_irq && !irq_reload && irq_enable)
        irq <= 1;
      irq_reload <= 0;
    end
    
  end
  // The PRG bank to load. Each increment here is 8kb. So valid values are 0..63.
  reg [5:0] prgsel;
  always @* begin
    casez({prg_ain[14:13], prg_rom_bank_mode})
    3'b00_0: prgsel = prg_bank_0;  // $8000 is R:6
    3'b01_0: prgsel = prg_bank_1;  // $A000 is R:7
    3'b10_0: prgsel = prg_bank_2;  // $C000 is R:F
    3'b11_0: prgsel = 6'b111111;   // $E000 fixed to last bank
    3'b00_1: prgsel = prg_bank_2;  // $8000 is R:F
    3'b01_1: prgsel = prg_bank_0;  // $A000 is R:6
    3'b10_1: prgsel = prg_bank_1;  // $C000 is R:7
    3'b11_1: prgsel = 6'b111111;   // $E000 fixed to last bank
    endcase
  end
  // The CHR bank to load. Each increment here is 1kb. So valid values are 0..255.
  reg [7:0] chrsel;
  always @* begin
    casez({chr_ain[12] ^ chr_a12_invert, chr_ain[11], chr_ain[10], chr_K})
    4'b00?_0: chrsel = {chr_bank_0[7:1], chr_ain[10]};
    4'b01?_0: chrsel = {chr_bank_1[7:1], chr_ain[10]};
    4'b000_1: chrsel = chr_bank_0;
    4'b001_1: chrsel = chr_bank_8;
    4'b010_1: chrsel = chr_bank_1;
    4'b011_1: chrsel = chr_bank_9;
    4'b100_?: chrsel = chr_bank_2;
    4'b101_?: chrsel = chr_bank_3;
    4'b110_?: chrsel = chr_bank_4;
    4'b111_?: chrsel = chr_bank_5;
    endcase
  end
  assign prg_aout = {3'b00_0,  prgsel, prg_ain[12:0]};
  assign {chr_allow, chr_aout} = {flags[15], 4'b10_00, chrsel, chr_ain[9:0]};
  assign prg_allow = prg_ain[15] && !prg_write;
  assign vram_a10 = mapper64 ? chrsel[7] :  // Mapper 64 controls mirroring by switching the top bits of the CHR address
                    mirroring ? chr_ain[11] : chr_ain[10];
  assign vram_ce = chr_ain[13];
endmodule


// #13 - CPROM - Used by Videomation
module Mapper13(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                            // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                      // Allow write
                output vram_a10,                             // Value for A10 address line
                output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.
  reg [1:0] chr_bank;
  always @(posedge clk) if (reset) begin
    chr_bank <= 0;
  end else if (ce) begin
    if (prg_ain[15] && prg_write)
      chr_bank <= prg_din[1:0];
  end
  assign prg_aout = {7'b00_0000_0, prg_ain[14:0]};
  assign prg_allow = prg_ain[15] && !prg_write;
  assign chr_allow = flags[15];
  assign chr_aout = {8'b01_0000_00, chr_ain[12] ? chr_bank : 2'b00, chr_ain[11:0]};
  assign vram_ce = chr_ain[13];
  assign vram_a10 = flags[14] ? chr_ain[10] : chr_ain[11];
endmodule

// #15 -  100-in-1 Contra Function 16
module Mapper15(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                            // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                      // Allow write
                output vram_a10,                             // Value for A10 address line
                output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.
// 15 bit  8 7  bit  0  Address bus
// ---- ---- ---- ----
// 1xxx xxxx xxxx xxSS
// |                ||
// |                ++- Select PRG ROM bank mode
// |                    0: 32K; 1: 128K (UNROM style); 2: 8K; 3: 16K
// +------------------- Always 1
// 7  bit  0  Data bus
// ---- ----
// bMBB BBBB
// |||| ||||
// ||++-++++- Select 16 KB PRG ROM bank
// |+-------- Select nametable mirroring mode (0=vertical; 1=horizontal)
// +--------- Select 8 KB half of 16 KB PRG ROM bank
//            (should be 0 except in bank mode 0)
  reg [1:0] prg_rom_bank_mode;
  reg prg_rom_bank_lowbit;
  reg mirroring;
  reg [5:0] prg_rom_bank;
  always @(posedge clk) if (reset) begin
    prg_rom_bank_mode <= 0;
    prg_rom_bank_lowbit <= 0;
    mirroring <= 0;
    prg_rom_bank <= 0;
  end else if (ce) begin
    if (prg_ain[15] && prg_write)
      {prg_rom_bank_mode, prg_rom_bank_lowbit, mirroring, prg_rom_bank} <= {prg_ain[1:0], prg_din[7:0]};
  end
  reg [6:0] prg_bank;
  always begin
    casez({prg_rom_bank_mode, prg_ain[14]})
    // Bank mode 0 ( 32K ) / CPU $8000-$BFFF: Bank B / CPU $C000-$FFFF: Bank (B OR 1)
    3'b00_0: prg_bank = {prg_rom_bank, prg_ain[13]};
    3'b00_1: prg_bank = {prg_rom_bank | 6'b1, prg_ain[13]};
    // Bank mode 1 ( 128K ) / CPU $8000-$BFFF: Switchable 16 KB bank B / CPU $C000-$FFFF: Fixed to last bank in the cart
    3'b01_0: prg_bank = {prg_rom_bank, prg_ain[13]};
    3'b01_1: prg_bank = {6'b111111, prg_ain[13]};
    // Bank mode 2 ( 8K ) / CPU $8000-$9FFF: Sub-bank b of 16 KB PRG ROM bank B / CPU $A000-$FFFF: Mirrors of $8000-$9FFF
    3'b10_?: prg_bank = {prg_rom_bank, prg_rom_bank_lowbit};
    // Bank mode 3 ( 16K ) / CPU $8000-$BFFF: 16 KB bank B / CPU $C000-$FFFF: Mirror of $8000-$BFFF
    3'b11_?: prg_bank = {prg_rom_bank, prg_ain[13]};
    endcase
  end
  assign prg_aout = {2'b00, prg_bank, prg_ain[12:0]};
  assign prg_allow = prg_ain[15] && !prg_write;
  assign chr_allow = flags[15]; // CHR RAM?
  assign chr_aout = {9'b10_0000_000, chr_ain[12:0]};
  assign vram_ce = chr_ain[13];
  assign vram_a10 = mirroring ? chr_ain[11] : chr_ain[10];
endmodule

// Mapper 16, Bandai
module Mapper16(input clk, input ce, input reset,
            input [31:0] flags,
            input [15:0] prg_ain, output [21:0] prg_aout,
            input prg_read, prg_write,                   // Read / write signals
            input [7:0] prg_din, output [7:0] prg_dout,
            output prg_allow,                            // Enable access to memory for the specified operation.
            input [13:0] chr_ain, output [21:0] chr_aout,
            output chr_allow,                      		// Allow write
            output reg vram_a10,                         // Value for A10 address line
            output vram_ce,                     			// True if the address should be routed to the internal 2kB VRAM.
				output reg irq); 

	reg [3:0] prg_bank;
	reg [7:0] chr_bank_0, chr_bank_1, chr_bank_2, chr_bank_3,
				 chr_bank_4, chr_bank_5, chr_bank_6, chr_bank_7;
	reg [3:0] prg_sel;
	reg [1:0] mirroring;
	reg irq_enable;
	reg [15:0] irq_counter;
	
	always @(posedge clk) if (reset) begin
		prg_bank <= 4'hF;
		chr_bank_0 <= 0;
		chr_bank_1 <= 0;
		chr_bank_2 <= 0;
		chr_bank_3 <= 0;
		chr_bank_4 <= 0;
		chr_bank_5 <= 0;
		chr_bank_6 <= 0;
		chr_bank_7 <= 0;
		mirroring <= 0;
		irq_counter <= 0;
	end else if (ce) begin
		if (prg_write)
			if(prg_ain >= 'h6000)				// Cover all from $6000 to $FFFF to maximize compatibility
				case(prg_ain & 'hf)				// Registers are mapped every 16 bytes
				'h0: chr_bank_0 <= prg_din[7:0];
				'h1: chr_bank_1 <= prg_din[7:0];
				'h2: chr_bank_2 <= prg_din[7:0];
				'h3: chr_bank_3 <= prg_din[7:0];
				'h4: chr_bank_4 <= prg_din[7:0];
				'h5: chr_bank_5 <= prg_din[7:0];
				'h6: chr_bank_6 <= prg_din[7:0];
				'h7: chr_bank_7 <= prg_din[7:0];
				'h8: prg_bank <= prg_din[3:0];
				'h9: mirroring <= prg_din[1:0];
				'ha: irq_enable <= prg_din[0];
				'hb: irq_counter[7:0] <= prg_din[7:0];
				'hc: irq_counter[15:8] <= prg_din[7:0];
//				'hd: RAM enable or EEPROM control
				endcase

		if (irq_enable)
			irq_counter <= irq_counter - 16'd1;
		else begin
			irq <= 1'b0;	// IRQ ACK
		end	
		
		if (irq_counter == 16'h0000)
			irq <= 1'b1;	// IRQ
			
	end
	
	always begin
      // mirroring
      casez(mirroring[1:0])
      2'b00:   vram_a10 = {chr_ain[10]};    // vertical
      2'b01:   vram_a10 = {chr_ain[11]};    // horizontal
      2'b1?:   vram_a10 = {mirroring[0]};   // single screen lower
      endcase
	end 
	
   reg [3:0] prgsel;  
	always begin
		case(prg_ain[15:14])
		2'b10: 	prgsel = prg_bank;			// $8000 is swapable
		2'b11: 	prgsel = 4'hF;					// $C000 is hardwired to last bank
		endcase
	end
	
   reg [7:0] chrsel;  
   always begin
    casez(chr_ain[12:10])
    0: chrsel = chr_bank_0;
    1: chrsel = chr_bank_1;
    2: chrsel = chr_bank_2;
    3: chrsel = chr_bank_3;
    4: chrsel = chr_bank_4;
    5: chrsel = chr_bank_5;
    6: chrsel = chr_bank_6;
    7: chrsel = chr_bank_7;
    endcase
   end	
	assign chr_aout = {4'b10_00, chrsel, chr_ain[9:0]};					// 1kB banks
	wire [21:0] prg_aout_tmp = {4'b00_00, prgsel, prg_ain[13:0]};  	// 16kB banks	
	
	wire prg_is_ram = (prg_ain >= 'h6000) && (prg_ain < 'h8000);
   wire [21:0] prg_ram = {9'b11_1100_000, prg_ain[12:0]};
   assign prg_aout = prg_is_ram ? prg_ram : prg_aout_tmp;
	assign prg_dout = prg_is_ram ? 8'h00 : 8'hFF;							// EEPROM stub
  
   assign prg_allow = prg_ain[15] && !prg_write ||
                     prg_is_ram;
	assign chr_allow = flags[15];
	assign vram_ce = chr_ain[13];
endmodule

// Tepples/Multi-discrete mapper
// This mapper can emulate other mappers,  such as mapper #0, mapper #2
module Mapper28(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                            // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                      // Allow write
                output reg vram_a10,                         // Value for A10 address line
                output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.
    reg [6:0] a53prg;    // output PRG ROM (A14-A20 on ROM)
    reg [1:0] a53chr;    // output CHR RAM (A13-A14 on RAM)
   
    reg [3:0] inner;    // "inner" bank at 01h
    reg [5:0] mode;     // mode register at 80h
    reg [5:0] outer;    // "outer" bank at 81h  
    reg [1:0] selreg;   // selector register
    
    // Allow writes to 0x5000 only when launching through the proper mapper ID.
    wire [7:0] mapper = flags[7:0];
    wire allow_select = (mapper == 8'd28); 

    always @(posedge clk) if (reset) begin
      mode[5:2] <= 0;         // NROM mode, 32K mode
      outer[5:0] <= 6'h3f;    // last bank
      inner <= 0;
      selreg <= 1;
      
      // Set value for mirroring
      if (mapper == 2 || mapper == 0 || mapper == 3)
        mode[1:0] <= flags[14] ? 2'b10 : 2'b11;
        
      // UNROM #2 - Current bank in $8000-$BFFF and fixed top half of outer bank in $C000-$FFFF
      if (mapper == 2) begin
        mode[5:2] <= 4'b1111; // 256K banks, UNROM mode
      end
		
      // CNROM #3 - Fixed PRG bank, switchable CHR bank.
      if (mapper == 3)
        selreg <= 0;

      // AxROM #7 - Switch 32kb rom bank + switchable nametables
      if (mapper == 7) begin
        mode[1:0] <= 2'b00;   // Switchable VRAM page.
        mode[5:2] <= 4'b1100; // 256K banks, (B)NROM mode
		  outer[5:0] <= 6'h00;
      end
    end else if (ce) begin
      if ((prg_ain[15:12] == 4'h5) & prg_write && allow_select)
			selreg <= {prg_din[7], prg_din[0]};        // select register
      if (prg_ain[15] & prg_write) begin
        case (selreg)
        2'h0:  {mode[0], a53chr}  <= {(mode[1] ? mode[0] : prg_din[4]), prg_din[1:0]};  // CHR RAM bank
        2'h1:  {mode[0], inner}   <= {(mode[1] ? mode[0] : prg_din[4]), prg_din[3:0]};  // "inner" bank
        2'h2:  {mode}             <= {prg_din[5:0]};                                    // mode register
        2'h3:  {outer}            <= {prg_din[5:0]};                                    // "outer" bank
        endcase
      end
    end
    
    always begin
      // mirroring mode
      casez(mode[1:0])
      2'b0?   :   vram_a10 = {mode[0]};        // 1 screen lower
      2'b10   :   vram_a10 = {chr_ain[10]};    // vertical
      2'b11   :   vram_a10 = {chr_ain[11]};    // horizontal
      endcase

      // PRG ROM bank size select
      casez({mode[5:2], prg_ain[14]})
      5'b00_0?_?  :  a53prg = {outer[5:0],             prg_ain[14]};  // 32K banks, (B)NROM mode
      5'b01_0?_?  :  a53prg = {outer[5:1], inner[0],   prg_ain[14]};  // 64K banks, (B)NROM mode
      5'b10_0?_?  :  a53prg = {outer[5:2], inner[1:0], prg_ain[14]};  // 128K banks, (B)NROM mode
      5'b11_0?_?  :  a53prg = {outer[5:3], inner[2:0], prg_ain[14]};  // 256K banks, (B)NROM mode
      
      5'b00_10_1,
      5'b00_11_0  :  a53prg = {outer[5:0], inner[0]};             // 32K banks, UNROM mode
      5'b01_10_1,
      5'b01_11_0  :  a53prg = {outer[5:1], inner[1:0]};           // 64K banks, UNROM mode
      5'b10_10_1,
      5'b10_11_0  :  a53prg = {outer[5:2], inner[2:0]};           // 128K banks, UNROM mode
      5'b11_10_1,
      5'b11_11_0  :  a53prg = {outer[5:3], inner[3:0]};           // 256K banks, UNROM mode
      
      default     :  a53prg = {outer[5:0],             prg_ain[14]};  // 16K fixed bank
      endcase
    end

  assign vram_ce = chr_ain[13];
  assign prg_aout = {1'b0, (a53prg & 7'b0011111), prg_ain[13:0]};
  assign prg_allow = prg_ain[15] && !prg_write;
  assign chr_allow = flags[15];
  assign chr_aout = {7'b10_0000_0, a53chr, chr_ain[12:0]};
endmodule

// Mapper 42, used for hacked FDS games converted to cartridge form
module Mapper42(input clk, input ce, input reset,
            input [31:0] flags,
            input [15:0] prg_ain, output [21:0] prg_aout,
            input prg_read, prg_write,                   // Read / write signals
            input [7:0] prg_din,
            output prg_allow,                            // Enable access to memory for the specified operation.
            input [13:0] chr_ain, output [21:0] chr_aout,
            output chr_allow,                      		// Allow write
            output vram_a10,                             // Value for A10 address line
            output vram_ce,                     			// True if the address should be routed to the internal 2kB VRAM.
				output reg irq); 

	reg [3:0] prg_bank;
	reg [3:0] chr_bank;
	reg [3:0] prg_sel;
	reg mirroring;
	reg irq_enable;
	reg [14:0] irq_counter;
	
	always @(posedge clk) if (reset) begin
		prg_bank <= 0;
		chr_bank <= 0;
		mirroring <= flags[14];
		irq_counter <= 0;
	end else if (ce) begin
		if (prg_write)
			case(prg_ain & 16'he003)
			16'h8000: chr_bank <= prg_din[3:0];
			16'he000: prg_bank <= prg_din[3:0];
			16'he001: mirroring <= prg_din[3];
			16'he002: irq_enable <= prg_din[1];
			endcase

		if (irq_enable)
			irq_counter <= irq_counter + 15'd1;
		else begin
			irq <= 1'b0;	// ACK
			irq_counter <= 0;
		end	
		
		if (irq_counter == 15'h6000)
			irq <= 1'b1;
			
	end
	
	always @* begin
/* PRG bank selection
	6000-7FFF: Selectable
	8000-9FFF: bank #0Ch
	A000-BFFF: bank #0Dh
	C000-DFFF: bank #0Eh
	E000-FFFF: bank #0Fh
*/	
		case(prg_ain[15:13])
		3'b011: 	prg_sel = prg_bank;                // $6000-$7FFF
		3'b100: 	prg_sel = 4'hC;
		3'b101: 	prg_sel = 4'hD;
		3'b110: 	prg_sel = 4'hE;
		3'b111: 	prg_sel = 4'hF;
		endcase
	end 
	assign prg_aout = {5'b0, prg_sel, prg_ain[12:0]};    		// 8kB banks
	assign chr_aout = {5'b10_000, chr_bank, chr_ain[12:0]};	// 8kB banks

	assign prg_allow = (prg_ain >= 16'h6000) && !prg_write;
	assign chr_allow = flags[15];
	assign vram_ce = chr_ain[13];
	assign vram_a10 = mirroring ? chr_ain[10] : chr_ain[11];
endmodule

// 11 - Color Dreams
// 66 - GxROM
module Mapper66(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                            // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                      // Allow write
                output vram_a10,                             // Value for A10 address line
                output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.
  reg [1:0] prg_bank;
  reg [3:0] chr_bank;
  wire GXROM = (flags[7:0] == 66);
  always @(posedge clk) if (reset) begin
    prg_bank <= 0;
    chr_bank <= 0;
  end else if (ce) begin
    if (prg_ain[15] & prg_write) begin
      if (GXROM)
        {prg_bank, chr_bank} <= {prg_din[5:4], 2'b0, prg_din[1:0]};
      else // Color Dreams
        {chr_bank, prg_bank} <= {prg_din[7:4], prg_din[1:0]};
    end
  end
  assign prg_aout = {5'b00_000, prg_bank, prg_ain[14:0]};
  assign prg_allow = prg_ain[15] && !prg_write;
  assign chr_allow = flags[15];
  assign chr_aout = {5'b10_000, chr_bank, chr_ain[12:0]};
  assign vram_ce = chr_ain[13];
  assign vram_a10 = flags[14] ? chr_ain[10] : chr_ain[11];
endmodule

// 34 - BxROM or NINA-001
module Mapper34(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                            // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                      // Allow write
                output vram_a10,                             // Value for A10 address line
                output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.
  reg [1:0] prg_bank;
  reg [3:0] chr_bank_0, chr_bank_1;
  
  wire NINA = (flags[13:11] != 0); // NINA is used when there is more than 8kb of CHR
  always @(posedge clk) if (reset) begin
    prg_bank <= 0;
    chr_bank_0 <= 0;
    chr_bank_1 <= 1; // To be compatible with BxROM
  end else if (ce && prg_write) begin
    if (!NINA) begin // BxROM
      if (prg_ain[15])
        prg_bank <= prg_din[1:0];
    end else begin // NINA
      if (prg_ain == 16'h7ffd)
        prg_bank <= prg_din[1:0];
      else if (prg_ain == 16'h7ffe)
        chr_bank_0 <= prg_din[3:0];
      else if (prg_ain == 16'h7fff)
        chr_bank_1 <= prg_din[3:0];
    end
  end

  wire [21:0] prg_aout_tmp = {5'b00_000, prg_bank, prg_ain[14:0]};
  assign chr_allow = flags[15];
  assign chr_aout = {6'b10_0000, chr_ain[12] == 0 ? chr_bank_0 : chr_bank_1, chr_ain[11:0]};
  assign vram_ce = chr_ain[13];
  assign vram_a10 = flags[14] ? chr_ain[10] : chr_ain[11];

  wire prg_is_ram = (prg_ain >= 'h6000 && prg_ain < 'h8000) && NINA;
  assign prg_allow = prg_ain[15] && !prg_write ||
                     prg_is_ram;
  wire [21:0] prg_ram = {9'b11_1100_000, prg_ain[12:0]};
  assign prg_aout = prg_is_ram ? prg_ram : prg_aout_tmp;
endmodule

// 41 - Caltron 6-in-1
module Mapper41(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                            // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                      // Allow write
                output vram_a10,                             // Value for A10 address line
                output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.
  reg [2:0] prg_bank;
  reg [1:0] chr_outer_bank, chr_inner_bank;
  reg mirroring;
  
  always @(posedge clk) if (reset) begin
    prg_bank <= 0;
    chr_outer_bank <= 0;
    chr_inner_bank <= 0;
    mirroring <= 0;
  end else if (ce && prg_write) begin
    if (prg_ain[15:11] == 5'b01100) begin
      {mirroring, chr_outer_bank, prg_bank} <= prg_ain[5:0];
    end else if (prg_ain[15] && prg_bank[2]) begin
      // The Inner CHR Bank Select only can be written while the PRG ROM bank is 4, 5, 6, or 7
      chr_inner_bank <= prg_din[1:0];
    end
  end

  assign prg_aout = {4'b00_00, prg_bank, prg_ain[14:0]};
  assign chr_allow = flags[15];
  assign chr_aout = {5'b10_000, chr_outer_bank, chr_inner_bank, chr_ain[12:0]};
  assign vram_ce = chr_ain[13];
  assign vram_a10 = mirroring ? chr_ain[11] : chr_ain[10];
  assign prg_allow = prg_ain[15] && !prg_write;
endmodule

// #68 - Sunsoft-4 - Game After Burner, and some japanese games. MAX: 128kB PRG, 256kB CHR
module Mapper68(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                            // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                      // Allow write
                output vram_a10,                             // Value for A10 address line
                output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.
  reg [6:0] chr_bank_0, chr_bank_1, chr_bank_2, chr_bank_3;
  reg [6:0] nametable_0, nametable_1;
  reg [2:0] prg_bank;
  reg use_chr_rom;
  reg mirroring;
  always @(posedge clk) if (reset) begin
    chr_bank_0 <= 0;
    chr_bank_1 <= 0;
    chr_bank_2 <= 0;
    chr_bank_3 <= 0;
    nametable_0 <= 0;
    nametable_1 <= 0;
    prg_bank <= 0;
    use_chr_rom <= 0;
    mirroring <= 0;
  end else if (ce) begin
    if (prg_ain[15] && prg_write) begin
//      $write("REG[%d] <= %X\n", prg_ain[14:12], prg_din);
      case(prg_ain[14:12])
      0: chr_bank_0  <= prg_din[6:0]; // $8000-$8FFF: 2kB CHR bank at $0000
      1: chr_bank_1  <= prg_din[6:0]; // $9000-$9FFF: 2kB CHR bank at $0800
      2: chr_bank_2  <= prg_din[6:0]; // $A000-$AFFF: 2kB CHR bank at $1000
      3: chr_bank_3  <= prg_din[6:0]; // $B000-$BFFF: 2kB CHR bank at $1800
      4: nametable_0 <= prg_din[6:0]; // $C000-$CFFF: 1kB Nametable register 0 at $2000
      5: nametable_1 <= prg_din[6:0]; // $D000-$DFFF: 1kB Nametable register 1 at $2400
      6: {use_chr_rom, mirroring} <= {prg_din[4], prg_din[0]};  // $E000-$EFFF: Nametable control
      7: prg_bank <= prg_din[2:0]; 
      endcase
    end
  end
  wire [2:0] prgout = (prg_ain[14] ? 3'b111 : prg_bank);
  assign prg_aout = {5'b00_000, prgout, prg_ain[13:0]};
  assign prg_allow = prg_ain[15] && !prg_write;

  reg [6:0] chrout;  
  always begin
    casez(chr_ain[12:11])
    0: chrout = chr_bank_0;
    1: chrout = chr_bank_1;
    2: chrout = chr_bank_2;
    3: chrout = chr_bank_3;
    endcase
  end
  assign vram_a10 = mirroring ? chr_ain[11] : chr_ain[10];
  wire [6:0] nameout = (vram_a10 == 0) ? nametable_0 : nametable_1;
 
  assign chr_allow = flags[15];
  assign chr_aout = (chr_ain[13] == 0) ? {4'b10_00, chrout, chr_ain[10:0]} : {5'b10_001, nameout, chr_ain[9:0]};
  assign vram_ce = chr_ain[13] && !use_chr_rom;

endmodule

// 69 - Sunsoft FME-7
module Mapper69(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                          // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                             // Allow write
                output reg vram_a10,                          // Value for A10 address line
                output vram_ce,                               // True if the address should be routed to the internal 2kB VRAM.
                output reg irq);
  reg [7:0] chr_bank[0:7];
  reg [4:0] prg_bank[0:3];
  reg [1:0] mirroring;
  reg irq_countdown, irq_trigger;
  reg [15:0] irq_counter;
  reg [3:0] addr;
  reg ram_enable, ram_select;
  wire [16:0] new_irq_counter = irq_counter - {15'b0, irq_countdown};
  always @(posedge clk) if (reset) begin
    chr_bank[0] <= 0;
    chr_bank[1] <= 0;
    chr_bank[2] <= 0;
    chr_bank[3] <= 0;
    chr_bank[4] <= 0;
    chr_bank[5] <= 0;
    chr_bank[6] <= 0;
    chr_bank[7] <= 0;
    prg_bank[0] <= 0;
    prg_bank[1] <= 0;
    prg_bank[2] <= 0;
    prg_bank[3] <= 0;
    mirroring <= 0;
    irq_countdown <= 0;
    irq_trigger <= 0;
    irq_counter <= 0;
    addr <= 0;
    ram_enable <= 0;
    ram_select <= 0;
    irq <= 0;
  end else if (ce) begin
    irq_counter <= new_irq_counter[15:0];
    if (irq_trigger && new_irq_counter[16]) irq <= 1;
    if (!irq_trigger) irq <= 0;
      
    if (prg_ain[15] & prg_write) begin
      case (prg_ain[14:13])
      0: addr <= prg_din[3:0];
      1: begin
          case(addr)
          0,1,2,3,4,5,6,7: chr_bank[addr[2:0]] <= prg_din;
          8,9,10,11:       prg_bank[addr[1:0]] <= prg_din[4:0];
          12:              mirroring <= prg_din[1:0];
          13:              {irq_countdown, irq_trigger} <= {prg_din[7], prg_din[0]};
          14:              irq_counter[7:0] <= prg_din;
          15:              irq_counter[15:8] <= prg_din;
          endcase
          if (addr == 8) {ram_enable, ram_select} <= prg_din[7:6];
        end
      endcase
    end
  end
  always begin
    casez(mirroring[1:0])
    2'b00   :   vram_a10 = {chr_ain[10]};    // vertical
    2'b01   :   vram_a10 = {chr_ain[11]};    // horizontal
    2'b1?   :   vram_a10 = {mirroring[0]};   // 1 screen lower
    endcase
  end
  reg [4:0] prgout;
  reg [7:0] chrout;
  always begin
    casez(prg_ain[15:13])
    3'b011:  prgout = prg_bank[0];
    3'b100:  prgout = prg_bank[1];
    3'b101:  prgout = prg_bank[2];
    3'b110:  prgout = prg_bank[3];
    3'b111:  prgout = 5'b11111;
    default: prgout = 5'bxxxxx;
    endcase
    chrout = chr_bank[chr_ain[12:10]];
  end
  wire ram_cs = (prg_ain[15] == 0 && ram_select);
  assign prg_aout = {1'b0, ram_cs, 2'b00, prgout[4:0], prg_ain[12:0]};
  assign prg_allow = ram_cs ? ram_enable : !prg_write;
  assign chr_allow = flags[15];
  assign chr_aout = {4'b10_00, chrout, chr_ain[9:0]};
  assign vram_ce = chr_ain[13];
endmodule

// #71,#232 - Camerica
module Mapper71(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                            // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                      // Allow write
                output vram_a10,                             // Value for A10 address line
                output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.
  reg [3:0] prg_bank;
  reg ciram_select;
  wire mapper232 = (flags[7:0] == 232);
  always @(posedge clk) if (reset) begin
    prg_bank <= 0;
    ciram_select <= 0;
  end else if (ce) begin
    if (prg_ain[15] && prg_write) begin
      $write("%X <= %X (bank = %x)\n", prg_ain, prg_din, prg_bank);
      if (!prg_ain[14] && mapper232) // $8000-$BFFF Outer bank select (only on iNES 232)
        prg_bank[3:2] <= prg_din[4:3];
      if (prg_ain[14:13] == 0)       // $8000-$9FFF Fire Hawk Mirroring
        ciram_select <= prg_din[4];
      if (prg_ain[14])               // $C000-$FFFF Bank select
        prg_bank <= {mapper232 ? prg_bank[3:2] : prg_din[3:2], prg_din[1:0]};
    end
  end
  reg [3:0] prgout;
  always begin
    casez({prg_ain[14], mapper232})
    2'b0?: prgout = prg_bank;
    2'b10: prgout = 4'b1111;
    2'b11: prgout = {prg_bank[3:2], 2'b11};
    endcase
  end
  assign prg_aout = {4'b00_00, prgout, prg_ain[13:0]};
  assign prg_allow = prg_ain[15] && !prg_write;
  assign chr_allow = flags[15];
  assign chr_aout = {9'b10_0000_000, chr_ain[12:0]};
  assign vram_ce = chr_ain[13];
  // XXX(ludde): Fire hawk uses flags[14] == 0 while no other game seems to do that.
  // So when flags[14] == 0 we use ciram_select instead.
  assign vram_a10 = flags[14] ? chr_ain[10] : ciram_select;
endmodule

// #79,#113 - NINA-03 / NINA-06
module Mapper79(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                            // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                      // Allow write
                output vram_a10,                             // Value for A10 address line
                output vram_ce);                             // True if the address should be routed to the internal 2kB VRAM.
  reg [2:0] prg_bank;
  reg [3:0] chr_bank;
  reg mirroring;  // 0: Horizontal, 1: Vertical
  wire mapper113 = (flags[7:0] == 113); // NINA-06
  always @(posedge clk) if (reset) begin
    prg_bank <= 0;
    chr_bank <= 0;
    mirroring <= 0;
  end else if (ce) begin
    if (prg_ain[15:13] == 3'b010 && prg_ain[8] && prg_write)
      {mirroring, chr_bank[3], prg_bank, chr_bank[2:0]} <= prg_din;
  end
  assign prg_aout = {4'b00_00, prg_bank, prg_ain[14:0]};
  assign prg_allow = prg_ain[15] && !prg_write;
  assign chr_allow = flags[15];
  assign chr_aout = {5'b10_000, chr_bank, chr_ain[12:0]};
  assign vram_ce = chr_ain[13];
  wire mirrconfig = mapper113 ? mirroring : flags[14]; // Mapper #13 has mapper controlled mirroring
  assign vram_a10 = mirrconfig ? chr_ain[10] : chr_ain[11]; // 0: horiz, 1: vert
endmodule

// #105 - NES-EVENT. Retrofits an MMC3 with lots of extra logic.
module NesEvent(input clk, input ce, input reset,
                input [15:0] prg_ain, output reg [21:0] prg_aout,
                input [13:0] chr_ain, output [21:0] chr_aout,
                input [3:0] mmc1_chr,                   // Upper 4 CHR output control bits from MMC chip
                input [21:0] mmc1_aout,                 // PRG output address from MMC chip
                output irq);
  // $A000-BFFF:   [...I OAA.]
  //      I = IRQ control / initialization toggle
  //      O = PRG Mode/Chip select
  //      A = PRG Reg 'A'
  // Mapper gets "initialized" by setting I bit to 0 then to 1.
  // On powerup and reset, the first 32k of PRG (from the first PRG chip) is selected at $8000 *no matter what*.
  // PRG cannot be swapped until the mapper has been "initialized" by setting the 'I' bit to 0, then to '1'.  This
  // toggling will "unlock" PRG swapping on the mapper.
  reg unlocked, old_val;
  reg [29:0] counter;
  
  reg [3:0] oldbits;
  always @(posedge clk) if (reset) begin
    old_val <= 0;
    unlocked <= 0;
    counter <= 0;
  end else if (ce) begin
    // Handle unlock.
    if (mmc1_chr[3] && !old_val) unlocked <= 1;
    old_val <= mmc1_chr[3];
    // The 'I' bit in $A000 controls the IRQ counter.  When cleared, the IRQ counter counts up every cycle.  When
    // set, the IRQ counter is reset to 0 and stays there (does not count), and the pending IRQ is acknowledged.
    counter <= mmc1_chr[3] ? 0 : counter + 1;
    
    if (mmc1_chr != oldbits) begin
      $write("NESEV Control Bits: %X => %X (%d)\n", oldbits, mmc1_chr, unlocked);
      oldbits <= mmc1_chr;
    end
  end
  // In the official tournament, 'C' was closed, and the others were open, so the counter had to reach $2800000.
  assign irq = (counter[29:25] == 5'b10100);
  always begin
    if (!prg_ain[15]) begin
      // WRAM is always routed as usual.
      prg_aout = mmc1_aout; 
    end else if (!unlocked) begin
      // Not initialized yet, mapper switch disabled.
      prg_aout = {7'b00_0000_0, prg_ain[14:0]}; 
    end else if (mmc1_chr[2] == 0) begin
      // O=0:  Use first PRG chip (first 128k), use 'A' PRG Reg, 32k swap
      prg_aout = {5'b00_000, mmc1_chr[1:0], prg_ain[14:0]};
    end else begin
      // O=1:  Use second PRG chip (second 128k), use 'B' PRG Reg, MMC1 style swap
      prg_aout = mmc1_aout;
    end
  end
  // 8kB CHR RAM.
  assign chr_aout = {9'b10_0000_000, chr_ain[12:0]};
endmodule

// mapper 165
module Mapper165(input clk, input ce, input reset,
            input [31:0] flags,
            input [15:0] prg_ain, output [21:0] prg_aout,
            input prg_read, prg_write,                   // Read / write signals
            input [7:0] prg_din,
            output prg_allow,                            // Enable access to memory for the specified operation.
            input chr_read, input [13:0] chr_ain, output [21:0] chr_aout,
            output chr_allow,                            // Allow write
            output vram_a10,                             // Value for A10 address line
            output vram_ce,                              // True if the address should be routed to the internal 2kB VRAM.
            output reg irq);
  reg [2:0] bank_select;             // Register to write to next
  reg prg_rom_bank_mode;             // Mode for PRG banking
  reg chr_a12_invert;                // Mode for CHR banking
  reg mirroring;                     // 0 = vertical, 1 = horizontal
  reg irq_enable, irq_reload;        // IRQ enabled, and IRQ reload requested
  reg [7:0] irq_latch, counter;      // IRQ latch value and current counter
  reg ram_enable, ram_protect;       // RAM protection bits
  reg [5:0] prg_bank_0, prg_bank_1;  // Selected PRG banks
  wire prg_is_ram;

  reg [6:0] chr_bank_0, chr_bank_1;  // Selected CHR banks
  reg [7:0] chr_bank_2, chr_bank_3, chr_bank_4, chr_bank_5;
  reg latch_0, latch_1;
  
  wire [7:0] new_counter = (counter == 0 || irq_reload) ? irq_latch : counter - 1;
  reg [3:0] a12_ctr; 
   
  always @(posedge clk) if (reset) begin
    irq <= 0;
    bank_select <= 0;
    prg_rom_bank_mode <= 0;
    chr_a12_invert <= 0;
    mirroring <= flags[14];
    {irq_enable, irq_reload} <= 0;
    {irq_latch, counter} <= 0;
    {ram_enable, ram_protect} <= 0;
    {chr_bank_0, chr_bank_1, chr_bank_2, chr_bank_3, chr_bank_4, chr_bank_5} <= 0;
    {prg_bank_0, prg_bank_1} <= 0;
    a12_ctr <= 0;
  end else if (ce) begin
  
    if (prg_write && prg_ain[15]) begin
      case({prg_ain[14], prg_ain[13], prg_ain[0]})
      3'b00_0: {chr_a12_invert, prg_rom_bank_mode, bank_select} <= {prg_din[7], prg_din[6], prg_din[2:0]}; // Bank select ($8000-$9FFE, even)
      3'b00_1: begin // Bank data ($8001-$9FFF, odd)
        case (bank_select) 
        0: chr_bank_0 <= prg_din[7:1];  // Select 2 KB CHR bank at PPU $0000-$07FF (or $1000-$17FF);
        1: chr_bank_1 <= prg_din[7:1];  // Select 2 KB CHR bank at PPU $0800-$0FFF (or $1800-$1FFF);
        2: chr_bank_2 <= prg_din;       // Select 1 KB CHR bank at PPU $1000-$13FF (or $0000-$03FF);
        3: chr_bank_3 <= prg_din;       // Select 1 KB CHR bank at PPU $1400-$17FF (or $0400-$07FF);
        4: chr_bank_4 <= prg_din;       // Select 1 KB CHR bank at PPU $1800-$1BFF (or $0800-$0BFF);
        5: chr_bank_5 <= prg_din;       // Select 1 KB CHR bank at PPU $1C00-$1FFF (or $0C00-$0FFF);
        6: prg_bank_0 <= prg_din[5:0];  // Select 8 KB PRG ROM bank at $8000-$9FFF (or $C000-$DFFF);
        7: prg_bank_1 <= prg_din[5:0];  // Select 8 KB PRG ROM bank at $A000-$BFFF
        endcase
      end
      3'b01_0: mirroring <= prg_din[0];                   // Mirroring ($A000-$BFFE, even)
      3'b01_1: {ram_enable, ram_protect} <= prg_din[7:6]; // PRG RAM protect ($A001-$BFFF, odd)
      3'b10_0: irq_latch <= prg_din;                      // IRQ latch ($C000-$DFFE, even)
      3'b10_1: irq_reload <= 1;                           // IRQ reload ($C001-$DFFF, odd)
      3'b11_0: begin irq_enable <= 0; irq <= 0; end       // IRQ disable ($E000-$FFFE, even)
      3'b11_1: irq_enable <= 1;                           // IRQ enable ($E001-$FFFF, odd)
      endcase
    end

    // Trigger IRQ counter on rising edge of chr_ain[12]
    // All MMC3A's and non-Sharp MMC3B's will generate only a single IRQ when $C000 is $00.
    // This is because this version of the MMC3 generates IRQs when the scanline counter is decremented to 0.
    // In addition, writing to $C001 with $C000 still at $00 will result in another single IRQ being generated.
    // In the community, this is known as the "alternate" or "old" behavior.
    // All MMC3C's and Sharp MMC3B's will generate an IRQ on each scanline while $C000 is $00.
    // This is because this version of the MMC3 generates IRQs when the scanline counter is equal to 0.
    // In the community, this is known as the "normal" or "new" behavior.
    if (chr_ain[12] && a12_ctr == 0) begin
      counter <= new_counter;
      if ( (counter != 0 || irq_reload) && new_counter == 0 && irq_enable) begin
//        $write("MMC3 SCANLINE IRQ!\n");
        irq <= 1;
      end
      irq_reload <= 0;      
    end
    a12_ctr <= chr_ain[12] ? 4'b1111 : (a12_ctr != 0) ? a12_ctr - 4'b0001 : a12_ctr;
  end

  // The PRG bank to load. Each increment here is 8kb. So valid values are 0..63.
  reg [5:0] prgsel;
  always @* begin
    casez({prg_ain[14:13], prg_rom_bank_mode})
    3'b00_0: prgsel = prg_bank_0;  // $8000 mode 0
    3'b00_1: prgsel = 6'b111110;   // $8000 fixed to second last bank
    3'b01_?: prgsel = prg_bank_1;  // $A000 mode 0,1
    3'b10_0: prgsel = 6'b111110;   // $C000 fixed to second last bank
    3'b10_1: prgsel = prg_bank_0;  // $C000 mode 1
    3'b11_?: prgsel = 6'b111111;   // $E000 fixed to last bank
    endcase
  end
  wire [21:0] prg_aout_tmp = {3'b00_0,  prgsel, prg_ain[12:0]};

// PPU reads $0FD0: latch 0 is set to $FD for subsequent reads
// PPU reads $0FE0: latch 0 is set to $FE for subsequent reads
// PPU reads $1FD0 through $1FDF: latch 1 is set to $FD for subsequent reads
// PPU reads $1FE0 through $1FEF: latch 1 is set to $FE for subsequent reads
  always @(posedge clk) if (ce && chr_read) begin
    latch_0 <= (chr_ain & 14'h3fff) == 14'h0fd0 ? 0 : (chr_ain & 14'h3fff) == 14'h0fe0 ? 1 : latch_0;
    latch_1 <= (chr_ain & 14'h3ff0) == 14'h1fd0 ? 0 : (chr_ain & 14'h3ff0) == 14'h1fe0 ? 1 : latch_1;
  end

  // The CHR bank to load. Each increment here is 1kb. So valid values are 0..255.
  reg [7:0] chrsel;
  always @* begin
    casez({chr_ain[12] ^ chr_a12_invert, latch_0, latch_1})
    3'b0_0?: chrsel = {chr_bank_0, chr_ain[10]};	// 2Kb page
    3'b0_1?: chrsel = {chr_bank_1, chr_ain[10]};	// 2Kb page
    3'b1_?0: chrsel = chr_bank_2;
    3'b1_?1: chrsel = chr_bank_4;
    endcase
  end
  
  assign {chr_allow, chr_aout} = {flags[15] && (chrsel < 4), 4'b10_00, chrsel, chr_ain[9:0]};

  assign prg_is_ram = prg_ain >= 'h6000 && prg_ain < 'h8000 && ram_enable && !(ram_protect && prg_write);
  assign prg_allow = prg_ain[15] && !prg_write || prg_is_ram;
  wire [21:0] prg_ram = {9'b11_1100_000, prg_ain[12:0]};
  assign prg_aout = prg_is_ram ? prg_ram : prg_aout_tmp;
  assign vram_a10 = mirroring ? chr_ain[11] : chr_ain[10];  
  assign vram_ce = chr_ain[13];
endmodule

// iNES Mapper 228 represents the board used by Active Enterprises for Action 52 and Cheetahmen II.
module Mapper228(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                          // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                             // Allow write
                output vram_a10,                              // Value for A10 address line
                output vram_ce);                              // True if the address should be routed to the internal 2kB VRAM.
  reg mirroring;
  reg [1:0] prg_chip;
  reg [4:0] prg_bank;
  reg prg_bank_mode;
  reg [5:0] chr_bank;
  always @(posedge clk) if (reset) begin
    {mirroring, prg_chip, prg_bank, prg_bank_mode} <= 0;
    chr_bank <= 0;
  end else if (ce) begin
    if (prg_ain[15] & prg_write) begin
      {mirroring, prg_chip, prg_bank, prg_bank_mode} <= prg_ain[13:5];
      chr_bank <= {prg_ain[3:0], prg_din[1:0]};
    end
  end
  assign vram_a10 = mirroring ? chr_ain[11] : chr_ain[10];
  wire prglow = prg_bank_mode ? prg_bank[0] : prg_ain[14];
  wire [1:0] addrsel = {prg_chip[1], prg_chip[1] ^ prg_chip[0]};
  assign prg_aout = {1'b0, addrsel, prg_bank[4:1], prglow, prg_ain[13:0]};
  assign prg_allow = prg_ain[15] && !prg_write;
  assign chr_allow = flags[15];
  assign chr_aout = {3'b10_0, chr_bank, chr_ain[12:0]};
  assign vram_ce = chr_ain[13];
endmodule

module Mapper234(input clk, input ce, input reset,
                input [31:0] flags,
                input [15:0] prg_ain, output [21:0] prg_aout,
                input prg_read, prg_write,                   // Read / write signals
                input [7:0] prg_din,
                output prg_allow,                          // Enable access to memory for the specified operation.
                input [13:0] chr_ain, output [21:0] chr_aout,
                output chr_allow,                             // Allow write
                output vram_a10,                              // Value for A10 address line
                output vram_ce);                              // True if the address should be routed to the internal 2kB VRAM.
  reg [2:0] block, inner_chr;
  reg mode, mirroring, inner_prg;
  always @(posedge clk) if (reset) begin
    block <= 0;
    {mode, mirroring} <= 0;
    inner_chr <= 0;
    inner_prg <= 0;
  end else if (ce) begin
    if (prg_read && prg_ain[15:7] == 9'b1111_1111_1) begin
      // Outer bank control $FF80 - $FF9F
      if (prg_ain[6:0] < 7'h20 && (block == 0)) begin
        {mirroring, mode} <= prg_din[7:6];
        block <= prg_din[3:1];
        {inner_chr[2], inner_prg} <= {prg_din[0], prg_din[0]};
      end
      // Inner bank control ($FFE8-$FFF7)
      if (prg_ain[6:0] >= 7'h68 && prg_ain[6:0] < 7'h78) begin
        {inner_chr[2], inner_prg} <= mode ? {prg_din[6], prg_din[0]} : {inner_chr[2], inner_prg};
        inner_chr[1:0] <= prg_din[5:4];
      end
    end
  end
  assign vram_a10 = mirroring ? chr_ain[11] : chr_ain[10];
  assign prg_aout = {3'b00_0, block, inner_prg, prg_ain[14:0]};
  assign chr_aout = {3'b10_0, block, inner_chr, chr_ain[12:0]};
  assign prg_allow = prg_ain[15] && !prg_write;
  assign chr_allow = flags[15];
  assign vram_ce = chr_ain[13];
endmodule

module MultiMapper(input clk, input ce, input ppu_ce, input reset,
                   input [19:0] ppuflags,                           // Misc flags from PPU for MMC5 cheating
                   input [31:0] flags,                              // Misc flags from ines header {prg_size(3), chr_size(3), mapper(8)}
                   input [15:0] prg_ain, output reg [21:0] prg_aout,// PRG Input / Output Address Lines
                   input prg_read, prg_write,                       // PRG Read / write signals
                   input [7:0] prg_din, output reg [7:0] prg_dout,  // PRG Data
                   input [7:0] prg_from_ram,                        // PRG Data from RAM
                   output reg prg_allow,                            // PRG Allow write access
                   input chr_read,                                  // Read from CHR
                   input [13:0] chr_ain, output reg [21:0] chr_aout,// CHR Input / Output Address Lines
                   output reg [7:0] chr_dout,                       // Value to override CHR data with
                   output reg has_chr_dout,                         // True if CHR data should be overridden
                   output reg chr_allow,                            // CHR Allow write
                   output reg vram_a10,                             // CHR Value for A10 address line
                   output reg vram_ce,                              // CHR True if the address should be routed to the internal 2kB VRAM.
                   output reg irq);
  wire mmc0_prg_allow, mmc0_vram_a10, mmc0_vram_ce, mmc0_chr_allow;
  wire [21:0] mmc0_prg_addr, mmc0_chr_addr;
  MMC0 mmc0(clk, ce, flags, prg_ain, mmc0_prg_addr, prg_read, prg_write, prg_din, mmc0_prg_allow,
                            chr_ain, mmc0_chr_addr, mmc0_chr_allow, mmc0_vram_a10, mmc0_vram_ce);

  wire mmc1_prg_allow, mmc1_vram_a10, mmc1_vram_ce, mmc1_chr_allow;
  wire [21:0] mmc1_prg_addr, mmc1_chr_addr;
  MMC1 mmc1(clk, ce, reset, flags, prg_ain, mmc1_prg_addr, prg_read, prg_write, prg_din, mmc1_prg_allow,
                                   chr_ain, mmc1_chr_addr, mmc1_chr_allow, mmc1_vram_a10, mmc1_vram_ce);

  wire map28_prg_allow, map28_vram_a10, map28_vram_ce, map28_chr_allow;
  wire [21:0] map28_prg_addr, map28_chr_addr;
  Mapper28 map28(clk, ce, reset, flags, prg_ain, map28_prg_addr, prg_read, prg_write, prg_din, map28_prg_allow,
                                        chr_ain, map28_chr_addr, map28_chr_allow, map28_vram_a10, map28_vram_ce);

  wire mmc2_prg_allow, mmc2_vram_a10, mmc2_vram_ce, mmc2_chr_allow;
  wire [21:0] mmc2_prg_addr, mmc2_chr_addr;
  MMC2 mmc2(clk, ppu_ce, reset, flags, prg_ain, mmc2_prg_addr, prg_read, prg_write, prg_din, mmc2_prg_allow,
                                   chr_read, chr_ain, mmc2_chr_addr, mmc2_chr_allow, mmc2_vram_a10, mmc2_vram_ce);

  wire mmc3_prg_allow, mmc3_vram_a10, mmc3_vram_ce, mmc3_chr_allow, mmc3_irq;
  wire [21:0] mmc3_prg_addr, mmc3_chr_addr;
  MMC3 mmc3(clk, ppu_ce, reset, flags, prg_ain, mmc3_prg_addr, prg_read, prg_write, prg_din, mmc3_prg_allow,
                                   chr_ain, mmc3_chr_addr, mmc3_chr_allow, mmc3_vram_a10, mmc3_vram_ce, mmc3_irq);

  wire mmc4_prg_allow, mmc4_vram_a10, mmc4_vram_ce, mmc4_chr_allow;
  wire [21:0] mmc4_prg_addr, mmc4_chr_addr;
  MMC4 mmc4(clk, ppu_ce, reset, flags, prg_ain, mmc4_prg_addr, prg_read, prg_write, prg_din, mmc4_prg_allow,
                                   chr_read, chr_ain, mmc4_chr_addr, mmc4_chr_allow, mmc4_vram_a10, mmc4_vram_ce);

  wire mmc5_prg_allow, mmc5_vram_a10, mmc5_vram_ce, mmc5_chr_allow, mmc5_irq;
  wire [21:0] mmc5_prg_addr, mmc5_chr_addr;
  wire [7:0] mmc5_chr_dout, mmc5_prg_dout;
  wire mmc5_has_chr_dout;
  MMC5 mmc5(clk, ppu_ce, reset, flags, ppuflags, prg_ain, mmc5_prg_addr, prg_read, prg_write, prg_din, mmc5_prg_dout, mmc5_prg_allow,
                                   chr_ain, mmc5_chr_addr, mmc5_chr_dout, mmc5_has_chr_dout, 
                                   mmc5_chr_allow, mmc5_vram_a10, mmc5_vram_ce, mmc5_irq);

  wire map13_prg_allow, map13_vram_a10, map13_vram_ce, map13_chr_allow;
  wire [21:0] map13_prg_addr, map13_chr_addr;
  Mapper13 map13(clk, ce, reset, flags, prg_ain, map13_prg_addr, prg_read, prg_write, prg_din, map13_prg_allow,
                                        chr_ain, map13_chr_addr, map13_chr_allow, map13_vram_a10, map13_vram_ce);

  wire map15_prg_allow, map15_vram_a10, map15_vram_ce, map15_chr_allow;
  wire [21:0] map15_prg_addr, map15_chr_addr;
  Mapper15 map15(clk, ce, reset, flags, prg_ain, map15_prg_addr, prg_read, prg_write, prg_din, map15_prg_allow,
                                        chr_ain, map15_chr_addr, map15_chr_allow, map15_vram_a10, map15_vram_ce);

  wire map16_prg_allow, map16_vram_a10, map16_vram_ce, map16_chr_allow, map16_irq;
  wire [21:0] map16_prg_addr, map16_chr_addr;
  wire [7:0] map16_prg_dout;
  Mapper16 map16(clk, ce, reset, flags, prg_ain, map16_prg_addr, prg_read, prg_write, prg_din, map16_prg_dout, map16_prg_allow,
                                        chr_ain, map16_chr_addr, map16_chr_allow, map16_vram_a10, map16_vram_ce, map16_irq);

  wire map34_prg_allow, map34_vram_a10, map34_vram_ce, map34_chr_allow;
  wire [21:0] map34_prg_addr, map34_chr_addr;
  Mapper34 map34(clk, ce, reset, flags, prg_ain, map34_prg_addr, prg_read, prg_write, prg_din, map34_prg_allow,
                                        chr_ain, map34_chr_addr, map34_chr_allow, map34_vram_a10, map34_vram_ce);

  wire map41_prg_allow, map41_vram_a10, map41_vram_ce, map41_chr_allow;
  wire [21:0] map41_prg_addr, map41_chr_addr;
  Mapper41 map41(clk, ce, reset, flags, prg_ain, map41_prg_addr, prg_read, prg_write, prg_din, map41_prg_allow,
                                        chr_ain, map41_chr_addr, map41_chr_allow, map41_vram_a10, map41_vram_ce);

  wire map42_prg_allow, map42_vram_a10, map42_vram_ce, map42_chr_allow, map42_irq;
  wire [21:0] map42_prg_addr, map42_chr_addr;
  Mapper42 map42(clk, ce, reset, flags, prg_ain, map42_prg_addr, prg_read, prg_write, prg_din, map42_prg_allow,
                                        chr_ain, map42_chr_addr, map42_chr_allow, map42_vram_a10, map42_vram_ce, map42_irq);

  wire map66_prg_allow, map66_vram_a10, map66_vram_ce, map66_chr_allow;
  wire [21:0] map66_prg_addr, map66_chr_addr;
  Mapper66 map66(clk, ce, reset, flags, prg_ain, map66_prg_addr, prg_read, prg_write, prg_din, map66_prg_allow,
                                        chr_ain, map66_chr_addr, map66_chr_allow, map66_vram_a10, map66_vram_ce);

  wire map68_prg_allow, map68_vram_a10, map68_vram_ce, map68_chr_allow;
  wire [21:0] map68_prg_addr, map68_chr_addr;
  Mapper68 map68(clk, ce, reset, flags, prg_ain, map68_prg_addr, prg_read, prg_write, prg_din, map68_prg_allow,
                                        chr_ain, map68_chr_addr, map68_chr_allow, map68_vram_a10, map68_vram_ce);

  wire map69_prg_allow, map69_vram_a10, map69_vram_ce, map69_chr_allow, map69_irq;
  wire [21:0] map69_prg_addr, map69_chr_addr;
  Mapper69 map69(clk, ce, reset, flags, prg_ain, map69_prg_addr, prg_read, prg_write, prg_din, map69_prg_allow,
                                        chr_ain, map69_chr_addr, map69_chr_allow, map69_vram_a10, map69_vram_ce, map69_irq);

  wire map71_prg_allow, map71_vram_a10, map71_vram_ce, map71_chr_allow;
  wire [21:0] map71_prg_addr, map71_chr_addr;
  Mapper71 map71(clk, ce, reset, flags, prg_ain, map71_prg_addr, prg_read, prg_write, prg_din, map71_prg_allow,
                                        chr_ain, map71_chr_addr, map71_chr_allow, map71_vram_a10, map71_vram_ce);

  wire map79_prg_allow, map79_vram_a10, map79_vram_ce, map79_chr_allow;
  wire [21:0] map79_prg_addr, map79_chr_addr;
  Mapper79 map79(clk, ce, reset, flags, prg_ain, map79_prg_addr, prg_read, prg_write, prg_din, map79_prg_allow,
                                        chr_ain, map79_chr_addr, map79_chr_allow, map79_vram_a10, map79_vram_ce);

  wire map165_prg_allow, map165_vram_a10, map165_vram_ce, map165_chr_allow, map165_irq;
  wire [21:0] map165_prg_addr, map165_chr_addr;
  Mapper165 map165(clk, ppu_ce, reset, flags, prg_ain, map165_prg_addr, prg_read, prg_write, prg_din, map165_prg_allow,
													 chr_read, chr_ain, map165_chr_addr, map165_chr_allow, map165_vram_a10, map165_vram_ce, map165_irq);

  wire map228_prg_allow, map228_vram_a10, map228_vram_ce, map228_chr_allow;
  wire [21:0] map228_prg_addr, map228_chr_addr;
  Mapper228 map228(clk, ce, reset, flags, prg_ain, map228_prg_addr, prg_read, prg_write, prg_din, map228_prg_allow,
                                          chr_ain, map228_chr_addr, map228_chr_allow, map228_vram_a10, map228_vram_ce);


  wire map234_prg_allow, map234_vram_a10, map234_vram_ce, map234_chr_allow;
  wire [21:0] map234_prg_addr, map234_chr_addr;
  Mapper234 map234(clk, ce, reset, flags, prg_ain, map234_prg_addr, prg_read, prg_write, prg_from_ram, map234_prg_allow,
                                          chr_ain, map234_chr_addr, map234_chr_allow, map234_vram_a10, map234_vram_ce);

  wire rambo1_prg_allow, rambo1_vram_a10, rambo1_vram_ce, rambo1_chr_allow, rambo1_irq;
  wire [21:0] rambo1_prg_addr, rambo1_chr_addr;
  Rambo1 rambo1(clk, ce, reset, flags, prg_ain, rambo1_prg_addr, prg_read, prg_write, prg_din, rambo1_prg_allow,
                                   chr_ain, rambo1_chr_addr, rambo1_chr_allow, rambo1_vram_a10, rambo1_vram_ce, rambo1_irq);

  wire [21:0] nesev_prg_addr, nesev_chr_addr;
  wire nesev_irq;
  NesEvent nesev(clk, ce, reset, prg_ain, nesev_prg_addr, chr_ain, nesev_chr_addr, mmc1_chr_addr[16:13], mmc1_prg_addr, nesev_irq);
  
  // Mask 
  reg [5:0] prg_mask;
  reg [6:0] chr_mask;

  always @* begin
    case(flags[10:8])
    0: prg_mask = 6'b000000;
    1: prg_mask = 6'b000001;
    2: prg_mask = 6'b000011;
    3: prg_mask = 6'b000111;
    4: prg_mask = 6'b001111;
    5: prg_mask = 6'b011111;
    default: prg_mask = 6'b111111;
    endcase

    case(flags[13:11])
    0: chr_mask = 7'b0000000;
    1: chr_mask = 7'b0000001;
    2: chr_mask = 7'b0000011;
    3: chr_mask = 7'b0000111;
    4: chr_mask = 7'b0001111;
    5: chr_mask = 7'b0011111;
    6: chr_mask = 7'b0111111;
    7: chr_mask = 7'b1111111;
    endcase
    
    irq = 0;
    prg_dout = 8'hff;
    has_chr_dout = 0;
    chr_dout = mmc5_chr_dout;
// 0 = Working
// 1 = Working
// 2 = Working
// 3 = Working
// 4 = Working
// 5 = Working
// 7 = Working
// 9 = Working
// 10 = Working
// 11 = Working
// 13 = Working
// 15 = Working
// 16 = Working minus EEPROM support
// 28 = Working
// 34 = Working
// 41 = Working
// 42 = Working
// 47 = Working
// 64 = Tons of GFX bugs
// 66 = Working
// 68 = Working
// 69 = Working
// 71 = Working
// 79 = Working
// 105 = Working
// 113 = Working
// 118 = Working
// 119 = Working
// 158 = Tons of GFX bugs
// 165 = GFX corrupted
// 209 = Not Tested
// 228 = Working
// 234 = Not Tested        
    case(flags[7:0])
    1:  {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}      = {mmc1_prg_addr, mmc1_prg_allow, mmc1_chr_addr, mmc1_vram_a10, mmc1_vram_ce, mmc1_chr_allow};
    9:  {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}      = {mmc2_prg_addr, mmc2_prg_allow, mmc2_chr_addr, mmc2_vram_a10, mmc2_vram_ce, mmc2_chr_allow};
    118, // TxSROM connects A17 to CIRAM A10.
    119, // TQROM  uses the Nintendo MMC3 like other TxROM boards but uses the CHR bank number specially.
    47,  // Mapper 047 is a MMC3 multicart
	 206, // MMC3 w/o IRQ or WRAM support
    4:  {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow, irq} = {mmc3_prg_addr, mmc3_prg_allow, mmc3_chr_addr, mmc3_vram_a10, mmc3_vram_ce, mmc3_chr_allow, mmc3_irq};

    10: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}      = {mmc4_prg_addr, mmc4_prg_allow, mmc4_chr_addr, mmc4_vram_a10, mmc4_vram_ce, mmc4_chr_allow};
	 
    5:  {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow, has_chr_dout, prg_dout, irq} = {mmc5_prg_addr, mmc5_prg_allow, mmc5_chr_addr, mmc5_vram_a10, mmc5_vram_ce, mmc5_chr_allow, mmc5_has_chr_dout, mmc5_prg_dout, mmc5_irq};

    0,
    2,
    3,
    7,
    28: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}      = {map28_prg_addr, map28_prg_allow, map28_chr_addr, map28_vram_a10, map28_vram_ce, map28_chr_allow};

    13: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}      = {map13_prg_addr, map13_prg_allow, map13_chr_addr, map13_vram_a10, map13_vram_ce, map13_chr_allow};
    15: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}      = {map15_prg_addr, map15_prg_allow, map15_chr_addr, map15_vram_a10, map15_vram_ce, map15_chr_allow};
	 
	 16: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow, prg_dout, irq} = {map16_prg_addr, map16_prg_allow, map16_chr_addr, map16_vram_a10, map16_vram_ce, map16_chr_allow, map16_prg_dout, map16_irq};
    
	 34: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}      = {map34_prg_addr, map34_prg_allow, map34_chr_addr, map34_vram_a10, map34_vram_ce, map34_chr_allow};
    41: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}      = {map41_prg_addr, map41_prg_allow, map41_chr_addr, map41_vram_a10, map41_vram_ce, map41_chr_allow};

    64,
    158: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow, irq} = {rambo1_prg_addr, rambo1_prg_allow, rambo1_chr_addr, rambo1_vram_a10, rambo1_vram_ce, rambo1_chr_allow, rambo1_irq};

	 42: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow, irq} = {map42_prg_addr, map42_prg_allow, map42_chr_addr, map42_vram_a10, map42_vram_ce, map42_chr_allow, map42_irq};

    11,
    66: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}      = {map66_prg_addr, map66_prg_allow, map66_chr_addr, map66_vram_a10, map66_vram_ce, map66_chr_allow};
    68: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}      = {map68_prg_addr, map68_prg_allow, map68_chr_addr, map68_vram_a10, map68_vram_ce, map68_chr_allow};
    69: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow, irq} = {map69_prg_addr, map69_prg_allow, map69_chr_addr, map69_vram_a10, map69_vram_ce, map69_chr_allow, map69_irq};

    71,
    232: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}     = {map71_prg_addr, map71_prg_allow, map71_chr_addr, map71_vram_a10, map71_vram_ce, map71_chr_allow};

    79,
    113: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}     = {map79_prg_addr, map79_prg_allow, map79_chr_addr, map79_vram_a10, map79_vram_ce, map79_chr_allow};

    105: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow, irq}= {nesev_prg_addr, mmc1_prg_allow, nesev_chr_addr, mmc1_vram_a10, mmc1_vram_ce, mmc1_chr_allow, nesev_irq};

    165: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow, irq} = {map165_prg_addr, map165_prg_allow, map165_chr_addr, map165_vram_a10, map165_vram_ce, map165_chr_allow, map165_irq};

    228: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}     = {map228_prg_addr, map228_prg_allow, map228_chr_addr, map228_vram_a10, map228_vram_ce, map228_chr_allow};
    234: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow}     = {map234_prg_addr, map234_prg_allow, map234_chr_addr, map234_vram_a10, map234_vram_ce, map234_chr_allow};
    default: {prg_aout, prg_allow, chr_aout, vram_a10, vram_ce, chr_allow} = {mmc0_prg_addr, mmc0_prg_allow, mmc0_chr_addr, mmc0_vram_a10, mmc0_vram_ce, mmc0_chr_allow};
    endcase
    if (prg_aout[21:20] == 2'b00)
      prg_aout[19:0] = {prg_aout[19:14] & prg_mask, prg_aout[13:0]};
    if (chr_aout[21:20] == 2'b10)
      chr_aout[19:0] = {chr_aout[19:13] & chr_mask, chr_aout[12:0]};
    // Remap the CHR address into VRAM, if needed.
    chr_aout = vram_ce ? {11'b11_0000_0000_0, vram_a10, chr_ain[9:0]} : chr_aout;
    prg_aout = (prg_ain < 'h2000) ? {11'b11_1000_0000_0, prg_ain[10:0]} : prg_aout;
    prg_allow = prg_allow || (prg_ain < 'h2000);
  end
endmodule

// PRG       = 0....
// CHR       = 10...
// CHR-VRAM  = 1100
// CPU-RAM   = 1110
// CARTRAM   = 1111
                 // Copyright (c) 2012-2013 Ludvig Strigeus
// This program is GPL Licensed. See COPYING for the full license.


// Copyright (c) 2012-2013 Ludvig Strigeus
// This program is GPL Licensed. See COPYING for the full license.

module video(
	input  clk,
	input [5:0] color,
	input [8:0] count_h,
	input [8:0] count_v,
	input mode,
	input ypbpr,
	input smoothing,
	input scanlines,
	input overscan,
	input palette,
	

	output       VGA_HS,
	output       VGA_VS,
	output [3:0] VGA_R,
	output [3:0] VGA_G,
	output [3:0] VGA_B,
	
	output osd_visible
);

reg clk2 = 1'b0;
always @(posedge clk) clk2 <= ~clk2;
wire clkv = mode ? clk2 : clk;

wire [5:0] R_out, G_out, B_out;



// NTSC UnsaturatedV6 palette
//see: http://www.firebrandx.com/nespalette.html
/*reg [15:0] pal_unsat_lut[0:63];
initial $readmemh("nes_palette_unsaturatedv6.txt", pal_unsat_lut);*/

// FCEUX palette
reg [15:0] pal_fcelut[0:63];
initial begin
    pal_fcelut[0] = 16'h39ce;
    pal_fcelut[1] = 16'h4464;
    pal_fcelut[2] = 16'h5400;
    pal_fcelut[3] = 16'h4c08;
    pal_fcelut[4] = 16'h3811;
    pal_fcelut[5] = 16'h0815;
    pal_fcelut[6] = 16'h0014;
    pal_fcelut[7] = 16'h002f;
    pal_fcelut[8] = 16'h00a8;
    pal_fcelut[9] = 16'h0100;
    pal_fcelut[10] = 16'h0140;
    pal_fcelut[11] = 16'h08e0;
    pal_fcelut[12] = 16'h2ce3;
    pal_fcelut[13] = 16'h0000;
    pal_fcelut[14] = 16'h0000;
    pal_fcelut[15] = 16'h0000;
    pal_fcelut[16] = 16'h5ef7;
    pal_fcelut[17] = 16'h75c0;
    pal_fcelut[18] = 16'h74e4;
    pal_fcelut[19] = 16'h7810;
    pal_fcelut[20] = 16'h5c17;
    pal_fcelut[21] = 16'h2c1c;
    pal_fcelut[22] = 16'h00bb;
    pal_fcelut[23] = 16'h0539;
    pal_fcelut[24] = 16'h01d1;
    pal_fcelut[25] = 16'h0240;
    pal_fcelut[26] = 16'h02a0;
    pal_fcelut[27] = 16'h1e40;
    pal_fcelut[28] = 16'h4600;
    pal_fcelut[29] = 16'h0000;
    pal_fcelut[30] = 16'h0000;
    pal_fcelut[31] = 16'h0000;
    pal_fcelut[32] = 16'h7fff;
    pal_fcelut[33] = 16'h7ee7;
    pal_fcelut[34] = 16'h7e4b;
    pal_fcelut[35] = 16'h7e28;
    pal_fcelut[36] = 16'h7dfe;
    pal_fcelut[37] = 16'h59df;
    pal_fcelut[38] = 16'h31df;
    pal_fcelut[39] = 16'h1e7f;
    pal_fcelut[40] = 16'h1efe;
    pal_fcelut[41] = 16'h0b50;
    pal_fcelut[42] = 16'h2769;
    pal_fcelut[43] = 16'h4feb;
    pal_fcelut[44] = 16'h6fa0;
    pal_fcelut[45] = 16'h3def;
    pal_fcelut[46] = 16'h0000;
    pal_fcelut[47] = 16'h0000;
    pal_fcelut[48] = 16'h7fff;
    pal_fcelut[49] = 16'h7f95;
    pal_fcelut[50] = 16'h7f58;
    pal_fcelut[51] = 16'h7f3a;
    pal_fcelut[52] = 16'h7f1f;
    pal_fcelut[53] = 16'h6f1f;
    pal_fcelut[54] = 16'h5aff;
    pal_fcelut[55] = 16'h577f;
    pal_fcelut[56] = 16'h539f;
    pal_fcelut[57] = 16'h53fc;
    pal_fcelut[58] = 16'h5fd5;
    pal_fcelut[59] = 16'h67f6;
    pal_fcelut[60] = 16'h7bf3;
    pal_fcelut[61] = 16'h6318;
    pal_fcelut[62] = 16'h0000;
    pal_fcelut[63] = 16'h0000;

end

wire [14:0] pixel = pal_fcelut[color][14:0];
 
// Horizontal and vertical counters
reg [9:0] h, v;
wire hpicture  = (h < 512);             // 512 lines of picture
wire hend = (h == 681);                 // End of line, 682 pixels.
wire vpicture = (v < (480 >> mode));    // 480 lines of picture
wire vend = (v == (523 >> mode));       // End of picture, 524 lines. (Should really be 525 according to NTSC spec)

wire [14:0] doubler_pixel;
wire doubler_sync;

scan_double doubler(clk, pixel,
		            count_v[8],                 // reset_frame
		            (count_h[8:3] == 42),       // reset_line
		            {v[0], h[9] ? 9'd0 : h[8:0] + 9'd1}, // 0-511 for line 1, or 512-1023 for line 2.
		            doubler_pixel);             // pixel is outputted


reg [8:0] old_count_v;
wire sync_frame = (old_count_v == 9'd511) && (count_v == 9'd0);

assign doubler_sync = sync_frame;

always @(posedge clkv) begin
  h <= (hend || (mode ? sync_frame : doubler_sync)) ? 10'd0 : h + 10'd1;
  if(mode ? sync_frame : doubler_sync) v <= 0;
    else if (hend) v <= vend ? 10'd0 : v + 10'd1;

  old_count_v <= count_v;
end

wire [14:0] pixel_v = (!hpicture || !vpicture) ? 15'd0 : mode ? pixel : doubler_pixel;
wire darker = !mode && v[0] && scanlines;

// display overlay to hide overscan area
// based on Mario3, DoubleDragon2, Shadow of the Ninja
wire ol = overscan && ( (h > 512-16) || 
								(h < 20) || 
								(v < (mode ? 6 : 12)) || 
								(v > (mode ? 240-10 : 480-20)) 
							  );

wire  [4:0]   vga_r = ol ? {4'b0, pixel_v[4:4]}   : (darker ? {1'b0, pixel_v[4:1]} : pixel_v[4:0]);
wire  [4:0]   vga_g = ol ? {4'b0, pixel_v[9:9]}   : (darker ? {1'b0, pixel_v[9:6]} : pixel_v[9:5]);
wire  [4:0]   vga_b = ol ? {4'b0, pixel_v[14:14]} : (darker ? {1'b0, pixel_v[14:11]} : pixel_v[14:10]);
wire         sync_h = ((h >= (512 + 23 + (mode ? 18 : 35))) && (h < (512 + 23 + (mode ? 18 : 35) + 82)));
wire         sync_v = ((v >= (mode ? 240 + 5  : 480 + 10))  && (v < (mode ? 240 + 14 : 480 + 12)));


assign VGA_HS = !sync_h;
assign VGA_VS = !sync_v;
assign VGA_R = vga_r[4:1];
assign VGA_G = vga_g[4:1];
assign VGA_B = vga_b[4:1];

endmodule
/*
The virtual NES cartridge
At the moment this stores the entire cartridge
in SPRAM, in the future it could stream data from
SQI flash, which is more than fast enough
*/

module cart_mem(
  input clock,
  input reset,
  
  input reload,
  input [3:0] index,
  
  output cart_ready,
  output reg [31:0] flags_out,
  //address into a given section - 0 is the start of CHR and PRG,
  //region is selected using the select lines for maximum flexibility
  //in partitioning
  input [20:0] address,
  
  input prg_sel, chr_sel,
  input ram_sel, //for cart SRAM (NYI)
  
  input rden, wren,
  
  input  [7:0] write_data,
  output [7:0] read_data,
  
  //Flash load interface
  output flash_csn,
  output flash_sck,
  output flash_mosi,
  input flash_miso
);

reg load_done;
initial load_done = 1'b0;

wire cart_ready = load_done;
// Does the image use CHR RAM instead of ROM? (i.e. UNROM or some MMC1)
wire is_chram = flags_out[15];
// Work out whether we're in the SPRAM, used for the main ROM, or the extra 8k SRAM
wire spram_en = prg_sel | (!is_chram && chr_sel);
wire sram_en = ram_sel | (is_chram && chr_sel);

wire [16:0] decoded_address;
assign decoded_address = chr_sel ? {1'b1, address[15:0]} : address[16:0];

reg [15:0] load_addr;
wire [14:0] spram_address = load_done ? decoded_address[16:2] : load_addr[14:0];

wire load_wren;
wire spram_wren = load_done ? (spram_en && wren) : load_wren;
wire [3:0] spram_mask = load_done ? (4'b0001 << decoded_address[1:0]) : 4'b1111;
wire [3:0] spram_maskwren = spram_wren ? spram_mask : 4'b0000;

wire [31:0] load_write_data;
wire [31:0] spram_write_data = load_done ? {write_data, write_data, write_data, write_data} : load_write_data;

wire [31:0] spram_read_data;

wire [7:0] csram_read_data;
// Demux the 32-bit memory
assign read_data = sram_en ? csram_read_data : 
    (decoded_address[1] ? (decoded_address[0] ? spram_read_data[31:24] : spram_read_data[23:16]) : (decoded_address[0] ? spram_read_data[15:8] : spram_read_data[7:0]));

 // The SRAM, used either for PROG_SRAM or CHR_SRAM
generic_ram #(
  .WIDTH(8),
  .WORDS(8192)
) sram_i (
  .clock(clock),
  .reset(reset),
  .address(decoded_address[12:0]), 
  .wren(wren&sram_en), 
  .write_data(write_data), 
  .read_data(csram_read_data)
);
// The SPRAM (with a generic option), which stores
// the ROM

  reg [7:0] spram_mem0[0:32767];
  reg [7:0] spram_mem1[0:32767];
  reg [7:0] spram_mem2[0:32767];
  reg [7:0] spram_mem3[0:32767];  
  reg [31:0] spram_dout_pre;
  always @(posedge clock)
  begin
    spram_dout_pre[7:0] <= spram_mem0[spram_address];
    spram_dout_pre[15:8] <= spram_mem1[spram_address];
    spram_dout_pre[23:16] <= spram_mem2[spram_address];
    spram_dout_pre[31:24] <= spram_mem3[spram_address];
    if(spram_maskwren[0]) spram_mem0[spram_address] <= spram_write_data[7:0];
    if(spram_maskwren[1]) spram_mem1[spram_address] <= spram_write_data[15:8];
    if(spram_maskwren[2]) spram_mem2[spram_address] <= spram_write_data[23:16];
    if(spram_maskwren[3]) spram_mem3[spram_address] <= spram_write_data[31:24];
  end;
  assign spram_read_data = spram_dout_pre;


wire flashmem_valid = !load_done;
wire flashmem_ready;
assign load_wren =  flashmem_ready && (load_addr != 16'h8000);
wire [23:0] flashmem_addr = (24'h100000 + (index_lat << 18)) | {load_addr, 2'b00};
reg [3:0] index_lat;
reg load_done_pre;

reg [7:0] wait_ctr;
// Flash memory load interface
always @(posedge clock) 
begin
  if (reset == 1'b1) begin
    load_done_pre <= 1'b0;
    load_done <= 1'b0;
    load_addr <= 16'h0000;
    flags_out <= 32'h00000000;
    wait_ctr <= 8'h00;
    index_lat <= 4'h0;
  end else begin
    if (reload == 1'b1) begin
      load_done_pre <= 1'b0;
      load_done <= 1'b0;
      load_addr <= 16'h0000;
      flags_out <= 32'h00000000;
      wait_ctr <= 8'h00;
      index_lat <= index;
    end else begin
      if(!load_done_pre) begin
        if (flashmem_ready == 1'b1) begin
          if (load_addr == 16'h8000) begin
            load_done_pre <= 1'b1;
            flags_out <= load_write_data; //last word is mapper flags
          end else begin
            load_addr <= load_addr + 1'b1;
          end;
        end
      end else begin
        if (wait_ctr < 8'hFF)
          wait_ctr <= wait_ctr + 1;
        else
          load_done <= 1'b1;
      end
      
    end
  end
end



icosoc_flashmem flash_i (
	.clk(clock),
  .reset(reset),
  .valid(flashmem_valid),
  .ready(flashmem_ready),
  .addr(flashmem_addr),
  .rdata(load_write_data),

	.spi_cs(flash_csn),
	.spi_sclk(flash_sck),
	.spi_mosi(flash_mosi),
	.spi_miso(flash_miso)
);

endmodule
