blob: f6880971c9cd449ee2ae990ded371d024918056e [file] [log] [blame]
// 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