NMPSM3软处理器

NMPSM3概述

在UCSC扩展学院上了第一门FPGA课后,我对这些设备为普通人提供的功能感到惊讶,我决定更深入地研究它们。我最终意识到我有足够的逻辑设计知识,可以构建自己的简单处理器。在了解了KCPSM(nanoblaze)之后,我开始构建自己的处理器,并将其称为NMPSM(Nick Mikstas可编程状态机)。我花了三遍迭代才能制作出功能全面的处理器,因此命名为NMPSM3。即使NMPSM3受到nanoblaze IO方案的启发,其内部结构也完全不同。NMPSM3是具有四个独立中断和一个复位的16位处理器。NMPSM至少需要实现四个18Kb BRAMS:一个用于寄存器,一个用于堆栈,一个用于解码器,至少一个用于程序ROM。使处理器正常工作后,我为其编写了汇编程序,并创建了一个大型项目以展示其功能。

当我第一次设计NMPSM3时,它是在Digilent Nexys 2板上实现的。Nexys 2上有Xilinx Spartan 3部件。在成功实施该项目之后,几年来我对NMPSM3一无所获。我最终在SCU上了一门课,基本上和UCSC Extension上的一门课一样。我决定通过更新项目以使其在Digilent Basys 3 FPGA板上工作来使NMPSM3振作起来。由于新的FPGA部件(Artyx 7)比Spartan 3具有更多的功能,因此我也对该项目进行了一些升级。我也写了一份详尽的报告。

NMPSM3报告


NMPSM3屏幕截图

NMPSM3调色板更改示范
NMPSM3属性表演示
NMPSM3基本颜色演示 NMPSM3平铺时钟演示 NMPSM3 sprite镜像演示 NMPSM3弹跳精灵演示 NMPSM3 Sprite音频演示 NMPSM3精灵优先级演示


NMPSM3硬件

与处理器一起,我还基于8位Nintendo构建了其他一些模块,包括UART和图片处理单元(PPU)。一些Verilog代码很粗糙,因为在创建此项目时我正在学习Verilog。

Final_Project.v
`timescale 1ns / 1ps
 
module Final_Project(
    input clk,
 
    input [15:0]sw,
 
    input btnC,
    input btnU,
    input btnD,
    input btnL,
    input btnR,
 
    input data,
 
    input RsRx,
    output RsTx,
 
    output RxTest,
    output TxTest,
 
    output [15:0]led,
 
    output [6:0]seg,
    output [3:0]an,
    output dp,
 
    output [3:0]vgaRed,
    output [3:0]vgaGreen,
    output [3:0]vgaBlue,
    output Hsync,
    output Vsync,
 
    output sclk,
    output ce
    );
 
    //UART test ports.
    assign RxTest = RsRx;
    assign TxTest = RsTx;
 
    wire clk100MHz;
    wire clk50MHz;
    wire clk25MHz;
    wire t0out;
    wire t1out;
    wire ack0;
    wire ack1;
    wire ack2;
    wire ack3;
    wire sigout0;
    wire sigout1;
    wire sigout2;
    wire sigout3;
    wire ce1k;
    wire blink;
    wire read;
    wire write;
    wire vblank;
    wire reset;
    wire [15:0]id;
    wire [15:0]outdata;
    wire [7:0]hour;
    wire [7:0]min;
    wire [7:0]sec;
    wire [35:0]inst;
    wire [15:0]in_port;
    wire [15:0]address;
    wire [7:0]romdata;
    wire [11:0]mdout;
    wire [7:0]vgadata;
    wire [9:0]addr;
    wire [10:0]romaddress;
    wire [11:0]mdin;
 
    //UART wires.
    wire [7:0]uartdata;
    wire [11:0]txcount;
    wire [11:0]rxcount;  
 
    //Unused VGA bits in this design.
    assign vgaRed[0] = 1'b0;
    assign vgaGreen[0] = 1'b0;
    assign vgaBlue[0] = 1'b0;
    assign vgaBlue[1] = 1'b0;
 
    //Reset signal.
    assign reset = btnU;
 
    //Flip-flop for interrupt 0.
    FF ff0(.set(t0out), .reset(ack0), .sigout(sigout0));
 
    //Flip-flop for interrupt 1.
    FF ff1(.set(t1out), .reset(ack1), .sigout(sigout1));
 
    //Flip-flop for interrupt 2.
    FF ff2(.set(vblank), .reset(ack2), .sigout(sigout2));
 
    //Flip-flop for interrupt 3(not used).
    FF ff3(.set(1'b0), .reset(ack3), .sigout(sigout3));
 
    //Divide by 100,000.
    div100k divideBy100K(.clock(clk100MHz), .ce1k(ce1k));
 
    //Clock divider.
    clk25 c(.clk_in1(clk), .clk_out1(clk100MHz), .clk_out2(clk50MHz), .clk_out3(clk25MHz));
 
    //NMPSM3 soft processor.    
    NMPSM3 nmpsm3(.clk(clk100MHz), .reset(reset), .IRQ0(sigout0), .IRQ1(sigout1), .IRQ2(sigout2), .IRQ3(sigout3),
                  .INSTRUCTION(inst), .IN_PORT(in_port), .READ_STROBE(read), .WRITE_STROBE(write), .IRQ_ACK0(ack0),
                  .IRQ_ACK1(ack1), .IRQ_ACK2(ack2), .IRQ_ACK3(ack3), .ADDRESS(address), .OUT_PORT(outdata),
                  .PORT_ID(id));
 
    //Program ROM for NMPSM3.
    Program_ROM prgROM(.clka(clk100MHz), .addra(address[9:0]), .douta(inst));
 
    //Lookup ROM
    Lookup_ROM lookuprom(.clka(clk100MHz), .addra(romaddress), .douta(romdata));
 
    //UART
    uart uart1(.clk(clk100MHz), .reset(reset), .id(id), .din(outdata), .write(write), .rx(RsRx), .tx(RsTx),
               .dout(uartdata), .rxcount(rxcount), .txcount(txcount));
 
    //LED output controller.    
    ledio LEDIO(.clk(clk100MHz), .reset(reset), .write(write), .id(id), .din(outdata), .ledsout(led[7:0]));
 
    //LED output controller 2.
    LEDIO2 ledio2(.clk(clk100MHz), .reset(reset), .write(write), .id(id), .din(outdata), .ledsout(led[15:8]));
 
    //Seven segment controller.
    seg7io seg7control(.clk(clk100MHz), .ce1k(ce1k), .write(write), .reset(reset), .id(id), .din(outdata),
                       .segselect(an), .segs({dp,seg}));
 
    //Timer 0.
    timer0 time0(.clk(clk100MHz), .cein(ce1k), .write(write), .reset(reset), .id(id), .din(outdata), .dout(t0out));
 
    //Timer 1.
    timer1 time1(.clk(clk100MHz), .cein(ce1k), .write(write), .reset(reset), .id(id), .din(outdata), .dout(t1out));
 
    //ROM controller for lookup ROM.
    ROMcontroller ROMcontrol(.clk(clk100MHz), .id(id), .ain(outdata), .aout(romaddress));
 
    //Processor input data MUX.
    dataMUX datamux(.read(read), .blink(blink), .id(id), .i2cdata(16'd0), .i2cstatus(16'd0), .xpos(16'd0), .ypos(16'd0),
                    .uartdata({8'h00,uartdata}), .txcount(txcount), .rxcount(rxcount), .romdata(romdata),
                    .switches(sw), .sec(sec), .min(min), .hour(hour), .micdata({btnD, 3'h0, mdout}),
                    .dout(in_port));
 
    //Clock control.
    ClockControl clockcontrol(.clock(clk100MHz), .ce_1KHz(ce1k), .button({btnD, btnL, btnC, btnR}), .blink(blink),
                              .hour(hour), .min(min), .sec(sec));  
 
    //Picture processing unit.
    VGA ppu(.clk25MHz(clk25MHz), .clk(clk100MHz), .write(write), .id(id), .data(outdata[7:0]),
            .vblank(vblank), .vsync(Vsync), .hsync(Hsync), .vga({vgaBlue[3:2], vgaGreen[3:1], vgaRed[3:1]}));    
 
    //Microphone control.
    MControl mc(.clk(clk100MHz), .reset(reset), .serialdata(data), .nenable(ce), .sclk(sclk), .micdata(mdout));          
endmodule


NMPSM3.v
`timescale 1ns / 1ps
 
module NMPSM3(clk, reset, INSTRUCTION, IN_PORT, IRQ0, IRQ1, IRQ2, IRQ3,
              ADDRESS, OUT_PORT, PORT_ID, READ_STROBE, WRITE_STROBE,
                  IRQ_ACK0, IRQ_ACK1, IRQ_ACK2, IRQ_ACK3);
 
    input  clk, reset, IRQ0, IRQ1, IRQ2, IRQ3;
     input  [35:0]INSTRUCTION;
     input  [15:0]IN_PORT;
     output READ_STROBE, WRITE_STROBE, IRQ_ACK0, IRQ_ACK1, IRQ_ACK2, IRQ_ACK3;
     output [15:0]PORT_ID;
     output [15:0]OUT_PORT;
     output [15:0]ADDRESS;
 
     localparam SIZE = 16;
 
     localparam JPNZ = 8'h16;
     localparam JPZ  = 8'h19;
     localparam JPNC = 8'h1C;
     localparam JPC  = 8'h20;
 
     localparam CLNZ = 8'h29;
     localparam CLZ  = 8'h2C;
     localparam CLNC = 8'h30;
     localparam CLC  = 8'h33;
 
     localparam RTNZ = 8'h39;
     localparam RTZ  = 8'h3C;
     localparam RTNC = 8'h40;
     localparam RTC  = 8'h43;    
 
     localparam IRQADDR0 = 8'hCC;
     localparam IRQADDR1 = 8'hD0;
     localparam IRQADDR2 = 8'hD3;
     localparam IRQADDR3 = 8'hD6;
 
     localparam STEP = 8'hD9;
 
     wire [43:0]control;
     wire [15:0]portA;
     wire [15:0]portB;    
     wire zero;
     wire [7:0]decodeAddr;
     wire I0, I1, I2, I3;
     wire [15:0]addrp1;
     wire [10:0] addrA;
    wire [15:0] dataA;
    wire weA;
    wire [10:0] addrB;
    wire [15:0] dataB;
    wire weB;
     wire [9:0]stackm1;
     wire [19:0]none;
     wire [7:0]portAup;
     wire [7:0]portAdn;
     wire [7:0]portBup;
     wire [7:0]portBdn;
     wire [4:0]sel;
    wire [15:0]a;
     wire [15:0]b;
     wire [15:0]inst;
 
     reg [1:0]IRQload = 2'b00;
     reg [15:0]wresult = 16'h0000;
     reg wcarry = 1'b0;    
     reg [15:0]result  = 16'h0000;
     reg carry  = 1'b0;
     reg [1:0]load = 2'b00;
     reg IRQMreg = 1'b1;
     reg IRQ0reg = 1'b0;
     reg IRQ1reg = 1'b0;
     reg IRQ2reg = 1'b0;
     reg IRQ3reg = 1'b0;
     reg [9:0]stack = 10'h000;
     reg [15:0]addr = 16'h0000;
 
     //Used to synchronize interrupts and reset with internal clock.
     reg IR0 = 1'b0;
     reg IR1 = 1'b0;
     reg IR2 = 1'b0;
     reg IR3 = 1'b0;
     reg [1:0]rst = 2'b00;
 
    RAMB16_S36_S36 #(
      .INIT_A(36'h000000000),       // Value of output RAM registers on Port A at startup
      .INIT_B(36'h000000000),       // Value of output RAM registers on Port B at startup
      .SRVAL_A(36'h000000000),      // Port A output value upon SSR assertion
      .SRVAL_B(36'h000000000),      // Port B output value upon SSR assertion
      .WRITE_MODE_A("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE
      .WRITE_MODE_B("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE
      .SIM_COLLISION_CHECK("ALL"),  // "NONE", "WARNING_ONLY", "GENERATE_X_ONLY", "ALL"
 
      // Micro-code for the decoder ROM
      .INIT_00(256'H00200001_00000000_00000000_04040007_00000000_00000000_04000007_00000000),
      .INIT_01(256'H00000000_08200007_00000001_00000000_00000000_08000007_00000000_04040007),
      .INIT_02(256'H00000000_0000000B_00000000_00000000_0000000F_00000000_00000000_0000000B),
      .INIT_03(256'H00000000_00000000_00000000_0000000B_00000000_00000000_0000000B_00000000),
      .INIT_04(256'H00000000_1950000F_00000000_00000000_1950000B_00000000_00000000_0000000B),
      .INIT_05(256'H00000000_00000000_00000000_1950000B_00000000_00000000_1950000B_00000000),
      .INIT_06(256'H00000017_12300001_00000000_00000000_1950000B_00000000_00000000_1950000B),
      .INIT_07(256'H00000000_00000000_00000017_12300001_00000000_00000017_12300001_00000000),
      .INIT_08(256'H00001137_12300001_00000000_00000017_12300001_00000000_00000017_12300001),
      .INIT_09(256'H00000000_00000000_00000000_44080407_00000000_00001157_12300001_00000000),
      .INIT_0A(256'H00000000_20000A07_00000000_00000000_20000C07_00000000_00000000_44080207),
      .INIT_0B(256'H00000000_00000000_00000000_04065007_00000000_00000000_04064007_00000000),
      .INIT_0C(256'H00000000_04066007_00000000_00000000_04063007_00000000_00000000_04062007),
      .INIT_0D(256'H00000000_00000000_00000000_0406C007_00000000_00000000_04067007_00000000),
      .INIT_0E(256'H00000000_04069007_00000000_00000000_0406D007_00000000_00000000_04068007),
      .INIT_0F(256'H00000000_00000000_00000000_0406A007_00000000_00000000_0406E007_00000000),
      .INIT_10(256'H00000000_00010007_00000000_00000000_0406B007_00000000_00000000_0406F007),
      .INIT_11(256'H00000000_00000000_00000000_00012007_00000000_00000000_00011007_00000000),
      .INIT_12(256'H00000000_04075007_00000000_00000000_04074007_00000000_00000000_00013007),
      .INIT_13(256'H00000000_00000000_00000000_04077007_00000000_00000000_04076007_00000000),
      .INIT_14(256'H00000000_00000027_00000000_00000000_00018007_00000000_00000000_00019007),
      .INIT_15(256'H00000000_00000000_00000000_00000067_00000000_00000000_00000047_00000000),
      .INIT_16(256'H00000000_000000C7_00000000_00000000_000000A7_00000000_00000000_00000087),
      .INIT_17(256'H00000000_00000000_00000000_00000107_00000000_00000000_000000E7_00000000),
      .INIT_18(256'H04040007_12300001_00000000_00000000_00000000_00000000_00000000_19100007),
      .INIT_19(256'H00000000_00000000_80000013_99900161_00000000_00000000_00000000_00000000),
      .INIT_1A(256'H00000013_19900161_00000000_00000013_19900161_00000000_00000013_19900161),
      .INIT_1B(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000007_00000000),
      .INIT_1C(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_1D(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_1E(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_1F(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_20(256'H00000080_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_21(256'H00000000_00000000_000000E0_00000000_00000000_00000000_00000000_00000000),
      .INIT_22(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_23(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_24(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_25(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_26(256'H00000000_00000370_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_27(256'H00000000_00000000_00000000_000003D0_00000000_00000000_000003A0_00000000),
      .INIT_28(256'H00000000_00000470_00000000_00000000_00000440_00000000_00000000_00000410),
      .INIT_29(256'H00000000_00000000_00000000_00000000_00000000_00000000_000004A0_00000000),
      .INIT_2A(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_2B(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_2C(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_2D(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_2E(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_2F(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_30(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_31(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_32(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_33(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_34(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_35(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_36(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_37(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_38(256'H00000000_00000C70_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_39(256'H00000000_00000000_00000000_00000CD8_00000000_00000000_00000000_00000000),
      .INIT_3A(256'H00000004_00000D6C_00000000_00000002_00000D4A_00000000_00000001_00000D19),
      .INIT_3B(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_3C(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_3D(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_3E(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000),
      .INIT_3F(256'H00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000))
    DecoderROM (
      .DOA(control[31:0]),          // Port A 32-bit Data Output
      .DOB({none, control[43:32]}), // Port B 32-bit Data Output
      .ADDRA({1'b0, decodeAddr}),   // Port A 9-bit Address Input
      .ADDRB({1'b1, decodeAddr}),   // Port B 9-bit Address Input
      .CLKA(clk),                   // Port A Clock
      .CLKB(clk),                   // Port B Clock
      .ENA(1'b1),                   // Port A RAM Enable Input
      .ENB(1'b1),                   // Port B RAM Enable Input
      .SSRA(1'b0),                  // Port A Synchronous Set/Reset Input
      .SSRB(1'b0),                  // Port B Synchronous Set/Reset Input
      .WEA(1'b0),                   // Port A Write Enable Input
      .WEB(1'b0)                    // Port B Write Enable Input
    );
 
    RAMB16_S9_S9 #(
      .INIT_A(18'h00000),           // Value of output RAM registers on Port A at startup
      .INIT_B(18'h00000),           // Value of output RAM registers on Port B at startup
      .SRVAL_A(18'h00000),          // Port A output value upon SSR assertion
      .SRVAL_B(18'h00000),          // Port B output value upon SSR assertion
      .WRITE_MODE_A("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE
      .WRITE_MODE_B("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE
      .SIM_COLLISION_CHECK("ALL"))  // "NONE", "WARNING_ONLY", "GENERATE_X_ONLY", "ALL"
    RAMupper (
      .DOA(portAup),                // Port A 16-bit Data Output
      .DOB(portBup),                // Port B 16-bit Data Output
      .ADDRA(addrA),                // Port A 10-bit Address Input
      .ADDRB(addrB),                // Port B 10-bit Address Input
      .CLKA(clk),                   // Port A Clock
      .CLKB(clk),                   // Port B Clock
      .DIA(dataA[15:8]),            // Port A 16-bit Data Input
      .DIB(dataB[15:8]),            // Port-B 16-bit Data Input
        .DIPA(1'b0),                  // Port A 1-bit parity Input
        .DIPB(1'b0),                  // Port B 1-bit parity Input
      .ENA(1'b1),                   // Port A RAM Enable Input
      .ENB(1'b1),                   // Port B RAM Enable Input
      .SSRA(1'b0),                  // Port A Synchronous Set/Reset Input
      .SSRB(1'b0),                  // Port B Synchronous Set/Reset Input
      .WEA(weA),                    // Port A Write Enable Input
      .WEB(weB)                     // Port B Write Enable Input
    );
 
    RAMB16_S9_S9 #(
      .INIT_A(18'h00000),           // Value of output RAM registers on Port A at startup
      .INIT_B(18'h00000),           // Value of output RAM registers on Port B at startup
      .SRVAL_A(18'h00000),          // Port A output value upon SSR assertion
      .SRVAL_B(18'h00000),          // Port B output value upon SSR assertion
      .WRITE_MODE_A("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE
      .WRITE_MODE_B("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE
      .SIM_COLLISION_CHECK("ALL"))  // "NONE", "WARNING_ONLY", "GENERATE_X_ONLY", "ALL"
    RAMlower (
      .DOA(portAdn),                // Port A 16-bit Data Output
      .DOB(portBdn),                // Port B 16-bit Data Output
      .ADDRA(addrA),                // Port A 10-bit Address Input
      .ADDRB(addrB),                // Port B 10-bit Address Input
      .CLKA(clk),                   // Port A Clock
      .CLKB(clk),                   // Port B Clock
      .DIA(dataA[7:0]),             // Port A 16-bit Data Input
      .DIB(dataB[7:0]),             // Port-B 16-bit Data Input
        .DIPA(1'b0),                  // Port A 1-bit parity Input
        .DIPB(1'b0),                  // Port B 1-bit parity Input
      .ENA(1'b1),                   // Port A RAM Enable Input
      .ENB(1'b1),                   // Port B RAM Enable Input
      .SSRA(1'b0),                  // Port A Synchronous Set/Reset Input
      .SSRB(1'b0),                  // Port B Synchronous Set/Reset Input
      .WEA(weA),                    // Port A Write Enable Input
      .WEB(weB)                     // Port B Write Enable Input
    );
 
     always @(posedge clk) begin
         if(rst) begin
                carry   <= 1'b0;
                IRQMreg <= 1'b1;
                IRQ0reg <= 1'b0;
                IRQ1reg <= 1'b0;
                IRQ2reg <= 1'b0;
                IRQ3reg <= 1'b0;
                stack   <= 10'h000;
                result  <= 16'h0000;
                addr    <= 16'h0000;
                load    <= 2'b00;
            rst <= rst + 1'b1;                
         end         
          else begin
              result <= wresult;
                carry  <= wcarry;
                if(control[1])
                   addr  <= ADDRESS;
              if(control[25:24] == 2'b01)
                  stack <= stack + 1'b1;
              if(control[25:24] == 2'b10)
                  stack <= stack - 1'b1;
              if(control[8:5] == 4'b0001)
                  IRQ0reg <=1'b1;
              if(control[8:5] == 4'b0010)
                  IRQ1reg <=1'b1;
             if(control[8:5] == 4'b0011)
                  IRQ2reg <=1'b1;
             if(control[8:5] == 4'b0100)
                  IRQ3reg <=1'b1;
             if(control[8:5] == 4'b0101)
                  IRQ0reg <=1'b0;
              if(control[8:5] == 4'b0110)
                  IRQ1reg <=1'b0;
              if(control[8:5] == 4'b0111)
                  IRQ2reg <=1'b0;
            if(control[8:5] == 4'b1000)
                  IRQ3reg <=1'b0;    
            if(control[8:5] == 4'b1001)
                  IRQMreg <=1'b1;
              if(control[8:5] == 4'b1010) begin
                  IRQMreg <= 1'b1;
                    IRQ0reg <= 1'b0;
                    IRQ1reg <= 1'b0;
                    IRQ2reg <= 1'b0;
                    IRQ3reg <= 1'b0;
                end
                if(control[8:5] == 4'b1011)
                    IRQMreg <= 1'b0;
                if(control[35])
                    load <= {carry, ~zero};
                //Synchronize interrupts and reset with the internal clock.    
            if(IRQ0)
                    IR0 <= 1'b1;
              else
                    IR0 <= 1'b0;
              if(IRQ1)
                    IR1 <= 1'b1;
              else   
                    IR1 <= 1'b0;
              if(IRQ2)
                    IR2 <= 1'b1;
              else   
                    IR2 <= 1'b0;
              if(IRQ3)
                    IR3 <= 1'b1;
              else   
                    IR3 <= 1'b0;
            if (reset)
                rst <= 2'b01;                
        end
     end
 
     assign IRQ_ACK0 = control[31];
     assign IRQ_ACK1 = control[32];
     assign IRQ_ACK2 = control[33];
     assign IRQ_ACK3 = control[34];
 
     always @(control)
         case(control[33:31])
              3'b001  : IRQload <= 2'h1;
                3'b010  : IRQload <= 2'h2;
                3'b100  : IRQload <= 2'h3;
                default : IRQload <= 2'h4;
        endcase
 
     and andIRQ0 (I0, IRQMreg, IRQ0reg, IR0);
     and andIRQ1 (I1, IRQMreg, IRQ1reg, IR1);
     and andIRQ2 (I2, IRQMreg, IRQ2reg, IR2);
     and andIRQ3 (I3, IRQMreg, IRQ3reg, IR3);
 
     assign decodeAddr = control[0] ? control[43:36] :                         
                        ({control[0], I0}             == 2'b01)    ? IRQADDR0 :
                         ({control[0], I0, I1}         == 3'b001)   ? IRQADDR1 :
                                ({control[0], I0, I1, I2}     == 4'b0001)  ? IRQADDR2 :
                                ({control[0], I0, I1, I2, I3} == 5'b00001) ? IRQADDR3 :
                                ({zero,  INSTRUCTION[35:28]}  == {1'b1, JPNZ}) ? STEP :
                                ({zero,  INSTRUCTION[35:28]}  == {1'b0, JPZ }) ? STEP :
                                ({carry, INSTRUCTION[35:28]}  == {1'b1, JPNC}) ? STEP :
                                ({carry, INSTRUCTION[35:28]}  == {1'b0, JPC }) ? STEP :
                                ({zero,  INSTRUCTION[35:28]}  == {1'b1, CLNZ}) ? STEP :
                                ({zero,  INSTRUCTION[35:28]}  == {1'b0, CLZ }) ? STEP :
                                ({carry, INSTRUCTION[35:28]}  == {1'b1, CLNC}) ? STEP :
                                ({carry, INSTRUCTION[35:28]}  == {1'b0, CLC }) ? STEP :
                                ({zero,  INSTRUCTION[35:28]}  == {1'b1, RTNZ}) ? STEP :
                                ({zero,  INSTRUCTION[35:28]}  == {1'b0, RTZ }) ? STEP :
                                ({carry, INSTRUCTION[35:28]}  == {1'b1, RTNC}) ? STEP :
                                ({carry, INSTRUCTION[35:28]}  == {1'b0, RTC }) ? STEP :
                         INSTRUCTION[35:28];
 
    assign PORT_ID  = (control[10:9] == 2'b01) ? portB             :
                       (control[10:9] == 2'b10) ? INSTRUCTION[15:0] :
                            16'h0000;
 
    assign OUT_PORT = (control[11] == 1'b1) ? portA : 16'h0000;
 
     assign WRITE_STROBE = control[29];
 
     assign READ_STROBE  = control[30];
 
     assign stackm1 = stack - 1'b1;
 
     assign weA = control[26];
     assign weB = control[27];
 
     assign addrA = {1'b0, INSTRUCTION[25:16]};
 
     assign portA = {portAup, portAdn};
 
     assign portB = {portBup, portBdn};
 
     assign dataA = (control[19:17] == 3'b001) ? portA    :
                    (control[19:17] == 3'b010) ? portB    :
                         (control[19:17] == 3'b011) ? wresult  :
                         (control[19:17] == 3'b100) ? IN_PORT  :
                    INSTRUCTION[15:0];
 
     assign addrB = (control[21:20] == 2'b01) ? {control[28], stack[9:0]}   :
                    (control[21:20] == 2'b10) ? {control[28], portB[9:0]}   :
                          (control[21:20] == 2'b11) ? {control[28], stackm1[9:0]} :
                    {control[28], INSTRUCTION[9:0]};
 
    assign dataB = (control[23:22] == 2'b01) ? addrp1  :
                    (control[23:22] == 2'b10) ? ADDRESS :
                    portA;
 
    assign addrp1 = addr + 1'b1;
 
     assign ADDRESS = rst ? 16'h0000 :
                      (control[4:2] == 3'b001) ? addrp1            :
                          (control[4:2] == 3'b010) ? INSTRUCTION[15:0] :
                           (control[4:2] == 3'b011) ? portA             :
                            (control[4:2] == 3'b100) ? {14'h0000,IRQload}:
                            (control[4:2] == 3'b101) ? portB             :
                            addr;
 
    //ALU code begins here.
    assign zero = (result == 16'h0000) ? 1'b1 : 1'b0;
 
     assign inst = INSTRUCTION[15:0];
     assign a = portA;
     assign b = portB;
     assign sel = control[16:12];
 
     //OR a | b, a | inst
     wire orc;
     wire [15:0]orr;
 
     assign orc  = 1'b0;    
    assign orr  = sel[0] ? (a | b) : (a | inst);
 
     //AND  a & b, a & inst
     wire andc;
     wire [15:0]andr;
 
     assign andc = 1'b0;    
    assign andr = sel[0] ? (a & b) : (a & inst);
 
     //XOR  a ^ b, a ^ inst
    wire xorc;
     wire [15:0]xorr;
 
     assign xorc = 1'b0;    
    assign xorr = sel[0] ? (a ^ b) : (a ^ inst);
 
    //ADD  ADD a + b, ADDC a + b
    wire addbcarryin, addbcarryout;
     wire [15:0]addbresult;
 
     assign addbcarryin = sel[0] ? carry : 1'b0;    
    assign {addbcarryout, addbresult} = a + b + addbcarryin;
 
    //SUB  SUB a - b, SUBC a - b
    wire subbcarryin, subbcarryout;
     wire [15:0]subbresult;
 
     assign subbcarryin = sel[0] ? carry : 1'b0;    
    assign {subbcarryout, subbresult} = a - b - subbcarryin;
 
    //ADD  ADD a + inst, ADDC a + inst
    wire addicarryin, addicarryout;
     wire [15:0]addiresult;
 
     assign addicarryin = sel[0] ? carry : 1'b0;    
    assign {addicarryout, addiresult} = a + inst + addicarryin;
 
    //SUB  SUB a - inst, SUBC a - inst
    wire subicarryin, subicarryout;
     wire [15:0]subiresult;
 
     assign subicarryin = sel[0] ? carry : 1'b0;    
    assign {subicarryout, subiresult} = a - inst - subicarryin;
 
    //TEST  TEST a and b, TEST a and inst  
    wire testc;
     wire [15:0]testr;
 
     assign testc = ^testr;
    assign testr = sel[0] ?  (a & b) :  (a & inst);
 
    //COMP  COMP a to b, COMP a to inst
    wire tempc1, tempc2, compc;
     wire [15:0]compr;
 
     assign tempc1 = (a < inst) ? 1'b1 : 1'b0;
     assign tempc2 = (a < b)    ? 1'b1 : 1'b0;
 
    assign compc   = sel[0] ? tempc2  : tempc1;
     assign compr   = sel[0] ? (a ^ b) : (a ^ inst);
 
    //LEFT  ROL, ASL
    wire leftc;
     wire [15:0]leftr;
 
    assign leftc = a[15];
     assign leftr = sel[0] ? {a[14:0], carry} : {a[14:0], 1'b0};
 
    //RIGHT ROR, LSR
    wire rightc;
     wire [15:0]rightr;
 
     assign rightc = a[0];
     assign rightr = sel[0] ? {carry, a[15:1]} : {1'b0, a[15:1]};
 
    //CARRY SETC, CLRC
    wire carryc;
     wire [15:0]carryr;
 
    assign carryc = sel[0];
     assign carryr = result;
 
    //LOAD  LOAD carry and result with load, no change.
     wire loadc;
     wire [15:0]loadr;
 
     assign loadc = sel[0] ? load[1]              : carry;
     assign loadr = sel[0] ? {15'h0000,  load[0]} : result;                    
 
    //MUX results
    always @(*)
        case(sel[4:1])
            4'b0000 : wresult <= loadr;
                4'b0001 : wresult <= orr;
                4'b0010 : wresult <= andr;
                4'b0011 : wresult <= xorr;
                4'b0100 : wresult <= addbresult;
                4'b0101 : wresult <= subbresult;
                4'b0110 : wresult <= addiresult;
                4'b0111 : wresult <= subiresult;
                4'b1000 : wresult <= testr;
                4'b1001 : wresult <= compr;
                4'b1010 : wresult <= leftr;
                4'b1011 : wresult <= rightr;
                4'b1100 : wresult <= carryr;
                default : wresult <= loadr;
        endcase
 
    always @(*)
        case(sel[4:1])
            4'b0000 : wcarry <= loadc;
                4'b0001 : wcarry <= orc;
                4'b0010 : wcarry <= andc;
                4'b0011 : wcarry <= xorc;
                4'b0100 : wcarry <= addbcarryout;
                4'b0101 : wcarry <= subbcarryout;
                4'b0110 : wcarry <= addicarryout;
                4'b0111 : wcarry <= subicarryout;
                4'b1000 : wcarry <= testc;
                4'b1001 : wcarry <= compc;
                4'b1010 : wcarry <= leftc;
                4'b1011 : wcarry <= rightc;
                4'b1100 : wcarry <= carryc;
                default : wcarry <= loadc;
        endcase
 
endmodule


VGA.v
`timescale 1ns / 1ps
 
//Address ports:
//0x8000 - 0x87FF Background pattern table A.
//0x8800 - 0x8FFF Background pattern table B.
//0x9000 - 0x97FF Sprite pattern table A.
//0x9800 - 0x9FFF Sprite pattern table B.
//0xA000 - 0xA3FF Name table.
//0xA400 - 0xA4FF Unused.
//0xA500 - 0xA5FF Background attribute table.
//0xA600 - 0xA60F Background pallettes 0 through 15.
//0xA610 - 0xA61F Sprite pallettes 0 through 15.
//0xA700          Base color (background color).
//0xB000 - 0xB3FF Sprite RAM (256 sprites).
 
module VGA(
    input clk25MHz,
    input clk,
    input write,
    input [15:0]id,
    input [7:0]data,
    output reg vblank = 1'b0,    
    output reg vsync = 1'b1,
    output reg hsync = 1'b1,
    output reg [7:0]vga = 8'h00
    );
 
    parameter WAIT  = 5'h00;
    parameter NTAT  = 5'h01;
    parameter PTAB  = 5'h02;
    parameter BUFF  = 5'h03;
    parameter NEXT  = 5'h04;
    parameter SPRAM = 5'h05;
    parameter SAB   = 5'h06;
    parameter WRIT0 = 5'h07;
    parameter WRIT1 = 5'h08;
    parameter WRIT2 = 5'h09;
    parameter WRIT3 = 5'h0A;
    parameter WRIT4 = 5'h0B;
    parameter WRIT5 = 5'h0C;
    parameter WRIT6 = 5'h0D;
    parameter WRIT7 = 5'h0E;
    parameter BUFF0 = 5'h0F;                
    parameter BUFF1 = 5'h10;                  
    parameter BUFF2 = 5'h11;                  
    parameter BUFF3 = 5'h12;                
    parameter BUFF4 = 5'h13;                
    parameter BUFF5 = 5'h14;                  
    parameter BUFF6 = 5'h15;                
    parameter BUFF7 = 5'h16;                
 
    reg [9:0]hcount       = 10'h001;
    reg [9:0]vcount       = 10'h001;
    reg [9:0]nextpixel    = 10'h000;
    reg [9:0]nextpixel2   = 10'h000;
    reg [8:0]currline     =  9'h000;
    reg [9:0]next256pixel =  9'h000;
 
    wire [8:0]nxt256pix;
    wire [7:0]cur256line;
    wire [7:0]nxt256line;
    wire [7:0]colorout;    
 
    reg [8:0]currsprite = 9'h000;
    reg [7:0]basecolor  = 8'h00;
 
    reg [7:0]bgpal0  = 8'b00000000;
    reg [7:0]bgpal1  = 8'b00111000;
    reg [7:0]bgpal2  = 8'b00100000;
    reg [7:0]bgpal3  = 8'b00011000;
    reg [7:0]bgpal4  = 8'b00000000;
    reg [7:0]bgpal5  = 8'b00111111;
    reg [7:0]bgpal6  = 8'b00100100;
    reg [7:0]bgpal7  = 8'b00011011;
    reg [7:0]bgpal8  = 8'b00000000;
    reg [7:0]bgpal9  = 8'b00011111;
    reg [7:0]bgpal10 = 8'b00010100;
    reg [7:0]bgpal11 = 8'b00001010;
    reg [7:0]bgpal12 = 8'b00000000;
    reg [7:0]bgpal13 = 8'b00000111;
    reg [7:0]bgpal14 = 8'b00000100;
    reg [7:0]bgpal15 = 8'b00000011;
 
    reg [7:0]sppal0  = 8'b00000000;
    reg [7:0]sppal1  = 8'b00100110;
    reg [7:0]sppal2  = 8'b00111111;
    reg [7:0]sppal3  = 8'b00000010;
    reg [7:0]sppal4  = 8'b00000000;
    reg [7:0]sppal5  = 8'b10111111;
    reg [7:0]sppal6  = 8'b10100100;
    reg [7:0]sppal7  = 8'b10011011;
    reg [7:0]sppal8  = 8'b00000000;
    reg [7:0]sppal9  = 8'b10011111;
    reg [7:0]sppal10 = 8'b10010100;
    reg [7:0]sppal11 = 8'b10001010;
    reg [7:0]sppal12 = 8'b00000000;
    reg [7:0]sppal13 = 8'b10000111;
    reg [7:0]sppal14 = 8'b10000100;
    reg [7:0]sppal15 = 8'b10000011;
 
    always @(posedge clk) begin
        if(id == 16'hA600 && write) bgpal0 <= data;
        if(id == 16'hA601 && write) bgpal1 <= data;
        if(id == 16'hA602 && write) bgpal2 <= data;
        if(id == 16'hA603 && write) bgpal3 <= data;
        if(id == 16'hA604 && write) bgpal4 <= data;
        if(id == 16'hA605 && write) bgpal5 <= data;
        if(id == 16'hA606 && write) bgpal6 <= data;
        if(id == 16'hA607 && write) bgpal7 <= data;
        if(id == 16'hA608 && write) bgpal8 <= data;
        if(id == 16'hA609 && write) bgpal9 <= data;
        if(id == 16'hA60A && write) bgpal10 <= data;
        if(id == 16'hA60B && write) bgpal11 <= data;
        if(id == 16'hA60C && write) bgpal12 <= data;
        if(id == 16'hA60D && write) bgpal13 <= data;
        if(id == 16'hA60E && write) bgpal14 <= data;
        if(id == 16'hA60F && write) bgpal15 <= data;
 
        if(id == 16'hA610 && write) sppal0  <= data;
        if(id == 16'hA611 && write) sppal1  <= data;
        if(id == 16'hA612 && write) sppal2  <= data;
        if(id == 16'hA613 && write) sppal3  <= data;
        if(id == 16'hA614 && write) sppal4  <= data;
        if(id == 16'hA615 && write) sppal5  <= data;
        if(id == 16'hA616 && write) sppal6  <= data;
        if(id == 16'hA617 && write) sppal7  <= data;
        if(id == 16'hA618 && write) sppal8  <= data;
        if(id == 16'hA619 && write) sppal9  <= data;
        if(id == 16'hA61A && write) sppal10  <= data;
        if(id == 16'hA61B && write) sppal11  <= data;
        if(id == 16'hA61C && write) sppal12  <= data;
        if(id == 16'hA61D && write) sppal13  <= data;
        if(id == 16'hA61E && write) sppal14  <= data;
        if(id == 16'hA61F && write) sppal15  <= data;
 
        if(id == 16'hA700 && write) basecolor <= data;
    end
 
    //Line buffer wires and regs.
    reg  lbwe = 1'b0;
    wire [8:0]lbaddra;
    wire [7:0]lbdin;
    wire lbrstb;
    wire [8:0]lbaddrb;
    wire [7:0]lbdout;
    wire [7:0]lbcheck;
 
    RAMB16_S9_S9 #(
        //Test pattern.
        .INIT_00(256'h00_01_02_03_04_05_06_07_08_09_0A_0B_0C_0D_0E_0F_10_11_12_13_14_15_16_17_18_19_1A_1B_1C_1D_1E_1F),
        .INIT_01(256'h20_21_22_23_24_25_26_27_28_29_2A_2B_2C_2D_2E_2F_30_31_32_33_34_35_36_37_38_39_3A_3B_3C_3D_3E_3F),
        .INIT_02(256'h40_41_42_43_44_45_46_47_48_49_4A_4B_4C_4D_4E_4F_50_51_52_53_54_55_56_57_58_59_5A_5B_5C_5D_5E_5F),
        .INIT_03(256'h60_61_62_63_64_65_66_67_68_69_6A_6B_6C_6D_6E_6F_70_71_72_73_74_75_76_77_78_79_7A_7B_7C_7D_7E_7F),
        .INIT_04(256'h80_81_82_83_84_85_86_87_88_89_8A_8B_8C_8D_8E_8F_90_91_92_93_94_95_96_97_98_99_9A_9B_9C_9D_9E_9F),
        .INIT_05(256'hA0_A1_A2_A3_A4_A5_A6_A7_A8_A9_AA_AB_AC_AD_AE_AF_B0_B1_B2_B3_B4_B5_B6_B7_B8_B9_BA_BB_BC_BD_BE_BF),
        .INIT_06(256'hC0_C1_C2_C3_C4_C5_C6_C7_C8_C9_CA_CB_CC_CD_CE_CF_D0_D1_D2_D3_D4_D5_D6_D7_D8_D9_DA_DB_DC_DD_DE_DF),
        .INIT_07(256'hE0_E1_E2_E3_E4_E5_E6_E7_E8_E9_EA_EB_EC_ED_EE_EF_F0_F1_F2_F3_F4_F5_F6_F7_F8_F9_FA_FB_FC_FD_FE_FF),
        .INIT_08(256'h0F_0E_0D_0C_0B_0A_09_08_07_06_05_04_03_02_01_00_1F_1E_1D_1C_1B_1A_19_18_17_16_15_14_13_12_11_10),
        .INIT_09(256'h2F_2E_2D_2C_2B_2A_29_28_27_26_25_24_23_22_21_20_3F_3E_3D_3C_3B_3A_39_38_37_36_35_34_33_32_31_30),
        .INIT_0A(256'h4F_4E_4D_4C_4B_4A_49_48_47_46_45_44_43_42_41_40_5F_5E_5D_5C_5B_5A_59_58_57_56_55_54_53_52_51_50),
        .INIT_0B(256'h6F_6E_6D_6C_6B_6A_69_68_67_66_65_64_63_62_61_60_7F_7E_7D_7C_7B_7A_79_78_77_76_75_74_73_72_71_70),
        .INIT_0C(256'h8F_8E_8D_8C_8B_8A_89_88_87_86_85_84_83_82_81_80_9F_9E_9D_9C_9B_9A_99_98_97_96_95_94_93_92_91_90),
        .INIT_0D(256'hAF_AE_AD_AC_AB_AA_A9_A8_A7_A6_A5_A4_A3_A2_A1_A0_BF_BE_BD_BC_BB_BA_B9_B8_B7_B6_B5_B4_B3_B2_B1_B0),
        .INIT_0E(256'hCF_CE_CD_CC_CB_CA_C9_C8_C7_C6_C5_C4_C3_C2_C1_C0_DF_DE_DD_DC_DB_DA_D9_D8_D7_D6_D5_D4_D3_D2_D1_D0),
        .INIT_0F(256'hEF_EE_ED_EC_EB_EA_E9_E8_E7_E6_E5_E4_E3_E2_E1_E0_FF_FE_FD_FC_FB_FA_F9_F8_F7_F6_F5_F4_F3_F2_F1_F0))
    LineBufferRAM (
        .DOA(lbcheck),    
        .DOB(lbdout),             // Port B 8-bit Data Output      
        .ADDRA({2'b00, lbaddra}), // Port A 11-bit Address Input
        .ADDRB({2'b00, lbaddrb}), // Port B 11-bit Address Input
        .CLKA(clk),               // Port A Clock
        .CLKB(clk25MHz),          // Port B Clock
        .DIA(lbdin),              // Port A 8-bit Data Input
        .DIPA(1'b0),              // 1-bit Parity
        .ENA(1'b1),               // Port A RAM Enable Input
        .ENB(1'b1),               // Port B RAM Enable Input
        .SSRA(1'b0),              // Port A Synchronous Set/Reset Input
        .SSRB(lbrstb),            // Port B Synchronous Set/Reset Input
        .WEA(lbwe),               // Port A Write Enable Input
        .WEB(1'b0)                // Port B Write Enable Input
    );
 
    //Name table wires and regs.
    wire [7:0]ntdout;
    wire [9:0]ntaddra;
    wire [9:0]ntaddrb;
    wire [7:0]ntdin;
    wire ntwe;
 
    assign ntdin = data;
    assign ntaddrb = id - 16'hA000;
    assign ntwe = (id >= 16'hA000 && id <= 16'hA3FF) ? write : 1'b0;
 
    RAMB16_S9_S9 #(
        .INIT_00(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_01(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_02(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_03(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_04(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_05(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_06(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_07(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_08(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_09(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_0A(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_0B(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_0C(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_0D(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_0E(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_0F(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_10(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_11(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_12(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_13(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_14(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_15(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_16(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_17(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_18(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_19(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_1A(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_1B(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_1C(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_1D(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_1E(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF),
        .INIT_1F(256'hFF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF_FF))
     NameTableRAM (
        .DOA(ntdout),             // Port B 8-bit Data Output
        .ADDRA({1'b0, ntaddra}),  // Port A 11-bit Address Input
        .ADDRB({1'b0, ntaddrb}),  // Port B 11-bit Address Input
        .CLKA(clk),               // Port A Clock
        .CLKB(clk),               // Port B Clock
        .DIB(ntdin),              // Port A 8-bit Data Input
        .DIPB(1'b0),              // 1-bit Parity
        .ENA(1'b1),               // Port A RAM Enable Input
        .ENB(1'b1),               // Port B RAM Enable Input
        .SSRA(1'b0),              // Port A Synchronous Set/Reset Input
        .SSRB(1'b0),              // Port B Synchronous Set/Reset Input
        .WEA(1'b0),               // Port A Write Enable Input
        .WEB(ntwe)                // Port B Write Enable Input
    );
 
    //Background pattern table A wires.
    wire [7:0]bgptadout;
    wire [10:0]bgptaaddra;
    wire [10:0]bgptaaddrb;
    wire [7:0]bgptadin;
    wire bgptawe;
 
    assign bgptadin = data;
    assign bgptaaddrb = id - 16'h8000;
    assign bgptawe = (id >= 16'h8000 && id <= 16'h87FF) ? write : 1'b0;     
 
    RAMB16_S9_S9 #(
        .INIT_00(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_01(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_02(256'h00_FC_C6_C6_FC_C6_C6_FC_00_C6_C6_FE_C6_C6_6C_38_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_03(256'h00_C0_C0_C0_FC_C0_C0_FE_00_FE_C0_C0_FC_C0_C0_FE_00_F8_CC_C6_C6_C6_CC_F8_00_3C_66_C0_C0_C0_66_3C),
        .INIT_04(256'h00_7C_C6_C6_06_06_06_1E_00_7E_18_18_18_18_18_7E_00_C6_C6_C6_FE_C6_C6_C6_00_3E_66_C6_CE_C0_60_3E),
        .INIT_05(256'h00_C6_CE_DE_FE_F6_E6_C6_00_C6_C6_D6_FE_FE_EE_C6_00_7E_60_60_60_60_60_60_00_CE_DC_F8_F0_D8_CC_C6),
        .INIT_06(256'h00_CE_DC_F8_CE_C6_C6_FC_00_7A_CC_DE_C6_C6_C6_7C_00_C0_C0_FC_C6_C6_C6_FC_00_7C_C6_C6_D6_C6_C6_7C),
        .INIT_07(256'h00_10_38_7C_EE_C6_C6_C6_00_7C_C6_C6_C6_C6_C6_C6_00_18_18_18_18_18_18_7E_00_7C_C6_06_7C_C0_CC_78),
        .INIT_08(256'h00_FE_E0_70_38_1C_0E_FE_00_18_18_18_3C_66_66_66_00_C6_EE_7C_38_7C_EE_C6_00_C6_EE_FE_FE_D6_C6_C6),
        .INIT_09(256'h00_1C_24_24_1C_04_04_00_00_38_40_40_40_38_00_00_00_38_24_24_38_20_20_00_00_34_48_48_38_08_30_00),
        .INIT_0A(256'h00_24_24_24_38_20_20_00_00_08_14_0C_3A_48_30_00_00_10_10_10_3C_10_18_00_00_3C_40_78_44_38_00_00),
        .INIT_0B(256'h00_16_08_14_14_14_08_00_00_4C_70_50_48_40_40_00_00_30_48_08_08_00_08_00_00_10_10_10_00_10_00_00),
        .INIT_0C(256'h00_20_20_38_24_24_38_00_00_30_48_48_48_30_00_00_00_48_48_48_48_30_00_00_00_54_54_54_54_28_00_00),
        .INIT_0D(256'h00_18_20_20_20_70_20_00_00_78_04_38_40_38_00_00_00_10_10_10_1C_60_00_00_00_04_0A_38_48_48_30_00),
        .INIT_0E(256'h00_44_28_10_28_44_00_00_00_28_54_54_54_44_00_00_00_10_38_28_44_44_00_00_00_34_48_48_48_48_00_00),
        .INIT_0F(256'h00_00_00_00_7C_00_00_00_00_08_00_08_02_22_1C_00_00_7C_20_10_08_7C_00_00_00_18_24_04_1C_24_24_00),
        .INIT_10(256'h04_04_FC_00_00_00_00_01_20_20_3F_00_00_00_00_80_80_00_00_00_00_00_00_00_01_00_00_00_00_00_00_00),
        .INIT_11(256'h82_82_82_82_82_82_82_82_FF_00_00_00_00_00_FF_00_FE_02_02_02_02_02_FE_00_7F_40_40_40_40_40_7F_00),
        .INIT_12(256'h00_00_FF_80_00_00_00_80_00_00_FF_01_00_00_00_01_82_82_82_82_82_02_04_08_41_41_41_41_41_40_20_10),
        .INIT_13(256'h10_60_80_00_00_00_00_00_08_06_01_00_00_00_00_00_02_02_04_08_10_60_80_00_40_40_20_10_08_06_01_00),
        .INIT_14(256'h01_00_00_00_00_FC_04_04_80_00_00_00_00_3F_20_20_00_00_00_00_00_00_00_80_00_00_00_00_00_00_00_01),
        .INIT_15(256'h00_FF_00_00_00_00_00_FF_41_41_41_41_41_41_41_41_00_FE_82_82_82_82_82_82_00_7F_40_40_40_40_40_7F),
        .INIT_16(256'h80_00_00_00_80_FF_00_00_01_00_00_00_01_FF_00_00_08_04_02_82_82_82_82_82_10_20_40_41_41_41_41_41),
        .INIT_17(256'h00_00_00_00_00_80_60_10_00_00_00_00_00_01_06_08_00_80_60_10_08_04_02_02_00_01_06_08_10_20_40_40),
        .INIT_18(256'h00_00_00_00_00_7F_40_40_40_40_7F_00_00_00_00_00_00_00_FF_00_00_00_00_00_00_00_00_00_00_FF_00_00),
        .INIT_19(256'h20_20_20_20_10_08_04_02_80_80_00_00_00_00_00_00_00_00_01_01_02_0C_F0_00_00_80_40_20_10_0C_03_00),
        .INIT_1A(256'h00_00_00_00_00_3F_20_20_04_04_FC_80_80_80_80_80_00_00_C0_40_40_40_40_C0_00_00_1F_10_08_04_02_01),
        .INIT_1B(256'h1C_22_41_41_41_22_1C_00_00_80_80_80_80_80_80_80_80_80_80_80_80_FC_04_04_40_40_40_40_40_C0_00_00),
        .INIT_1C(256'h41_40_40_40_40_40_7F_00_00_FE_02_02_02_02_02_FE_00_7F_40_40_40_40_40_40_01_00_00_00_00_00_00_00),
        .INIT_1D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_61_41_43_00_61_41_43_00_40_40_41_41_41_41_41_41),
        .INIT_1E(256'h00_00_00_00_00_00_00_00_FF_FF_AA_55_AA_55_AA_55_AA_55_AA_55_AA_55_AA_55_AA_55_AA_55_AA_55_FF_FF),
        .INIT_1F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_61_41_43_00_61_41_43_00),
        .INIT_20(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_21(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_22(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_23(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_24(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_25(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_26(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_27(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_28(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_29(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2A(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2B(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2C(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2E(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_30(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_31(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_32(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_33(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_34(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_35(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_36(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_37(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_38(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_39(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3A(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3B(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3C(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3E(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00))    
    BGPatternTableARAM (
        .DOA(bgptadout),          // Port B 8-bit Data Output
        .ADDRA(bgptaaddra),       // Port A 11-bit Address Input
        .ADDRB(bgptaaddrb),       // Port B 11-bit Address Input
        .CLKA(clk),               // Port A Clock
        .CLKB(clk),               // Port B Clock
        .DIB(bgptadin),           // Port A 8-bit Data Input
        .DIPB(1'b0),              // 1-bit Parity
        .ENA(1'b1),               // Port A RAM Enable Input
        .ENB(1'b1),               // Port B RAM Enable Input
        .SSRA(1'b0),              // Port A Synchronous Set/Reset Input
        .SSRB(1'b0),              // Port B Synchronous Set/Reset Input
        .WEA(1'b0),               // Port A Write Enable Input
        .WEB(bgptawe)             // Port B Write Enable Input
    );
 
    //Background pattern table B wires.
    wire [7:0]bgptbdout;
    wire [10:0]bgptbaddra;
    wire [10:0]bgptbaddrb;
    wire [7:0]bgptbdin;
    wire bgptbwe;    
 
    assign bgptbdin = data;
    assign bgptbaddrb = id - 16'h8800;
    assign bgptbwe = (id >= 16'h8800 && id <= 16'h8FFF) ? write : 1'b0;
 
    RAMB16_S9_S9 #(
        .INIT_00(256'h00_7C_C6_06_3C_18_0C_7E_00_FE_E0_78_3C_0E_C6_7C_00_7E_18_18_18_18_38_18_00_7C_C6_C6_C6_C6_C6_7C),
        .INIT_01(256'h00_30_30_30_18_0C_C6_FE_00_7C_C6_C6_FC_C0_60_3C_00_7C_C6_06_06_FC_C0_FC_00_0C_0C_FE_CC_6C_3C_1C),
        .INIT_02(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_78_0C_06_7E_C6_C6_7C_00_7C_C6_C6_7C_C6_C6_7C),
        .INIT_03(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_04(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_05(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_06(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_07(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_08(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_09(256'h00_1C_24_24_1C_04_04_00_00_38_40_40_40_38_00_00_00_38_24_24_38_20_20_00_00_34_48_48_38_08_30_00),
        .INIT_0A(256'h00_24_24_24_38_20_20_00_00_08_14_0C_3A_48_30_00_00_10_10_10_3C_10_18_00_00_3C_40_78_44_38_00_00),
        .INIT_0B(256'h00_16_08_14_14_14_08_00_00_4C_70_50_48_40_40_00_00_30_48_08_08_00_08_00_00_10_10_10_00_10_00_00),
        .INIT_0C(256'h00_20_20_38_24_24_38_00_00_30_48_48_48_30_00_00_00_48_48_48_48_30_00_00_00_54_54_54_54_28_00_00),
        .INIT_0D(256'h00_18_20_20_20_70_20_00_00_78_04_38_40_38_00_00_00_10_10_10_1C_60_00_00_00_04_0A_38_48_48_30_00),
        .INIT_0E(256'h00_44_28_10_28_44_00_00_00_28_54_54_54_44_00_00_00_10_38_28_44_44_00_00_00_34_48_48_48_48_00_00),
        .INIT_0F(256'h00_00_00_00_7C_00_00_00_00_08_00_08_02_22_1C_00_00_7C_20_10_08_7C_00_00_00_18_24_04_1C_24_24_00),
        .INIT_10(256'hF8_F8_00_00_00_00_00_01_3F_3F_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_11(256'hFC_FC_FC_FC_FC_FC_FC_FC_FF_FF_FF_FF_FF_FF_00_00_FC_FC_FC_FC_FC_FC_00_00_7F_7F_7F_7F_7F_7F_00_00),
        .INIT_12(256'hFF_FF_00_00_00_00_00_00_FF_FF_00_00_00_00_00_01_FC_FC_FC_FC_FC_FC_F8_F0_7E_7E_7E_7E_7E_7F_3F_1F),
        .INIT_13(256'hE0_80_00_00_00_00_00_00_0F_07_00_00_00_00_00_00_FC_FC_F8_F0_E0_80_00_00_7F_7F_3F_1F_0F_07_00_00),
        .INIT_14(256'h00_00_00_00_00_F8_F8_F8_00_00_00_00_00_3F_3F_3F_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_01),
        .INIT_15(256'h00_FF_FF_FF_FF_FF_FF_00_7E_7E_7E_7E_7E_7E_7E_7E_00_FC_FC_FC_FC_FC_FC_FC_00_7F_7F_7F_7F_7F_7F_00),
        .INIT_16(256'h00_00_00_00_00_FF_FF_FF_00_00_00_00_01_FF_FF_FF_F0_F8_FC_FC_FC_FC_FC_FC_1F_3F_7F_7E_7E_7E_7E_7E),
        .INIT_17(256'h00_00_00_00_00_00_80_E0_00_00_00_00_00_01_07_0F_00_80_80_E0_F0_F8_FC_FC_00_01_07_0F_1F_3F_7F_7F),
        .INIT_18(256'h00_00_00_00_00_7F_7F_7F_7F_7F_00_00_00_00_00_00_FF_FF_00_00_00_00_00_00_00_00_00_00_00_FF_FF_FF),
        .INIT_19(256'h3F_3F_3F_3F_1F_0F_07_03_00_00_00_00_00_00_00_00_FF_FF_FE_FE_FC_F0_00_00_FF_FF_7F_3F_1F_0F_00_00),
        .INIT_1A(256'h00_00_00_00_00_3F_3F_3F_F8_F8_00_00_00_00_00_00_FF_FF_7F_7F_7F_7F_7F_7F_FF_FF_E0_E0_F0_F8_FC_FE),
        .INIT_1B(256'h1C_3C_7E_7E_7E_3C_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_F8_F8_F8_7F_7F_7F_7F_7F_FF_FF_FF),
        .INIT_1C(256'h7F_7F_7F_7F_7F_7F_00_00_00_FC_FC_FC_FC_FC_FC_00_00_7F_7F_7F_7F_7F_7F_7F_01_00_00_00_00_00_00_00),
        .INIT_1D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_7F_7F_7E_7E_7E_7E_7E_7E),
        .INIT_1E(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_1F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_7E_7E_7C_00_7E_7E_7C_00),
        .INIT_20(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_21(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_22(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_23(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_24(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_25(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_26(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_27(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_28(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_29(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2A(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2B(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2C(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2E(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_30(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_31(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_32(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_33(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_34(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_35(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_36(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_37(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_38(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_39(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3A(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3B(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3C(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3E(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00))
    BGPatternTableBRAM (
        .DOA(bgptbdout),          // Port B 8-bit Data Output
        .ADDRA(bgptbaddra),       // Port A 11-bit Address Input
        .ADDRB(bgptbaddrb),       // Port B 11-bit Address Input
        .CLKA(clk),               // Port A Clock
        .CLKB(clk),               // Port B Clock
        .DIB(bgptbdin),           // Port A 8-bit Data Input
        .DIPB(1'b0),              // 1-bit Parity
        .ENA(1'b1),               // Port A RAM Enable Input
        .ENB(1'b1),               // Port B RAM Enable Input
        .SSRA(1'b0),              // Port A Synchronous Set/Reset Input
        .SSRB(1'b0),              // Port B Synchronous Set/Reset Input
        .WEA(1'b0),               // Port A Write Enable Input
        .WEB(bgptbwe)             // Port B Write Enable Input
    );
 
    //Background attribute table wires.
    wire [7:0]bgatdout;
    wire [7:0]bgataddra;
    wire [7:0]bgataddrb;
    wire [7:0]bgatdin;
    wire bgatwe;    
 
    assign bgatdin = data;
    assign bgataddrb = id - 16'hA500;
    assign bgatwe = (id >= 16'hA500 && id <= 16'hA5FF) ? write : 1'b0;
 
    RAMB16_S9_S9 #(
        .INIT_00(256'hAA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA),
        .INIT_01(256'hAA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA),
        .INIT_02(256'hAA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA),
        .INIT_03(256'hFF_FF_FF_FF_FF_FF_FF_FF_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA),
        .INIT_04(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_05(256'h56_55_55_55_55_55_55_55_55_55_55_55_55_55_55_55_55_55_55_55_55_55_55_55_56_55_55_55_55_55_55_55),
        .INIT_06(256'hAA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_55_55_55_55_55_55_55_55_55_55_55_55_55_55_55_55),
        .INIT_07(256'hAA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA_AA))
    BGAttributeTableRAM (
        .DOA(bgatdout),            // Port B 8-bit Data Output
        .ADDRA({3'h0, bgataddra}), // Port A 11-bit Address Input
        .ADDRB({3'h0, bgataddrb}), // Port B 11-bit Address Input
        .CLKA(clk),                // Port A Clock
        .CLKB(clk),                // Port B Clock
        .DIB(bgatdin),             // Port A 8-bit Data Input
        .DIPB(1'b0),               // 1-bit Parity
        .ENA(1'b1),                // Port A RAM Enable Input
        .ENB(1'b1),                // Port B RAM Enable Input
        .SSRA(1'b0),               // Port A Synchronous Set/Reset Input
        .SSRB(1'b0),               // Port B Synchronous Set/Reset Input
        .WEA(1'b0),                // Port A Write Enable Input
        .WEB(bgatwe)               // Port B Write Enable Input
    );
 
    //Sprite RAM wires.
    wire spwe;
    wire [9:0]spaddra;
    wire [7:0]spdin;
    wire [7:0]spaddrb;
    wire [31:0]spdout;
 
    assign spwe = (id >= 16'hB000 && id <= 16'hB3FF) ? write : 1'b0;
    assign spaddra = id - 16'hB000;
    assign spdin = data;
    assign spaddrb = (currsprite) ? currsprite - 1'b1 : 8'h00;
 
    BRAM_TDP_MACRO #(
        .BRAM_SIZE("36Kb"), // Target BRAM: "18Kb" or "36Kb"      
        .READ_WIDTH_A (8),  // Valid values are 1-36 (19-36 only valid when BRAM_SIZE="36Kb")
        .READ_WIDTH_B (32), // Valid values are 1-36 (19-36 only valid when BRAM_SIZE="36Kb")
        .WRITE_WIDTH_A(8),  // Valid values are 1-36 (19-36 only valid when BRAM_SIZE="36Kb")
        .WRITE_WIDTH_B(32), // Valid values are 1-36 (19-36 only valid when BRAM_SIZE="36Kb")
        .INIT_00(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_01(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_02(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_03(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_04(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_05(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_06(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_07(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
 
        .INIT_08(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_09(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_0A(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_0B(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_0C(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_0D(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_0E(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_0F(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
 
        .INIT_10(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_11(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_12(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_13(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_14(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_15(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_16(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_17(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
 
        .INIT_18(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_19(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_1A(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_1B(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_1C(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_1D(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_1E(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF),
        .INIT_1F(256'h00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF__00_00_00_FF)
    ) SpriteRAM (
        .DOB(spdout),               // Port B 32-bit Data Output
        .ADDRA({2'b00, spaddra}),   // Port A 12-bit Address Input
        .ADDRB({2'b00, spaddrb}),   // Port B 10-bit Address Input
        .CLKA(clk),                 // Port A Clock
        .CLKB(clk),                 // Port B Clock
        .DIA(spdin),                // Port A 8-bit Data Input
        .DIB(32'h00000000),         // Port B 32-bit Data Input
        .ENA(1'b1),                 // Port A RAM Enable Input
        .ENB(1'b1),                 // Port B RAM Enable Input
        .RSTA(1'b0),                // 1-bit input port-A reset
        .RSTB(1'b0),                // 1-bit input port-B reset
        .WEA(spwe),                 // Port A Write Enable Input
        .WEB(1'b0)                  // Port B Write Enable Input
    );
 
     wire awe;
     wire [10:0]aaddra;
     wire [7:0]adin;
     wire [10:0]aaddrb;
     wire [7:0]adout;
 
     assign awe = (id >= 16'h9000 && id <= 16'h97FF) ? write : 1'b0;
     assign aaddra = id - 16'h9000;
     assign adin = data;
 
     RAMB16_S9_S9 #(
        .INIT_00(256'hD0_70_F8_F8_F8_F0_E0_80_3E_0F_06_25_16_1F_0F_03_E0_30_F0_F0_E0_C0_00_00_1D_0D_4B_2D_3F_1F_07_00),
        .INIT_01(256'h30_70_7C_FE_ED_ED_F6_F6_E0_E0_F0_F0_F0_E0_C0_00_7D_1F_0D_4B_2D_3F_1F_07_00_3C_7E_7E_7E_7E_3C_00),
        .INIT_02(256'h04_64_00_12_00_09_27_00_6E_38_08_48_A0_D0_E0_80_76_1C_10_12_05_0B_07_01_00_00_00_60_E0_C0_80_00),
        .INIT_03(256'hEC_CC_9C_98_B8_F0_E0_C0_5C_B0_60_A4_68_F8_F0_C0_0F_0F_1F_1F_1F_0F_07_01_04_28_00_48_20_50_60_84),
        .INIT_04(256'hE0_E0_F8_FE_FF_FF_FB_BE_01_03_33_1D_0E_06_0B_1D_C0_E0_F8_F8_38_F0_E0_40_13_0B_0B_1D_0D_15_3A_7B),
        .INIT_05(256'h00_00_00_00_20_00_00_20_E0_E0_F0_F8_FC_F6_EE_F8_33_7B_FD_FE_EF_67_11_3F_BD_18_18_18_00_3C_18_18),
        .INIT_06(256'h01_00_C0_11_70_2C_D8_0A_EF_93_63_F2_FE_FC_BF_5F_09_91_C6_4F_7F_3F_FD_FA_68_FC_AE_F7_DA_77_3F_0C),
        .INIT_07(256'hFF_FF_FE_FE_FE_F6_F6_EE_9A_3E_FC_E0_F8_FC_FE_BE_07_07_0F_0E_1E_1D_1D_1E_04_00_20_10_6E_E8_93_50),
        .INIT_08(256'h3C_70_60_E0_E0_F0_F0_F0_1D_03_1F_1E_38_77_7F_3F_F8_E0_E0_E0_F0_F0_F0_E0_01_00_01_01_00_00_01_01),
        .INIT_09(256'h00_18_B8_B0_B0_C0_C0_00_1C_3F_3F_77_E3_F1_F1_F0_1C_0E_0E_07_07_03_01_01_00_00_00_00_18_BD_FF_99),
        .INIT_0A(256'h70_98_C0_08_58_62_38_20_18_38_30_30_7C_66_F6_FF_18_1C_0C_0C_02_00_01_01_7F_FF_FF_3F_FF_FF_FF_40),
        .INIT_0B(256'hFF_FF_FF_FF_FF_FF_FF_FF_F0_38_38_70_F0_E0_C0_80_07_07_07_07_07_0F_0F_0F_0E_05_4B_10_12_06_04_00),
        .INIT_0C(256'h03_01_00_01_02_07_1F_3F_00_00_00_00_00_00_78_3C_7A_37_0F_1F_3E_3F_7B_FE_00_00_08_3C_38_3C_08_00),
        .INIT_0D(256'h00_00_18_3C_3C_34_18_00_00_80_C0_C0_80_00_00_18_3E_1E_09_07_07_07_0E_1C_80_C0_C0_C0_C0_00_C0_80),
        .INIT_0E(256'h00_3D_1D_0B_07_07_07_07_00_00_66_66_66_00_00_00_70_F8_F0_08_78_38_38_38_FF_FF_FF_FF_FF_FF_FF_00),
        .INIT_0F(256'h81_80_A7_A3_A3_91_60_1F_74_A0_A4_80_20_40_00_00_01_07_23_AA_DD_6A_A1_48_3C_1C_83_8F_9F_3E_F8_F0),
        .INIT_10(256'hCC_DE_BE_7C_F0_E0_88_FC_07_07_07_07_1F_37_37_1F_E0_80_C0_F0_60_A8_5C_DE_07_0F_1F_1F_1C_0F_07_02),
        .INIT_11(256'h03_05_0D_0E_3E_36_7A_7D_00_00_00_00_02_00_00_02_80_80_38_1C_1C_38_D0_B8_07_07_18_7C_FC_F8_C7_7D),
        .INIT_12(256'h00_00_00_00_40_00_00_40_C0_E0_D0_B0_FC_7C_BE_FE_07_07_0F_1F_3E_3F_1F_0F_E0_F0_F8_FC_DE_EE_FC_F0),
        .INIT_13(256'hFF_93_9F_95_93_93_83_81_14_2D_16_3A_1D_4A_5C_A8_0F_17_1A_1C_1C_38_38_38_3C_66_C3_99_99_C3_66_3C),
        .INIT_14(256'h78_F0_E0_E0_C0_C0_00_00_5F_74_77_3F_3F_1F_07_00_FC_F8_F8_F0_C0_00_00_00_33_1B_1F_0F_03_00_00_00),
        .INIT_15(256'h14_3E_7C_5E_7C_7E_3F_14_A0_C0_E0_E0_40_00_00_00_7B_BD_DE_EF_FF_FF_FE_F8_FB_FC_7F_7F_1F_07_03_00),
        .INIT_16(256'h00_00_00_00_00_00_00_00_3F_1F_0F_1F_3F_7B_71_20_00_17_14_54_57_B4_17_00_00_49_49_49_49_49_E9_00),
        .INIT_17(256'hE0_40_60_F0_F0_60_40_E0_01_00_11_77_77_11_00_01_00_00_00_00_00_00_00_00_3C_66_C3_81_81_C3_66_3C),
        .INIT_18(256'hFE_DE_7E_FE_FC_7C_FC_78_3D_3F_1F_78_7C_7E_3F_1F_C0_70_F8_F8_FC_FC_FC_FC_03_0F_1F_1F_3F_3F_3F_37),
        .INIT_19(256'h00_00_00_00_00_00_40_20_00_00_00_00_20_60_60_60_00_C0_D8_F8_BC_BE_AF_B7_00_00_11_3B_7F_7F_F7_F7),
        .INIT_1A(256'hC0_80_80_00_00_00_00_00_00_08_18_30_F0_60_C0_80_18_00_00_48_00_00_00_00_1C_3E_7F_7F_7F_7F_3E_1C),
        .INIT_1B(256'hFF_01_7D_7D_7D_7D_7D_01_FF_01_41_41_41_41_7D_01_00_00_00_00_00_00_00_00_F0_F0_F0_E0_E0_E0_C0_C0),
        .INIT_1C(256'hD0_B8_78_F0_F8_DC_BE_7E_07_03_00_01_01_07_1F_3F_3C_7E_F3_C1_C1_F3_7E_3C_3C_7E_F3_C1_C1_F3_7E_3C),
        .INIT_1D(256'h07_07_0F_0F_0F_1F_1F_1F_FE_FE_C0_FC_FC_C0_FE_FE_20_30_98_36_4A_35_48_02_0A_09_05_01_00_00_00_00),
        .INIT_1E(256'h05_05_05_06_07_07_07_06_A0_F0_F0_F0_F0_E0_E0_E0_3B_7B_7B_79_3D_3F_1F_07_80_C0_C0_A0_60_60_60_C0),
        .INIT_1F(256'hC6_CE_DE_FE_FE_F6_E6_C6_FC_FC_FC_F8_F8_F0_C0_00_3F_3F_3F_1F_1F_0F_03_00_FC_C0_FE_E0_7F_80_F0_00),
        .INIT_20(256'h98_68_F0_E0_C0_00_01_02_1F_1F_0E_05_03_00_80_40_C0_C0_E0_F0_F8_3C_06_03_07_2F_07_13_00_00_00_00),
        .INIT_21(256'h10_30_E0_C0_00_00_00_00_0C_0F_07_03_10_08_00_00_17_37_37_17_17_F5_F6_F4_E8_E8_E8_E8_E8_AF_61_2F),
        .INIT_22(256'h00_FC_7E_1E_0C_01_05_05_3C_7E_E7_DB_DB_E7_7E_3C_38_7C_FE_FE_FE_FE_7C_38_BB_7E_26_A2_7A_1A_07_07),
        .INIT_23(256'h7E_FF_FF_FF_FF_FF_FF_7E_00_00_C0_30_98_E8_FC_FC_00_00_03_0E_1F_1F_3F_3F_00_70_F0_70_A0_40_F8_80),
        .INIT_24(256'h02_01_00_C0_E0_F0_68_98_40_80_00_03_05_0E_1F_1F_00_00_00_00_C0_E0_F0_E0_C0_70_3C_1F_0F_07_03_01),
        .INIT_25(256'hF8_FE_00_00_C0_E0_30_10_1F_7F_00_00_03_07_0F_0C_00_24_24_24_00_F4_F6_17_00_24_24_24_00_2F_6F_E8),
        .INIT_26(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_74_48_61_F5_B6_60_F8_84_1A_7C_BB_9F_4F_02_79_15),
        .INIT_27(256'hE0_58_AC_58_F0_20_00_00_07_1D_2A_55_6B_D4_A8_D9_00_00_00_00_00_00_00_00_A8_D8_AC_58_70_20_00_00),
        .INIT_28(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_C0_C0_00_00_00),
        .INIT_29(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2A(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2B(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2C(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2E(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_30(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_31(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_32(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_33(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_34(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_35(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_36(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_37(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_38(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_39(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3A(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3B(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3C(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3E(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00))
     aRAM (
        .DOB(adout),              // Port B 8-bit Data Output
        .ADDRA(aaddra),           // Port A 11-bit Address Input
        .ADDRB(aaddrb),           // Port B 11-bit Address Input
        .CLKA(clk),               // Port A Clock
        .CLKB(clk),               // Port B Clock
        .DIA(adin),               // Port A 8-bit Data Input
        .DIPA(1'b0),              // 1-bit Parity
        .ENA(1'b1),               // Port A RAM Enable Input
        .ENB(1'b1),               // Port B RAM Enable Input
        .SSRA(1'b0),              // Port A Synchronous Set/Reset Input
        .SSRB(1'b0),              // Port B Synchronous Set/Reset Input
        .WEA(awe),                // Port A Write Enable Input
        .WEB(1'b0)                // Port B Write Enable Input    
     );
 
     wire bwe;
     wire [10:0]baddra;
     wire [7:0]bdin;
     wire [10:0]baddrb;
     wire [7:0]bdout;
 
     assign bwe = (id >= 16'h9800 && id <= 16'h9FFF) ? write : 1'b0;
     assign baddra = id - 16'h9800;
     assign bdin = data;
 
     RAMB16_S9_S9 #(
        .INIT_00(256'hF8_70_00_00_10_20_00_00_00_20_31_32_19_00_00_00_C0_00_00_20_40_00_00_00_41_62_64_32_00_00_00_00),
        .INIT_01(256'h00_70_58_D8_EA_E2_F1_F0_E0_00_00_00_20_40_00_00_01_40_62_64_32_00_00_00_3C_42_A1_95_8D_9D_42_3C),
        .INIT_02(256'h00_60_09_8E_0A_04_01_00_0E_80_D0_F0_70_20_00_00_70_01_0B_0F_0E_04_01_00_00_00_00_00_00_00_00_00),
        .INIT_03(256'h10_30_60_60_40_00_00_00_C0_84_8C_4C_98_00_00_00_0F_07_00_00_08_04_00_00_04_00_50_F0_30_20_00_04),
        .INIT_04(256'hE0_E0_E0_C2_C3_C7_FC_FE_00_03_37_73_F1_F1_94_61_20_30_30_60_F8_F0_E0_E0_3A_54_54_32_03_0B_07_03),
        .INIT_05(256'h00_00_00_00_7C_FC_F8_78_E0_E0_F0_F8_FC_F0_EC_F8_03_43_6D_7E_2F_07_0B_07_91_00_00_18_00_24_00_18),
        .INIT_06(256'h01_08_40_00_60_64_D8_08_E7_F3_90_0A_86_4E_5F_3F_3D_FB_09_50_64_72_FA_FC_08_10_24_15_1A_06_00_00),
        .INIT_07(256'h00_00_00_00_00_08_08_10_80_F0_20_00_63_CF_FF_EF_07_07_0F_0F_1F_1D_1F_1F_00_80_08_00_06_48_03_10),
        .INIT_08(256'h2C_70_60_E0_E0_F0_F0_F0_02_0C_00_0C_38_77_6F_1F_40_E0_E0_E0_F0_F0_F0_E0_00_00_00_00_00_00_01_01),
        .INIT_09(256'h00_00_00_40_40_20_00_00_0C_36_36_77_E0_F0_F0_F0_00_0E_0E_07_07_03_01_01_00_00_00_00_10_91_F7_B5),
        .INIT_0A(256'h00_00_08_10_00_00_08_20_08_30_30_30_70_60_E0_E1_10_0C_0C_0C_0E_12_29_5F_00_00_00_26_26_00_00_3F),
        .INIT_0B(256'h00_00_00_00_00_00_00_00_70_30_20_70_F0_E0_C0_80_06_07_07_07_07_0F_0F_0F_00_00_10_06_00_00_00_00),
        .INIT_0C(256'h00_00_00_00_01_00_0E_0E_00_00_00_00_00_00_00_00_04_08_10_06_0E_3C_7C_F0_00_00_10_28_04_28_10_00),
        .INIT_0D(256'h00_00_00_24_14_18_00_00_00_00_00_00_00_00_00_00_00_01_06_00_03_07_0E_0C_00_00_00_00_00_C0_00_00),
        .INIT_0E(256'h00_02_02_04_01_03_07_06_00_00_00_66_66_00_00_00_00_00_08_70_10_38_38_38_00_00_00_66_66_00_00_FF),
        .INIT_0F(256'h01_00_25_21_20_11_00_00_E0_00_24_80_00_40_00_00_03_93_17_EE_50_4A_00_40_00_02_0C_00_04_3C_78_30),
        .INIT_10(256'hC4_DA_BA_7C_F0_E0_D0_E0_07_07_07_07_1F_3F_3F_1F_98_04_3C_88_60_D0_E0_C0_07_0F_0F_07_1C_0F_07_07),
        .INIT_11(256'h03_02_02_01_F1_E9_C5_83_00_00_00_00_07_0F_0F_07_00_C0_F8_3C_FC_F8_80_80_07_07_1F_7E_FF_FF_27_7F),
        .INIT_12(256'h00_00_00_00_E0_F0_F0_E0_C0_E0_E0_C0_DC_FF_FF_F3_07_07_0F_1F_1F_1F_1F_0F_00_00_18_3C_DC_F0_FC_F0),
        .INIT_13(256'h00_11_1F_17_11_11_00_00_30_25_52_38_91_68_C8_E0_00_08_04_08_1C_38_38_38_00_00_18_3C_3C_18_00_00),
        .INIT_14(256'hF8_F0_E0_00_00_00_00_00_27_0F_0B_00_10_08_00_00_BC_38_F8_F0_C0_00_00_00_0F_07_03_01_03_00_00_00),
        .INIT_15(256'h00_1A_04_16_14_0A_19_00_40_20_00_00_00_00_00_00_7E_FF_FF_FF_FF_FF_FE_F8_1F_9E_5F_1F_0F_07_03_00),
        .INIT_16(256'h00_00_00_00_00_00_00_00_00_0E_06_0E_1A_30_20_00_00_17_14_54_57_B4_17_00_00_49_49_49_49_49_E9_00),
        .INIT_17(256'hE0_40_C0_00_F0_C0_40_E0_01_00_10_44_45_10_00_01_00_00_00_00_00_00_00_00_24_42_99_3C_3C_99_42_24),
        .INIT_18(256'hFE_FE_FE_FE_FC_7C_FC_F8_1F_0B_07_1B_3D_7E_7F_6F_00_90_78_F8_FC_FC_7C_FC_00_0B_1F_07_23_36_1E_0F),
        .INIT_19(256'h3C_7E_C3_DF_DF_DF_7E_3C_00_00_00_00_00_00_00_80_00_00_80_C8_9C_AE_BE_FE_00_00_0D_07_03_07_07_1F),
        .INIT_1A(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_80_00_00_78_78_78_78_78_30_00_00_00_00_00_00_00_20_10_00),
        .INIT_1B(256'h00_FE_FE_FE_FE_FE_FE_FE_00_FE_82_82_82_82_82_FE_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_1C(256'h20_40_80_00_D8_FC_FE_FE_00_00_00_00_01_07_1F_3F_00_20_00_0C_0C_00_20_00_00_20_00_00_00_00_20_00),
        .INIT_1D(256'h07_07_0F_0F_0F_1F_1F_1F_00_FE_C0_C0_FC_C0_C0_FE_40_30_50_22_38_1E_04_00_19_04_16_05_0A_00_00_00),
        .INIT_1E(256'h01_01_01_00_00_00_00_00_C0_C0_C0_A0_00_80_E0_E0_1F_0F_2F_27_03_00_01_01_80_C0_C0_C0_80_80_80_80),
        .INIT_1F(256'h00_C6_CE_DE_FE_F6_E6_C6_FC_FC_FC_F8_F8_70_C0_00_2F_2F_33_11_19_0E_03_00_FC_E0_FE_F0_7F_00_00_00),
        .INIT_20(256'h00_00_08_04_02_11_09_06_08_0C_14_21_44_88_90_60_9C_9C_C8_E0_30_C8_04_02_7B_77_3B_3C_1F_07_00_00),
        .INIT_21(256'hC2_02_02_02_02_04_04_F8_40_40_42_40_50_28_20_1F_E7_07_C7_07_E7_07_06_04_E7_E4_E7_E4_E7_E0_6E_20),
        .INIT_22(256'hFC_02_00_00_00_01_01_01_00_00_00_18_18_00_00_00_38_7C_FE_FE_FE_BE_5C_38_00_00_00_00_08_00_00_00),
        .INIT_23(256'h24_66_E7_18_18_E7_66_24_00_00_C0_30_98_E8_FC_FC_00_00_03_0E_1F_1F_3F_3F_F0_80_00_00_80_40_F8_C0),
        .INIT_24(256'h06_09_11_22_04_08_00_00_60_90_88_44_20_00_00_00_00_C0_F0_38_18_CC_E4_C4_40_23_10_2C_37_7B_7D_7F),
        .INIT_25(256'hF8_FE_82_02_02_02_02_C2_1F_7F_41_40_40_42_40_40_FE_00_24_24_00_04_06_07_7F_00_24_24_00_20_60_E0),
        .INIT_26(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_80_00_00_00_00_00_20_00_08_02_00_00),
        .INIT_27(256'h40_08_04_08_50_20_80_C0_05_08_00_00_41_80_01_8A_C0_80_00_00_00_00_00_00_03_89_04_08_50_20_00_00),
        .INIT_28(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_C0_C0_00_00_00),
        .INIT_29(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2A(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2B(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2C(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2E(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_2F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_30(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_31(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_32(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_33(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_34(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_35(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_36(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_37(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_38(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_39(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3A(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3B(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3C(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3E(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
        .INIT_3F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00))
    bRAM (
        .DOB(bdout),              // Port B 8-bit Data Output
        .ADDRA(baddra),           // Port A 11-bit Address Input
        .ADDRB(baddrb),           // Port B 11-bit Address Input
        .CLKA(clk),               // Port A Clock
        .CLKB(clk),               // Port B Clock
        .DIA(bdin),               // Port A 8-bit Data Input
          .DIPA(1'b0),            // 1-bit Parity
        .ENA(1'b1),               // Port A RAM Enable Input
        .ENB(1'b1),               // Port B RAM Enable Input
        .SSRA(1'b0),              // Port A Synchronous Set/Reset Input
        .SSRB(1'b0),              // Port B Synchronous Set/Reset Input
        .WEA(bwe),                // Port A Write Enable Input
        .WEB(1'b0)                // Port B Write Enable Input    
    );    
 
//////////////////////////////////////////Display Buffer///////////////////////////////////////////    
    assign nxt256pix  = next256pixel[9:1];
    assign cur256line =    currline ? ((currline + 1'b1) / 2) : 8'h00;
     assign nxt256line = (vcount > 31 && vcount < 512) ? cur256line + 1'b1 : 8'h00;
 
     //No color out if not in drawing area.
     assign lbrstb = (cur256line && nxt256pix) ? 1'b0 : 1'b1;
 
     //Select between odd line buffer and even line buffer
     assign lbaddrb[8] = (cur256line % 2 == 1) ? 1'b0 : 1'b1;
     assign lbaddrb[7:0] = nxt256pix - 1'b1;
 
 
//////////////////////////////////////////Buffer Fill FSM//////////////////////////////////////////    
    wire leavewait;
    wire [1:0]bgatbits;
    wire bgptabit;
    wire bgptbbit;
    reg  [4:0]State = 3'b000;
    reg  [4:0]NextState = 3'b000;
    reg  [8:0]pix256draw = 9'h000;
 
    //Sprite registers and wires.
    wire spriteinrange;
    wire [7:0]spritex;
    wire [7:0]spritey;
    wire [7:0]spriteptrn;
    wire [1:0]upal;
    wire hmirror;
    wire vmirror;
    wire back;
    wire [2:0]invert;
    wire [2:0]normal;
    wire [10:0]address;
    reg  spbita = 1'b0;
    reg  spbitb = 1'b0;    
    reg  [7:0]bfaddr = 8'h00;
    reg  bs = 1'b0;
    reg  [7:0]pix = 8'h00;
 
    always @(State, leavewait, pix256draw, currsprite, spriteinrange, back) begin
        case(State)
            WAIT : NextState = leavewait ? NTAT : WAIT;
            NTAT : NextState = PTAB;
            PTAB : NextState = BUFF;
            BUFF : NextState = (pix256draw && (pix256draw < 256)) ? NTAT : NEXT;
            NEXT : NextState = SPRAM;
            SPRAM: NextState = spriteinrange ? SAB :
                               (currsprite == 256 && !spriteinrange) ? WAIT :
                                NEXT;
            SAB  : NextState = back ? WRIT0 : BUFF0;
            WRIT0: NextState = WRIT1;
            WRIT1: NextState = WRIT2;
            WRIT2: NextState = WRIT3;
            WRIT3: NextState = WRIT4;
            WRIT4: NextState = WRIT5;
            WRIT5: NextState = WRIT6;
            WRIT6: NextState = WRIT7;
            WRIT7: NextState = BUFF0;
            BUFF0: NextState = BUFF1;                
            BUFF1: NextState = BUFF2;                
            BUFF2: NextState = BUFF3;                
            BUFF3: NextState = BUFF4;                
            BUFF4: NextState = BUFF5;                
            BUFF5: NextState = BUFF6;                
            BUFF6: NextState = BUFF7;                
            BUFF7: NextState = (currsprite == 256) ? WAIT : NEXT;
            default : NextState = WAIT;
        endcase
    end
 
     always @(posedge clk) begin
        if(!nxt256line)
              State <= WAIT;
          else
              State <= NextState;
 
         if(NextState == WAIT) begin
            lbwe = 1'b0;          
              pix256draw <= 9'h000;
            currsprite = 9'h000;
            bfaddr = 8'h00;
            bs <= 1'b0;                
          end
 
         if(NextState == NTAT) begin    
            lbwe = 1'b0;          
                pix256draw <= pix256draw + 1;                
          end
 
        if(NextState == PTAB) begin
              lbwe = 1'b0;
        end
 
          if(NextState == BUFF) begin
              lbwe = 1'b1;
        end
 
          if(NextState == NEXT) begin
              lbwe = 1'b0;
                pix <= 8'h00;
                pix256draw <= 9'h000;
                currsprite = currsprite + 1;
                bfaddr = 8'h00;
                bs <= 1'b1;
          end
 
          if(NextState == SAB) begin
              bfaddr = hmirror ? spritex + 7 : spritex;
          end
 
        if(NextState == WRIT0) begin
            bfaddr = hmirror ? spritex + 6 : spritex + 1;                
        end
 
        if(NextState == WRIT1) begin
            bfaddr = hmirror ? spritex + 5 : spritex + 2;
                if(lbcheck)
                    pix[0] <= 1'b1;
        end
 
        if(NextState == WRIT2) begin
            bfaddr = hmirror ? spritex + 4 : spritex + 3;
                if(lbcheck)
                    pix[1] <= 1'b1;
        end
 
        if(NextState == WRIT3) begin
            bfaddr = hmirror ? spritex + 3 : spritex + 4;
                if(lbcheck)
                    pix[2] <= 1'b1;
        end
 
        if(NextState == WRIT4) begin
            bfaddr = hmirror ? spritex + 2 : spritex + 5;
                if(lbcheck)
                    pix[3] <= 1'b1;
        end
 
        if(NextState == WRIT5) begin
            bfaddr = hmirror ? spritex + 1 : spritex + 6;
                if(lbcheck)
                    pix[4] <= 1'b1;
        end
 
        if(NextState == WRIT6) begin
            bfaddr = hmirror ? spritex     : spritex + 7;
                if(lbcheck)
                    pix[5] <= 1'b1;
        end
 
        if(NextState == WRIT7) begin              
                if(lbcheck)
                    pix[6] <= 1'b1;
        end          
 
          if(NextState == BUFF0) begin
              if((!adout[7] && !bdout[7]) || (back && pix[0]))
                    lbwe = 1'b0;
                else
                  lbwe = 1'b1;
                if(lbcheck)
                    pix[7] <= 1'b1;
                bfaddr = hmirror ? spritex + 7 : spritex;
            spbita = adout[7];
                spbitb = bdout[7];                
          end
 
          if(NextState == BUFF1) begin
              if((!adout[6] && !bdout[6]) || (back && pix[1]))
                    lbwe = 1'b0;
                else
                  lbwe = 1'b1;
                bfaddr = hmirror ? spritex + 6 : spritex + 1;
                spbita = adout[6];
                spbitb = bdout[6];
          end
 
          if(NextState == BUFF2) begin
              if((!adout[5] && !bdout[5]) || (back && pix[2]))
                    lbwe = 1'b0;
                else
                  lbwe = 1'b1;
                bfaddr = hmirror ? spritex + 5 : spritex + 2;
                spbita = adout[5];
                spbitb = bdout[5];
          end
 
          if(NextState == BUFF3) begin
              if((!adout[4] && !bdout[4]) || (back && pix[3]))
                    lbwe = 1'b0;
                else
                  lbwe = 1'b1;
                bfaddr = hmirror ? spritex + 4 : spritex + 3;
                spbita = adout[4];
                spbitb = bdout[4];
          end          
 
          if(NextState == BUFF4) begin
              if((!adout[3] && !bdout[3]) || (back && pix[4]))
                    lbwe = 1'b0;
                else
                  lbwe = 1'b1;
                bfaddr = hmirror ? spritex + 3 : spritex + 4;
                spbita = adout[3];
                spbitb = bdout[3];
          end
 
          if(NextState == BUFF5) begin
              if((!adout[2] && !bdout[2]) || (back && pix[5]))
                    lbwe = 1'b0;
                else
                  lbwe = 1'b1;
                bfaddr = hmirror ? spritex + 2 : spritex + 5;
                spbita = adout[2];
                spbitb = bdout[2];
          end
 
          if(NextState == BUFF6) begin
              if((!adout[1] && !bdout[1]) || (back && pix[6]))
                    lbwe = 1'b0;
                else
                  lbwe = 1'b1;
                bfaddr = hmirror ? spritex + 1 : spritex + 6;
               spbita = adout[1];
                spbitb = bdout[1];
          end
 
          if(NextState == BUFF7) begin
              if((!adout[0] && !bdout[0]) || (back && pix[7]))
                    lbwe = 1'b0;
                else
                  lbwe = 1'b1;
                bfaddr = hmirror ? spritex     : spritex + 7;
                spbita = adout[0];
                spbitb = bdout[0];
          end
     end
 
     //Determine when it is time to go from WAIT to NTAT.
     assign leavewait = (nxt256line && (vcount % 2 == 1'b0) && hcount < 10'h002) ? 1'b1 : 1'b0;
     //Name table address.
     assign ntaddra   = nxt256line ? (32 * ((nxt256line - 1) / 8) + ((pix256draw - 1) / 8)) : 10'h000;
     //Attribute table address.
     assign bgataddra = nxt256line ? (8  * ((nxt256line - 1) / 8) + ((pix256draw - 1) / 32)) : 10'h000;
     //Pattern table addresses.
     assign bgptaaddra = pix256draw ? (8 * ntdout + (nxt256line - 1) % 8) :10'h000;
     assign bgptbaddra = pix256draw ? (8 * ntdout + (nxt256line - 1) % 8) :10'h000;
     //Attribute table bits for palette MUX.
     assign bgatbits = (ntaddra % 4 == 2'b00) ? bgatdout[7:6] :
                       (ntaddra % 4 == 2'b01) ? bgatdout[5:4] :
                       (ntaddra % 4 == 2'b10) ? bgatdout[3:2] :
                        bgatdout[1:0];
     //Pattern table B bit for palette MUX.                        
     assign bgptbbit = bgptbdout[~(pix256draw - 1) % 8];
     //Pattern table A bit for palette MUX.
     assign bgptabit = bgptadout[~(pix256draw - 1) % 8];
    //Break down the sprite data into its separate parts.    
     assign spritex       = spdout[31:24];
     assign spritey       = spdout[7:0];
     assign spriteptrn    = spdout[15:8];
     assign spriteinrange = (currsprite && (nxt256line - 1'b1 >= spritey) &&
                             nxt256line - 1'b1 - spritey < 8) ? 1'b1 : 1'b0;
     assign upal          = spdout[17:16];
     assign hmirror       = spdout[22];
     assign vmirror       = spdout[23];
     assign back          = spdout[21];
    //Get sprite graphic info with or without vertical mirroring.
     assign invert  = ~(nxt256line - 1'b1 - spritey);
     assign normal  = (nxt256line - 1'b1 - spritey);
     assign address = spriteptrn * 8;    
     assign aaddrb  = address + (vmirror ? invert : normal);
     assign baddrb  = aaddrb;    
     //Palette MUX
     assign lbdin = ({bs, bgatbits, bgptbbit, bgptabit} == 5'h00) ? bgpal0  :
                    ({bs, bgatbits, bgptbbit, bgptabit} == 5'h01) ? bgpal1  :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h02) ? bgpal2  :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h03) ? bgpal3  :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h04) ? bgpal4  :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h05) ? bgpal5  :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h06) ? bgpal6  :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h07) ? bgpal7  :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h08) ? bgpal8  :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h09) ? bgpal9  :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h0A) ? bgpal10 :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h0B) ? bgpal11 :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h0C) ? bgpal12 :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h0D) ? bgpal13 :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h0E) ? bgpal14 :
                         ({bs, bgatbits, bgptbbit, bgptabit} == 5'h0F) ? bgpal15 :
                   ({bs, upal    , spbitb  , spbita  } == 5'h10) ? sppal0  :
                         ({bs, upal    , spbitb  , spbita  } == 5'h11) ? sppal1  :
                         ({bs, upal    , spbitb  , spbita  } == 5'h12) ? sppal2  :
                         ({bs, upal    , spbitb  , spbita  } == 5'h13) ? sppal3  :
                         ({bs, upal    , spbitb  , spbita  } == 5'h14) ? sppal4  :
                         ({bs, upal    , spbitb  , spbita  } == 5'h15) ? sppal5  :
                         ({bs, upal    , spbitb  , spbita  } == 5'h16) ? sppal6  :
                         ({bs, upal    , spbitb  , spbita  } == 5'h17) ? sppal7  :
                         ({bs, upal    , spbitb  , spbita  } == 5'h18) ? sppal8  :
                         ({bs, upal    , spbitb  , spbita  } == 5'h19) ? sppal9  :
                         ({bs, upal    , spbitb  , spbita  } == 5'h1A) ? sppal10 :
                         ({bs, upal    , spbitb  , spbita  } == 5'h1B) ? sppal11 :
                         ({bs, upal    , spbitb  , spbita  } == 5'h1C) ? sppal12 :
                         ({bs, upal    , spbitb  , spbita  } == 5'h1D) ? sppal13 :
                         ({bs, upal    , spbitb  , spbita  } == 5'h1E) ? sppal14 :
                         sppal15;
 
     //Write to odd or even line buffer.
     assign lbaddra[8] = ~lbaddrb[8];
     //Line buffer address.
     assign lbaddra[7:0] = bs ? bfaddr : pix256draw - 1'b1;
     //Determine final pixel color.
     assign colorout = (hcount < 112 || hcount > 623 || !currline) ? 8'h00 :
                       !lbdout ? basecolor :                    
                       lbdout;
 
////////////////////////////////////////////Base Timing////////////////////////////////////////////
    always @(posedge clk25MHz) begin
         //Horizontal timing.
         hcount <= hcount + 1'b1;
          if(hcount == 704)
              hsync  <= 1'b0;
          if(hcount == 800) begin
              hcount <= 10'h001;
                hsync  <= 1'b1;
                vcount <= vcount + 1'b1;
          end
 
          //Vertical timing.
          if(vcount == 523)
              vsync  <= 1'b0;
          if(vcount == 525) begin
              vcount <= 10'h001;
                vsync  <= 1'b1;
          end
 
          //Visible pixel counters.
          if(hcount >= 47 && hcount <= 686)
              nextpixel  <= nextpixel  + 1;
          else
              nextpixel <= 0;
          if(hcount >= 46 && hcount <= 685)
              nextpixel2 <= nextpixel2 + 1;
          else
               nextpixel2 <= 0;
 
          //Visible line counters.
          if(vcount >= 33 && hcount == 800)
              currline <= currline + 1;
          if(vcount >= 513 && hcount == 800)
            currline <= 0;      
 
        //256 resolution pixel counter.
        if(hcount >= 109 && hcount <= 621)
            next256pixel <= next256pixel + 1;
        else
            next256pixel <= 1'b0;
 
        //Vertical blank.
          if(vcount == 514)
              vblank <= 1'b1;
          else
              vblank <= 1'b0;
 
        //Draw linebuffer data to screen.
        vga <= colorout;                
     end
 
endmodule


uart.v
`timescale 1ns / 1ps
 
module uart(
           input clk,
           input reset,
           input [15:0] id,
           input [15:0] din,
           input write,
           input rx,
           output reg tx = 1'b1,
           output [7:0]dout,
           output reg [11:0]rxcount = 12'h000,
           output reg [11:0]txcount = 12'h000
           );
 
    parameter initbaud    = 16'd5244; //Default 9600 baud.
 
    parameter setBaud     = 16'h0200;
    parameter txStoreByte = 16'h0201;
    parameter txFlush     = 16'h0202;
    parameter txPurge     = 16'h0203;
    parameter rxNextByte  = 16'h0204;
    parameter rxPurge     = 16'h0205;
 
    parameter TXREADY     = 4'h0;
    parameter TXSYNC      = 4'h1;
    parameter TXSTART     = 4'h2;
    parameter TXB0        = 4'h3;
    parameter TXB1        = 4'h4;
    parameter TXB2        = 4'h5;
    parameter TXB3        = 4'h6;
    parameter TXB4        = 4'h7;
    parameter TXB5        = 4'h8;
    parameter TXB6        = 4'h9;
    parameter TXB7        = 4'hA;
    parameter TXSTOP      = 4'hB;
 
    parameter RXREADY     = 4'h0;
    parameter RXSTART     = 4'h1;
    parameter RXB0        = 4'h2;
    parameter RXB1        = 4'h3;
    parameter RXB2        = 4'h4;
    parameter RXB3        = 4'h5;
    parameter RXB4        = 4'h6;
    parameter RXB5        = 4'h7;
    parameter RXB6        = 4'h8;
    parameter RXB7        = 4'h9;
    parameter RXSTOP      = 4'hA;
    parameter RXSTORE     = 4'hB;
 
    reg [3:0]txstate      = TXREADY;
    reg [3:0]txnextstate  = TXREADY;
 
    reg [3:0]rxstate      = RXREADY;
    reg [3:0]rxnextstate  = RXREADY;
 
    //baudreg calculation is as follows:
    //Clock frequency / desired baud rate / 2.
    reg [15:0]txbaudreg  = initbaud;
    reg [17:0]txcountreg = 18'h00000; //Counts system clock cycles to generate baud clock.
    reg baudclock        = 1'b0;      //Used to time data out.
 
    reg [15:0]rxbaudcntr = 16'h0000;
 
    reg [10:0]txstartreg = 11'h000;
    reg [10:0]txendreg   = 11'h000; //Tx buffer regs.
 
    reg [10:0]rxstartreg = 11'h000;
    reg [10:0]rxendreg   = 11'h000; //Rx buffer regs.
 
    reg baudthis         = 1'b0;
    reg baudlast         = 1'b0;
    reg baudpostrans     = 1'b0;
 
    reg rxthis           = 1'b0;
    reg rxlast           = 1'b0;
    reg rxnegtrans       = 1'b0;
 
    reg nbwait           = 1'b0; //Wait while user retrieves received byte.
 
    reg [7:0]txreg = 8'h00;
    reg [7:0]rxreg = 8'h00;
 
    wire txwe;
    wire rxwe;    
 
    wire [7:0]txdout;
 
    RAMB16_S9_S9 #(
      .INIT_A(9'h000),              // Value of output RAM registers on Port A at startup
      .INIT_B(9'h000),              // Value of output RAM registers on Port B at startup
      .SRVAL_A(9'h000),             // Port A output value upon SSR assertion
      .SRVAL_B(9'h000),             // Port B output value upon SSR assertion
      .WRITE_MODE_A("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE
      .WRITE_MODE_B("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE
      .SIM_COLLISION_CHECK("ALL"))  // "NONE", "WARNING_ONLY", "GENERATE_X_ONLY", "ALL"
    TXRAM (
      .DOA(txdout),                 // Port A 8-bit Data Output
      .DOB(),                       // Port B 16-bit Data Output
      .ADDRA(txstartreg),           // Port A 11-bit Address Input
      .ADDRB(txendreg),             // Port B 11-bit Address Input
      .CLKA(clk),                   // Port A Clock
      .CLKB(clk),                   // Port B Clock
      .DIA(),                       // Port A 8-bit Data Input
      .DIB(din[7:0]),               // Port-B 8-bit Data Input
      .DIPA(1'b0),                  // Port A 1-bit parity Input
      .DIPB(1'b0),                  // Port B 1-bit parity Input
      .ENA(1'b1),                   // Port A RAM Enable Input
      .ENB(1'b1),                   // Port B RAM Enable Input
      .SSRA(1'b0),                  // Port A Synchronous Set/Reset Input
      .SSRB(1'b0),                  // Port B Synchronous Set/Reset Input
      .WEA(1'b0),                   // Port A Write Enable Input
      .WEB(txwe)                    // Port B Write Enable Input
    );
 
     RAMB16_S9_S9 #(
      .INIT_A(9'h000),              // Value of output RAM registers on Port A at startup
      .INIT_B(9'h000),              // Value of output RAM registers on Port B at startup
      .SRVAL_A(9'h000),             // Port A output value upon SSR assertion
      .SRVAL_B(9'h000),             // Port B output value upon SSR assertion
      .WRITE_MODE_A("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE
      .WRITE_MODE_B("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE
      .SIM_COLLISION_CHECK("ALL"))  // "NONE", "WARNING_ONLY", "GENERATE_X_ONLY", "ALL"
    RXRAM (
      .DOA(),                       // Port A 8-bit Data Output
      .DOB(dout),                   // Port B 16-bit Data Output
      .ADDRA(rxendreg),             // Port A 11-bit Address Input
      .ADDRB(rxstartreg),           // Port B 11-bit Address Input
      .CLKA(clk),                   // Port A Clock
      .CLKB(clk),                   // Port B Clock
      .DIA(rxreg),                  // Port A 8-bit Data Input
      .DIB(),                       // Port-B 8-bit Data Input
      .DIPA(1'b0),                  // Port A 1-bit parity Input
      .DIPB(1'b0),                  // Port B 1-bit parity Input
      .ENA(1'b1),                   // Port A RAM Enable Input
      .ENB(1'b1),                   // Port B RAM Enable Input
      .SSRA(1'b0),                  // Port A Synchronous Set/Reset Input
      .SSRB(1'b0),                  // Port B Synchronous Set/Reset Input
      .WEA(rxwe),                   // Port A Write Enable Input
      .WEB(1'b0)                    // Port B Write Enable Input
    );
 
    assign txwe   = (write && id == txStoreByte) ? 1'b1 : 1'b0;    
    assign rxwe   = (rxstate == RXSTOP) ? 1'b1 : 1'b0;
 
    always @(posedge clk) begin
        txcountreg <= txcountreg + 1'b1;
        txstate    <= txnextstate;
        rxstate    <= rxnextstate;
 
        //Keep track of baud clock edges.
        baudthis <= baudclock;
        baudlast <= baudthis;
 
        //Keep track of rx edges
        rxthis   <= rx;
        rxlast   <= rxthis;
 
        //Keep track of rx negative edge.
        if(rxlast && !rxthis)
            rxnegtrans <= 1'b1;
        else
            rxnegtrans <= 1'b0;
 
        //Keep track of baud clock positive edge.
        if(!baudlast && baudthis)
            baudpostrans <= 1'b1;
        else
            baudpostrans <= 1'b0;
 
        //Reset all registers to defaults.
        if(reset) begin       
            txcountreg  <= 18'h00000;
            rxstartreg  <= 11'h000;             
            txstartreg  <= 11'h000;
            txbaudreg   <= initbaud;
            baudclock   <= 1'b0;                
            txendreg    <= 11'h000;                        
            rxendreg    <= 11'h000;
            txstate     <= TXREADY;
            rxstate     <= RXREADY;
            txcount     <= 10'h000;
            rxcount     <= 10'h000;
            txreg       <= 8'h00;
            rxreg       <= 8'h00;        
            tx          <= 1'b1;                
        end
 
        if(txstate == TXREADY || txstate == TXSYNC)
            tx <= 1'b1;    
 
        if(txcountreg == txbaudreg) begin
            baudclock  <= ~baudclock;
            txcountreg <= 18'h00000;
        end
 
        if(id == setBaud && write)
            txbaudreg <= din;
 
        if(id == txStoreByte && write) begin
            txendreg <= txendreg + 1;
            if(txcount < 2048) //Still room in buffer.
                txcount <= txcount + 1;
            else //No room in buffer.  Overwrite oldest byte.
                txstartreg <= txstartreg + 1;                
        end
 
        if(nbwait) begin
            rxstartreg <= rxstartreg + 1;
            rxcount    <= rxcount - 1;
            nbwait     <= nbwait + 1;
        end
 
        if(id == rxNextByte && write && rxcount) begin
            nbwait <= 1'b1;                
        end
 
        if(id == txPurge && write) begin
            txendreg   <= 0;
            txstartreg <= 0;
            txcount    <= 0;
        end
 
        if(id == rxPurge && write) begin
            rxendreg   <= 0;
            rxstartreg <= 0;
            rxcount    <= 0;
        end
 
        if(txstate == TXSTART) begin
            txreg <= txdout;
            tx <= 1'b0;
        end
 
        if(txstate == TXB0)
            tx <= txreg[0];
 
        if(txstate == TXB1)
            tx <= txreg[1];
 
        if(txstate == TXB2)
            tx <= txreg[2];
 
        if(txstate == TXB3)
            tx <= txreg[3];
 
        if(txstate == TXB4)
            tx <= txreg[4];
 
        if(txstate == TXB5)
            tx <= txreg[5];
 
        if(txstate == TXB6)
            tx <= txreg[6];
 
        if(txstate == TXB7)
            tx <= txreg[7];
 
        if(txstate == TXSTOP) begin
            tx <= 1'b1;        
        end
 
        if(txnextstate == TXSTOP && baudpostrans) begin
            txcount  <= txcount  - 1;
            txstartreg <= txstartreg + 1;
        end    
 
        if(rxbaudcntr)
            rxbaudcntr <= rxbaudcntr - 1;
 
        if(rxstate == RXREADY && rxnextstate == RXSTART)
            rxbaudcntr <= txbaudreg * 2 + txbaudreg;
 
        if(rxstate == RXSTART && rxnextstate == RXB0) begin
            rxreg[0]   <= rx;
            rxbaudcntr <= txbaudreg * 2;
        end
 
        if(rxstate == RXB0 && rxnextstate == RXB1) begin
            rxreg[1]   <= rx;
            rxbaudcntr <= txbaudreg * 2;
        end
 
        if(rxstate == RXB1 && rxnextstate == RXB2) begin
            rxreg[2]   <= rx;
            rxbaudcntr <= txbaudreg * 2;
        end
 
        if(rxstate == RXB2 && rxnextstate == RXB3) begin
            rxreg[3]   <= rx;
            rxbaudcntr <= txbaudreg * 2;
        end
 
        if(rxstate == RXB3 && rxnextstate == RXB4) begin
            rxreg[4]   <= rx;
            rxbaudcntr <= txbaudreg * 2;
        end
 
        if(rxstate == RXB4 && rxnextstate == RXB5) begin
            rxreg[5]   <= rx;
            rxbaudcntr <= txbaudreg * 2;
        end
 
        if(rxstate == RXB5 && rxnextstate == RXB6) begin
            rxreg[6]   <= rx;
            rxbaudcntr <= txbaudreg * 2;
        end
 
        if(rxstate == RXB6 && rxnextstate == RXB7) begin
            rxreg[7]   <= rx;
            rxbaudcntr <= txbaudreg * 2;
        end
 
        if(rxstate == RXSTOP && rxnextstate == RXSTORE) begin
            rxendreg <= rxendreg + 1;
            if(rxcount < 1024)
                rxcount  <= rxcount  + 1;
        end          
    end
 
    always @(*) begin //Transmit finite state machine.
        case(txstate)
            TXREADY : txnextstate = reset ? TXREADY :
                     (id == txFlush && write && txcount) ? TXSYNC :
                      TXREADY;
            TXSYNC  : txnextstate = baudpostrans ? TXSTART : TXSYNC;
            TXSTART : txnextstate = baudpostrans ? TXB0    : TXSTART;
            TXB0    : txnextstate = baudpostrans ? TXB1    : TXB0;
            TXB1    : txnextstate = baudpostrans ? TXB2    : TXB1;
            TXB2    : txnextstate = baudpostrans ? TXB3    : TXB2;
            TXB3    : txnextstate = baudpostrans ? TXB4    : TXB3;
            TXB4    : txnextstate = baudpostrans ? TXB5    : TXB4;
            TXB5    : txnextstate = baudpostrans ? TXB6    : TXB5;
            TXB6    : txnextstate = baudpostrans ? TXB7    : TXB6;
            TXB7    : txnextstate = baudpostrans ? TXSTOP  : TXB7;
            TXSTOP  : txnextstate = (baudpostrans && txcount) ? TXSTART :
                                     baudpostrans ? TXREADY :
                                     TXSTOP;
            default : txnextstate = TXREADY;
         endcase
    end
 
    always @(*) begin //Receive finite state machine.
        case(rxstate)
            RXREADY : rxnextstate = rxnegtrans ? RXSTART : RXREADY;
            RXSTART : rxnextstate = rxbaudcntr ? RXSTART : RXB0;
            RXB0    : rxnextstate = rxbaudcntr ? RXB0    : RXB1;
            RXB1    : rxnextstate = rxbaudcntr ? RXB1    : RXB2;
            RXB2    : rxnextstate = rxbaudcntr ? RXB2    : RXB3;
            RXB3    : rxnextstate = rxbaudcntr ? RXB3    : RXB4;
            RXB4    : rxnextstate = rxbaudcntr ? RXB4    : RXB5;
            RXB5    : rxnextstate = rxbaudcntr ? RXB5    : RXB6;
            RXB6    : rxnextstate = rxbaudcntr ? RXB6    : RXB7;
            RXB7    : rxnextstate = rxbaudcntr ? RXB7    : RXSTOP;
            RXSTOP  : rxnextstate = RXSTORE;
            RXSTORE : rxnextstate = RXREADY;
            default : rxnextstate = RXREADY;
        endcase    
    end
endmodule


ROMcontroller.v
`timescale 1ns / 1ps
 
module ROMcontroller(
    input [15:0]id,
    input [15:0]ain,
     input clk,
    output reg [10:0]aout = 11'h000
    );
 
     always @(posedge clk) begin
        if(id == 16'h0000)
              aout <= {3'b000, ain[7:0]};
        if(id == 16'h0001)
              aout <= {3'b001, ain[7:0]};
        if(id == 16'h0002)
              aout <= {3'b010, ain[7:0]};
        if(id == 16'h0003)
              aout <= {3'b011, ain[7:0]};
        if(id == 16'h0004)
              aout <= {3'b100, ain[7:0]};
        if(id == 16'h0005)
              aout <= {3'b101, ain[7:0]};
        if(id == 16'h0006)
              aout <= {3'b110, ain[7:0]};
        if(id == 16'h0007)
              aout <= {3'b111, ain[7:0]};
    end
endmodule


MControl.v
`timescale 1ns / 1ps
 
module MControl(
    input  clk,
    input  reset,
     input  serialdata,
     output nenable,
     output reg sclk = 1'b1,
    output reg [11:0]micdata = 12'h000
    );
 
     parameter WAIT    = 2'b00;
     parameter GETDATA = 2'b01;
     parameter PUTDATA = 2'b10;
     parameter QUIET   = 2'b11;
 
     reg [1:0]clockdivider = 2'b00;
     reg [1:0]state        = WAIT;
     reg [1:0]nextstate    = WAIT;
    reg [4:0]bitcounter   = 5'h00;
    reg [11:0]datahold    = 12'h000;
 
    nand nen(nenable, ~state[1], state[0]);    
 
     always @(posedge clk) begin
         if(!reset)
              clockdivider <= clockdivider + 1'b1;
          else begin
              clockdivider <= 2'b00;
                sclk <= 1'b0;
          end
 
          if(clockdivider == 2'b01)
              sclk <= 1'b1;
          if(clockdivider == 2'b11)
              sclk <= 1'b0;
     end
 
     always @(posedge sclk) begin
        if(reset)
              state       <= WAIT;
          else
              state       <= nextstate;
 
          if(nextstate == GETDATA) begin
                bitcounter  <= bitcounter + 1'b1;
                datahold    <= {datahold[10:0], serialdata};
          end
          if(nextstate == PUTDATA) begin
             datahold    <= {datahold[10:0], serialdata};
                bitcounter  <= 5'h00;
          end              
          if(nextstate == WAIT)
              micdata     <= datahold;
    end
 
     always @(state, reset, bitcounter) begin
         case(state)
              WAIT    : nextstate = (reset)               ? WAIT    : GETDATA;
            GETDATA : nextstate = (bitcounter == 5'h10) ? PUTDATA : GETDATA;
            PUTDATA : nextstate = WAIT;
            QUIET   : nextstate = WAIT;                
           endcase
     end
 
endmodule


ClockControl.v
`timescale 1ns / 1ps
 
//This module controls the timing of the clock and the time change
//functions.  It takes the 50 MHz system clock in as an input and the
//1 KHz clock enable.  It also takes the status of the buttons in so
//it can set the clock time.  The current time of the clock in BCD is
//provided on the output.
 
module ClockControl(
    input clock,
    input ce_1KHz,
    input [3:0]button,
     output [7:0]hour,
     output [7:0]min,
     output [7:0]sec,
     output blink
     );
 
     reg ce_1Hz         =  1'b0;
    reg [9:0]mscounter = 10'h000;    
     reg [3:0]seclo     =  4'h0;
    reg [3:0]sechi     =  4'h0;
    reg [3:0]minlo     =  4'h0;
    reg [3:0]minhi     =  4'h0;
    reg [3:0]hourlo    =  4'h1;
    reg [3:0]hourhi    =  4'h0;
 
     assign hour  = {hourhi, hourlo};
     assign min   = {minhi, minlo};
     assign sec   = {sechi, seclo};
     assign blink = mscounter[9];
 
    always @(posedge clock) begin
         //Reset 1 second clock enable pulse every clock cycle.
          ce_1Hz = 1'b0;
 
         if(ce_1KHz)
                mscounter = mscounter + 1;
 
          if(mscounter == 1000) begin
              mscounter = 0;
                ce_1Hz = 1'b1; //1 second clock enable pulse.
              seclo = seclo + 1;                
          end    
 
          if(seclo == 10) begin
              seclo = 0;
                sechi = sechi + 1;
          end
 
          if(sechi == 6) begin
               sechi = 0;
                minlo = minlo + 1;
          end
 
          if(minlo == 10) begin
               minlo = 0;
                minhi = minhi + 1;
          end
 
          if(minhi == 6) begin
               minhi = 0;
                hourlo = hourlo + 1;
          end
 
          if(hourlo == 10) begin
               hourlo = 0;
                hourhi = hourhi + 1;
          end
 
          if(hourhi == 1 && hourlo == 3) begin
                hourlo = 4'b0001;
                hourhi = 0;
          end
 
         //Button inputs used to set the clock time.
         //Increment the lower minute digit.
        if(button == 4'b0001 && ce_1Hz)
             minlo = minlo + 1;
 
         //Increment the upper minute digit.
         if(button == 4'b0010 && ce_1Hz)
             minhi = minhi + 1;
 
         //Increment the lower hour digit.
         if(button == 4'b0100 && ce_1Hz)
              hourlo = hourlo + 1;                    
    end
endmodule


dataMUX.v
`timescale 1ns / 1ps
 
module dataMUX(
    input  [15:0]xpos,
    input  [15:0]ypos,
    input  [15:0]i2cdata,
    input  [15:0]i2cstatus,
    input  read,
    input  blink,
    input  [15:0]id,
    input  [15:0]uartdata,
    input  [11:0]txcount,
    input  [11:0]rxcount,
    input  [7:0]romdata,
    input  [15:0]switches,
    input  [7:0]sec,
    input  [7:0]min,
    input  [7:0]hour,
    input  [15:0]micdata,
    output [15:0]dout
    );
 
    assign dout = (id == 16'h0001 && read) ? i2cdata                :
                  (id == 16'h0002 && read) ? i2cstatus              :
                  (id == 16'h0003 && read) ? uartdata               :
                  (id == 16'h0004 && read) ? {4'h0, txcount}        :
                  (id == 16'h0005 && read) ? {4'h0, rxcount}        :
                  (id == 16'h0006 && read) ? xpos                   :
                  (id == 16'h0007 && read) ? ypos                   :
                  (id == 16'h0012 && read) ? {8'h00, romdata}       :
                  (id == 16'h0013 && read) ? switches               :
                  (id == 16'h0030 && read) ? {8'h00, sec}           :
                  (id == 16'h0031 && read) ? {8'h00, min}           :
                  (id == 16'h0032 && read) ? {8'h00, hour}          :
                  (id == 16'h0033 && read) ? {15'h0000, blink}      :
                  (id == 16'h0034 && read) ? micdata                :                                         
                    16'h0000;
endmodule


div100k.v
`timescale 1ns / 1ps
 
module div100k(
    input clock,
      output reg ce1k = 1'b0
     );
 
    reg [17:0]counter = 18'h00000;
 
     always @(posedge clock) begin
          counter <= counter + 1;
          ce1k <= 0;
          if(counter == 18'd100681) begin
              counter <= 18'd0;  
              ce1k <= 1;
          end                                      
    end
 
endmodule


FF.v
`timescale 1ns / 1ps
 
//IRQ flipflop
module FF(input set, input reset, output reg sigout = 1'b0);
 
     always @(posedge set, posedge reset) begin
       if(reset)
          sigout <= 1'b0;
        else
          sigout <= 1'b1;        
     end
 
endmodule


ledio.v
`timescale 1ns / 1ps
 
module ledio(
    input clk,
    input reset,
    input write,
    input [15:0]id,
    input [15:0]din,
    output reg [7:0]ledsout = 8'h00
    );    
 
    always @(posedge clk)
         begin                    
              if(id == 16'h0020 && write)
                    ledsout <= din[7:0];
                if(reset)
                    ledsout <= 8'h00;                
          end
 
endmodule


LEDIO2.v
`timescale 1ns / 1ps
 
module LEDIO2(
    input clk,
    input reset,
    input write,
    input [15:0]id,
    input [15:0]din,
    output reg [7:0]ledsout = 8'h00
    );    
 
    always @(posedge clk) begin                    
        if(id == 16'h0021 && write) ledsout <= din[7:0];
        if(reset) ledsout <= 8'h00;                
    end
endmodule


seg7io.v
`timescale 1ns / 1ps
 
module seg7io(
    input clk,
     input ce1k,
     input write,
     input reset,
     input [15:0]id,
     input [15:0]din,
     output reg [3:0]segselect = 4'h0,
     output reg [7:0]segs = 8'h00
     );
 
    reg [7:0]seg0 = 8'h00;
    reg [7:0]seg1 = 8'h00;
    reg [7:0]seg2 = 8'h00;
    reg [7:0]seg3 = 8'h00;
 
    always @(posedge ce1k)
        begin
            //Constantly cycle through the enable pins.
            if(segselect == 4'b1110) begin
                segselect <= 4'b0111;
                segs <= ~seg0;
            end
            else if(segselect == 4'b0111) begin
                segselect <= 4'b1011;
                segs <= ~seg1;
            end
            else if(segselect == 4'b1011) begin
                segselect <= 4'b1101;
                segs <= ~seg2;
            end
            else begin
                segselect <= 4'b1110;
                segs <= ~seg3;
            end                    
        end
 
    always @(posedge clk)
        begin
              if(id == 16'h0024 && write)
                   seg0 <= din[7:0];
              if(id == 16'h0025 && write)
                   seg1 <= din[7:0];
                if(id == 16'h0026 && write)
                   seg2 <= din[7:0];
              if(id == 16'h0027 && write)
                   seg3 <= din[7:0];
 
                if(reset)
                    begin
                         seg0 <= 8'h00;
                         seg1 <= 8'h00;
                         seg2 <= 8'h00;
                         seg3 <= 8'h00;
                     end                                                
          end
 
endmodule


timer.v
`timescale 1ns / 1ps
 
module timer0(
    input clk,
    input cein,
     input write,
     input [15:0] id,
     input [15:0] din,
     input reset,
     output reg dout = 1'b0
     );
 
    reg [15:0] timerreg = 16'h0000;
 
    always @(posedge clk) begin
             dout <= 1'b0;
              //Load timer bits.
              if(id == 16'h0010 && write)
                    timerreg <= din;    
            //Decrement timer if not 0.
            if(cein && timerreg > 1'b1)            
                    timerreg <= timerreg - 1'b1;
                //One timer is about to expire, send output strobe.
                if(cein && timerreg == 1'b1) begin
                    timerreg <= timerreg - 1'b1;
                     dout <= 1'b1;
                end
                //Synchronous reset.   
            if(reset)
                timerreg <= 16'h0000;                    
          end
 
endmodule


timer1.v
`timescale 1ns / 1ps
 
module timer1(
    input clk,
    input cein,
     input write,
     input [15:0] id,
     input [15:0] din,
     input reset,
     output reg dout = 1'b0
     );
 
    reg [15:0] timerreg = 16'h0000;
 
    always @(posedge clk) begin
             dout <= 1'b0;
              //Load timer bits.
              if(id == 16'h0011 && write)
                    timerreg <= din;    
            //Decrement timer if not 0.
            if(cein && timerreg > 1'b1)            
                    timerreg <= timerreg - 1'b1;
                //One timer is about to expire, send output strobe.
                if(cein && timerreg == 1'b1) begin
                    timerreg <= timerreg - 1'b1;
                     dout <= 1'b1;
                end
                //Synchronous reset.   
            if(reset)
                timerreg <= 16'h0000;                    
          end
 
endmodule


lookupROM.coe
memory_initialization_radix = 16;
memory_initialization_vector =
 
; LEDTbl($ 000)
01,02,04,08,10204080402010,08,04,02,01,02,
04,08,10204080402010,08,04,02,01,02,04,08,10204080402010,08,04,02,01,02,04,08,10204080402010、08、04、02、01,FF,00,FF,00,FF,00,FF,
00,AA,55,AA,55,AA,55,AA,55 ,AA,55,AA,55,AA,
55、00、18、3C,7E,FF,00、18、3C,7E,FF,00、18、3C,7E,FF,
00、18、3C,7E ,FF,00、18、3C,7E,FF,00、18、3C,7E,FF
,00、00、00、00、00、00、00、00、00、00、00、00、00、00 ,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00 ,00、00、00、00、00、00、00、00、00、00、00、00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00, 00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00, 00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00, 00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
 
; TimeLoTbl($ 100505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050,FF,FF,FF,FF,FF,FF,
FF,FF,FF,A0,A0,A0,A0,A0,A0,A0,A0 ,A0,A0,A0,A0,A0,A0,A0,
A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,
A0,A0 ,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,A0,00,00,00,
00,00,00,00,00,00,00,00,00,00,00 ,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00 ,00、00、00、00、00、00、00、00、00、00、00、00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00, 00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00, 00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00, 00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
 
; Seg7IndexTbl($ 200)
1C,1E,1B,0E,10,05,05,1B,1E,22,1B,1A,1816,如图1A所示,10232323,00,01,02,03 ,
04,05,06,07,08,09,232323,1C,1E,1B,00,00,00,00,00,00,00,00,00,00,00,00,00 ,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00 ,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00 ,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00 ,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00 ,00、00、00、00、00、00、00、00、00、00、00、00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00, 00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00, 00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00, 00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
 
; Seg7Tbl($ 300)
3F,06,5B,4F,66,6D,7D,07,7F,6777,5F,图7C,3958,如图5E所示,
79,7B,71,6F,7674,04 ,1E,383754、5C,733150、3E,
1C,6E,00、80、00、00、00、00、00、00、00、00、00、00、00、00 ,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00 ,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00 ,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00 ,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00 ,00、00、00、00、00、00、00、00、00、00、00、00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00, 00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00, 00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00, 00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
 
; ClockTbl($ 400; 0
4C,4646,4D,5651504756414047,5C,5757,5D,;
1
FF,44,4D,FF,FF ,5047,FF,FF,FF,47,FF,FF,FF,55,FF,;
2
444646,4D,4E,61,4A,5948,5B,60,5F,5C ,575772;
3
444646,4D,6261,4A,596360,5A,49545757,5D,;
4
70646566676869,6A,6B,60,6C,6D,FF,FF,71,6E,;
5
73464645746161,4F,6360,5A,49545757、5D,;
6
4C,464645564261、4F,5652、5A,49、5C,5757、5D,;
7
444646 ,4D,FF,FF,5047,FF,FF,FF,47,FF,FF,FF,55;
8
4C,4646、4D,58、4B,4A,5948、5B,5A ,49、5C,5757、5D,
; 9
4C,4646、4D,58、4B,4347、5E,605347545757、5D 、
;空白
FF,FF,FF,FF,FF,FF,FF, FF,FF,FF,FF,FF,FF,FF,FF,FF,
 
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00, 00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00, 00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00, 00,00,00,00,00,
 
; MessageTbl($ 500;活动演示
-0A,0C,1D,12、1F,0E,FF,0D,0E,161817、1C,1D,1B,0A,
1D,1218、17C ,3F,
;($ 516;平时时钟
1D,1215,0E ,0D,FF,0C,1518,0C ,14;($ 521; SPRITE AUDIO
1C,19,1B ,121 ,D ,0E ,FF,0A,1E,0D,
1218;($ 52D)
;基色
0B,0A,1C,0E,FF,0C,181518,1B ,
;($ 537;弹跳
0B, 18,1E,17,0C,121710,FF,1C,19,1B,12,1D,0E,1C,
;($ 547;属性表
0A,1D,1D,1B,12,0B,1E ,1D,0E,FF,1D,0A,0B,15,0E,
;($ 556; SPRITE PRIORITY
1C,19,1B ,12,1D,0E,FF,19,1B,1218,1B,12, 1D,22;($ 565;调色板更改19,0A ,15,0E
,1D,1D,0E,FF,0C,11,0A ,1710,0E ,
;($ 573; SPRITE MIRRORING
1C,19,1B ,12, 1D,0E,FF,1612,1B,1B,18,1B,121710
;($ 583)
00,00,00,00,00,00,00,00,00,00,00,00 ,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00 ,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00 ,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00 ,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00 ,00、00、00、00、00、00、00、00、00、00、00、00、00,
 
; PaletteTbl($ 600)00、382018、00、3F,24、1B,00、52
,A4,FF,00、07、04、03、00、26、3F,02、00
,C4,C2 ,82、00、60,A0、20、00、0B,19、5D
,00、00、00、00、00、00、00、00、00、00、00、00、00、00、00、00 ,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
 
; SamusTbl($ 640)D0,00,D0,01,D8,10,D8,11,E0,20,E0,21
,E0,FF,E8,FF,
E8,31,E8,FF,FF,FF,FF ,FF,D0、02,D0、03,D8、12,D8、13,E0、22,E0、23,
E0,FF,E8、32,E8、33,E8、34,FF,FF,FF,FF ,
D0、00,D0、01,D8、10,D8、11,E0、20,
E0、21,E0,FF,E8,FF,E8、31,E8,FF,FF,FF,FF,FF,D0 ,05,D0、06,D8、15,D8、16,E0、25,
E0、26,E0、27,E8、35,E8、36,E8,FF,FF,FF,FF,FF,
 
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00, 00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00, 00,00,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00, 00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
 
; SpriteTbl($ 700)
C0,9C,01,28,C0,9D,01,30,C8,9E,01,28,C8,9F,01,30,
C0,9F,C1,78,C0,9E,C1 ,80,C8、9D,C1、78,C8、9C,
C1、80,C0、9C,01,C8,C0、9D,01,D0,C8、9E,01,C8,C8、9F,01,D0 ,
FF,9F,C1,C8,FF,9E,C1,D0,FF,9D,C1,C8,FF,9C,C1,D0,
C0、9E,8128,C0、9F,8130,C8 ,9C,8128,C8、9D,
8130,C0、9D,4178,C0、9C,4180,C8、9F,4178,C8、9E,
4180,C0、9E ,81,C8,C0、9F,81,D0,C8、9C,81,C8,C8、9D,81,D0,
FF,9D,41,C8,FF,9C,41,D0,FF,9F,41 ,C8,FF,9E,41,D0,
C0、9F,C1、28,C0、9E,C1、30,C8、9D,C1、28,
C8、9C,C1、30,C0、9C,01、78 ,C0、9D,01、80,C8、9E,01、78,C8、9F,01、80,
C0、9F,C1,C8,C0、9E,C1,D0,C8、9D,C1,C8,C8、9C,C1,D0,
FF,9C,01,C8,FF,9D,01,D0,FF, 9E,01,C8,FF,9F,01,D0,
C0、9D,4128,C0、9C,4130,C8、9F,4128,C8、9E,
4130,C0、9E, 8178,C0、9F,8180,C8、9C,8178,C8、9D,
8180,C0、9D,41,C8,C0、9C,41,D0,C8、9F,41, C8,C8、9E,41,D0,
FF,9E,81,C8,FF,9F,81,D0,FF,9C,81,C8,FF,9D,81,D0;


NMPSM3汇编程序

还为NMPSM3编写了汇编程序。它是一个基本的汇编器,但运行良好,已被用于在多个FPGA项目上为NMPSM3编写代码。

NMPSM3.java
package nmpsm3;
 
import java.io.RandomAccessFile;
import java.io.IOException;
import java.util.Vector;
 
//A simple class to store alias associations.
class AliasSet {
    AliasSet(String as, String rs) {
        aliasString = as;
        replacementString = rs;
    }
    public String aliasString;
    public String replacementString;
}
 
//A simple class to store address labels.
class Labels {
    Labels(String ln, int la, int lin) {
        labelName = ln;
        labelAddress = la;
        lineNumber = lin;
    }
    public String labelName;
    public int labelAddress;
    public int lineNumber;
}
 
//A simple class to store error events.
class Error{
    Error(String es, int el) {
        errorString = es;
        errorLine = el;
    }
    public String errorString;
    public int errorLine;
}
 
public class NMPSM3 {
 
    //Line number where error occurs.
    private int errorLine = 0;
    //Current address.
    private int currentAddress = 0;
    //Program size limit. Min. = 1, max = 65536, default = 512.
    private int sizeLimit = 512;
    //Input file.
    private RandomAccessFile read;
    //Output file.
    private RandomAccessFile write;
    //Output array. Size calculated later.
    private String[] output;
    //Input vector.
    private Vector<String> input = new Vector<String>();
    //Vector of aliases.
    private Vector<AliasSet> aliases = new Vector<AliasSet>();
    //Vector of addresses corresponding to each program line.
    private Vector<Integer> addresses = new Vector<Integer>();
    //Vector of labels.
    private Vector<Labels> labels = new Vector<Labels>();
    //Vector of error messages.
    private Vector<Error> error = new Vector<Error>();
    //Reserved words not to be used in labels.
    private String[] reserved = {"load", "stor", "jump", "jpnz", "jpz" , "jpnc",
                                 "jpc" , "call", "clnz", "clz" , "clnc", "clc" ,
                                 "ret" , "rtnz", "rtz" , "rtnc", "rtc" , "rtie",
                                 "rtid", "in"  , "out" , "and" , "or"  , "xor" ,
                                 "add" , "addc", "sub" , "subc", "test", "comp",
                                 "asl" , "rol" , "lsr" , "ror" , "setc", "clrc",
                                 "ein0", "ein1", "ein2", "ein3", "din0", "din1",
                                 "din2", "din3", "push", "pop"};
    //Invalid label characters.
    private String[] invalidChars = {"!" , "@" , "#" , "$" , "%" , "^" , "&" ,
                                     "*" , "(" , ")" , "+" , "=" , "`" , "~" ,
                                     "\\", "|" , "]" , "[" , "{" , "}" , ";" ,
                                     ":" , "\"", "\'", "-" , "<" , "," , ">" ,
                                     "." , "/" , "?"};
    //Arrays containing the different types of instructions.
    private String[] inst1 = {"ret" , "rtnz", "rtz" , "rtnc", "rtc" , "rtie",
                              "rtid", "setc", "clrc", "ein0", "ein1", "ein2",
                              "ein3", "din0", "din1", "din2", "din3"};
    private String[] inst2 = {"jump", "jpnz", "jpz" , "jpnc", "jpc" , "call",
                              "clnz", "clz" , "clnc", "clc" , "asl" , "rol" ,
                              "lsr" , "ror" , "push", "pop"};
    private String[] inst3 = {"load", "stor", "in"  , "out" , "and" , "or"  ,
                              "xor" , "add" , "addc", "sub" , "subc", "test",
                              "comp"};
    //Invalid instructions
    private String[] invalidInst =  {"stork", "jumpk", "jpnzk", "jpnzi",
                                     "jpzk" , "jpzi" , "jpnck", "jpnci",
                                     "jpck" , "jpci" , "callk", "clnzk",
                                     "clnzi", "clzk" , "clzi" , "clnck",
                                     "clnci", "clck" , "clci" , "ini"  ,
                                     "outi" , "andi" , "ori"  , "xori" ,
                                     "addi" , "addci", "subi" , "subci",
                                     "testi", "compi", "aslk" , "asli" ,
                                     "rolk" , "roli" , "lsrk" , "lsri" ,
                                     "rork" , "rori" , "pushk", "pushi",
                                     "popk" , "popi"};
    //Array of complete commands
    private String[] completeInst = {"loadk", "load" , "loadi", "stor" ,
                                     "stori", "jump" , "jumpi", "jpnz" ,
                                     "jpz"  , "jpnc" , "jpc"  , "call" ,
                                     "calli", "clnz" , "clz"  , "clnc" ,
                                     "clc"  , "ret"  , "rtnz" , "rtz"  ,
                                     "rtnc" , "rtc"  , "rtie" , "rtid" ,
                                     "ink"  , "in"   , "outk" , "out"  ,
                                     "andk" , "and"  , "ork"  , "or"   ,
                                     "xork" , "xor"  , "addk" , "add"  ,
                                     "addck", "addc" , "subk" , "sub"  ,
                                     "subck", "subc" , "testk", "test" ,
                                     "compk", "comp" , "asl"  , "rol"  ,
                                     "lsr"  , "ror"  , "setc" , "clrc" ,
                                     "ein0" , "ein1" , "ein2" , "ein3" ,
                                     "din0" , "din1" , "din2" , "din3" ,
                                     "push" , "pop"};
    //Opcodes for the above instructions.
    private String[] opcodes = {"01", "04", "07", "0A", "0D", "10", "13", "16",
                                "19", "1C", "20", "23", "26", "29", "2C", "30",
                                "33", "36", "39", "3C", "40", "43", "46", "49",
                                "4C", "50", "53", "56", "59", "5C", "60", "63",
                                "66", "69", "6C", "70", "73", "76", "79", "7C",
                                "80", "83", "86", "89", "8C", "90", "93", "96",
                                "99", "9C", "A0", "A3", "A6", "A9", "AC", "B0",
                                "B3", "B6", "B9", "BC", "C0", "C6"};
 
    NMPSM3(String[] arguments) {
 
        //Check for proper number of arguments.
        if (arguments.length < 1 || arguments.length > 2) {
            System.out.println("\nThe proper usage of the assembler is as follows:\n" +
                    "\njava -jar NMPSM3.jar [input.file] {[output.file]}\n\n" +
                    "A minimum of one argument is required which is the input assembly file.\n" +
                    "The output file name is optional.  If an output file name is not\n" +
                    "specified, the input file name with a .coe extension is created.");
            System.exit(1);
        }
 
        try {
            //Open input assembly file to read from.
            read = new RandomAccessFile(arguments[0], "r");                       
        }
        catch (IOException ioException) {
            System.err.println("Error opening file: " + ioException);
            System.exit(1);
        }
 
        try {
            //Fill input vector.
            while (read.getFilePointer() != read.length()) {
                input.add(read.readLine());
            }
        }
        catch (IOException ioException) {
            System.err.println("Error reading file: " + ioException);
            System.exit(1);
        }
 
////////////////////////Start processing input vector///////////////////////////
        //Remove all comments from input vector.
        CommentRemover();
 
        //Remove all blank lines from input vector.
        BlankLineRemover();
 
        //Replace all commas with spaces.
        CommaRemover();
 
        //Remove consecutive blank spaces from input vector.
        SpaceRemover();
 
        //Create alias vector.        
        AliasVector();        
 
        //Replace aliases in input vector.
        ReplaceAliases();
 
        //Set program size limit.
        ProgramSizer();
 
        //Fill address vector.
        FillAddressVector();
 
        //Verify the labels are properly formed and fill the label vector.
        LabelChecker();
 
        //Process the instructions.
        ProcessCode();
 
        //Fill output vector.
        FillOutput();
 
        //Print errors.
        PrintErrors();
 
        //Check vector.
        //VectorPrint();
        //Check addresses.
        //AddressPrint();
 
/////////////////////////End processing input vector////////////////////////////
        try {
            //Open output .coe file to write to.
            if(arguments.length == 2)
                write = new RandomAccessFile(arguments[1], "rw");
            else
                write = new RandomAccessFile(arguments[0].substring(0, arguments[0].indexOf('.')) + ".coe", "rw");
        }
        catch (IOException ioException) {
            System.err.println("Error opening file: " + ioException);
            System.exit(1);
        }
 
        //Write to output file.
        WriteOutput();        
 
        try {
            //Close read file
            if (read != null) {
                read.close();
            }
            //Close write file
            if (write != null) {
                write.close();
            }
        }
        catch (IOException ioException) {
            System.err.println("Error closing file: " + ioException);
            System.exit(1);
        }
        System.out.println("\nNMPSM3 .coe file created successfully.\n");
    }
 
///////////////////////////////Utility methods//////////////////////////////////
    void VectorPrint() {
        //Print input vector.  Used during development.
        System.out.println("\nInput Vector:");
        for(int i = 0; i < input.size(); i++) {
            System.out.println(input.elementAt(i));
        }
    }
 
    void AddressPrint() {
        //Print addresses vector.  Used during development.
        System.out.println("\nAddress Vector:");
        for(int i = 0; i < addresses.size(); i++) {
            System.out.println(addresses.elementAt(i));
        }
    }
 
    void CommentRemover() {
        //Trim all comments from input vector.
        for(int i = 0; i < input.size(); i++) {
            String s = input.elementAt(i);
            String[] tokenizedString = s.split(";");
            input.setElementAt(tokenizedString[0], i);
        }
    }
 
    void BlankLineRemover() {
        for(int i = 0; i < input.size(); i++) {
            String s = input.elementAt(i);
            s = s.replaceAll("\t", " ");
            s = s.replaceAll("\n", "");
            s = s.trim();
            input.setElementAt(s, i);
        }
    }
 
    void CommaRemover() {
        for(int i = 0; i < input.size(); i++) {
            String s = input.elementAt(i);
            s = s.replaceAll(",", " ");
            input.setElementAt(s, i);
        }
    }
 
    void SpaceRemover() {
        for(int i = 0; i < input.size(); i++) {
            String s = input.elementAt(i);
            String newString = "";
            String[] tokenizedString = s.split(" ");
            for(int j = 0; j < tokenizedString.length; j++) {
                if(tokenizedString[j].length() != 0)
                    newString = newString + tokenizedString[j] + " ";
            }
            newString = newString.trim();
            input.setElementAt(newString, i);
        }
    }
 
    void AliasVector() {
        for(int i = 0; i < input.size(); i++) {
            try {
                errorLine = i + 1;
                String s = input.elementAt(i);
                String[] tokenizedString = s.split(" ");
                if(tokenizedString[0].toLowerCase().equals(".alias")) {
                    if(tokenizedString.length != 3)
                        throw new Exception();
                    //Add alias to vector.
                    aliases.addElement(new AliasSet(tokenizedString[1], tokenizedString[2]));
                    //erase alias from input vector.
                    input.setElementAt("", i);
                }
            }
            catch (Exception exception) {
                if(!CheckErrorLine(errorLine))
                    error.addElement(new Error("Invalid .ALIAS", errorLine));
            }
        }
    }
 
    void ReplaceAliases() {
        for(int i = 0; i < input.size(); i++) {
            String newString = "";
            String temp;
            String s = input.elementAt(i);
            String[] tokenizedString = s.split(" ");
            for(int j = 0; j < tokenizedString.length; j++) {
                for(int k = 0; k < aliases.size(); k++) {
                    //Check for alias inside parenthesis.
                    if(tokenizedString[j].startsWith("(") && tokenizedString[j].endsWith(")")) {
                        temp = tokenizedString[j].substring(1, tokenizedString[j].length() - 1);
                        if(aliases.elementAt(k).aliasString.equals(temp))
                            tokenizedString[j] = "(" + aliases.elementAt(k).replacementString + ")";
                    }
                    if(aliases.elementAt(k).aliasString.equals(tokenizedString[j]))
                        tokenizedString[j] = aliases.elementAt(k).replacementString;
                }
            }
            for(int j = 0; j < tokenizedString.length; j++) {
                newString = newString + tokenizedString[j] + " ";
            }
            newString = newString.trim();
            input.setElementAt(newString, i);
        }
    }
 
    void ProgramSizer() {
        boolean sizeFound = false;
        for(int i = 0; i < input.size(); i++) {
            errorLine = i + 1;
            String s = input.elementAt(i);
            String[] tokenizedString = s.split(" ");
            try {
                //Size directive already found.  Throw exception.
                if(tokenizedString[0].toLowerCase().equals(".size") && sizeFound == true)
                    throw new Exception();
            }
            catch(Exception exception) {
                if(!CheckErrorLine(errorLine))
                    error.addElement(new Error("Multiple .SIZE directives", errorLine));
            }
            try {
                //Check if only one size argument.
                if(tokenizedString[0].toLowerCase().equals(".size") && tokenizedString.length != 2)
                    throw new Exception();
            }
            catch(Exception exception) {
                if(!CheckErrorLine(errorLine))
                    error.addElement(new Error("Incorrect number of .SIZE arguments", errorLine));
            }
            try {
                //Attempt to convert size argument to an integer.
                if(tokenizedString[0].toLowerCase().equals(".size")) {
                    sizeLimit = NumberConverter(tokenizedString[1]);
                    sizeFound = true;
                    //Remove .size directive
                    input.setElementAt("", i);
                }
            }
            catch(Exception exception) {
                if(!CheckErrorLine(errorLine))
                    error.addElement(new Error("Invalid .SIZE argument", errorLine));
            }
            try {
                //Check if size argument is within the proper range of 1 to 65536.
                if(sizeLimit < 1 || sizeLimit > 65536) {
                    sizeLimit = 65536;
                    input.setElementAt("", i);
                    throw new Exception();
                }
            }
            catch(Exception exception) {
                if(!CheckErrorLine(errorLine))
                    error.addElement(new Error(".SIZE argument out of range", errorLine));
            }
        }
        //Instantiate and size output array.
        output = new String[sizeLimit];
        //Initialize array values to $000000000.
        for(int i = 0; i < output.length; i++) {
            output[i] = "000000000";
        }
    }
 
    int NumberConverter(String s) {
        int number = 0;
        //Radix of number
        int numberType = 0;
        //Check if hex number.
        if(s.charAt(0) == '$') {
            numberType = 16;
            s = s.substring(1);
        }
        //Check if binary number.
        else if(s.charAt(0) == '%') {
            numberType = 2;
            s = s.substring(1);
        }
        else
            numberType = 10;
        //Attempt to parse.  Exception will be caught by calling method.
        number = Integer.parseInt(s, numberType);
        return number;
    }
 
    void FillAddressVector() {
        for(int i = 0; i < input.size(); i++) {
            errorLine = i + 1;
            String s = input.elementAt(i);
            String[] tokenizedString = s.split(" ");
            //Empty element.
            if(s.length() == 0) {
                addresses.addElement(currentAddress);
            }
            //Check to see if valid .ORG directive is present.
            else if(tokenizedString[0].toLowerCase().equals(".org")) {
                try {
                    if(tokenizedString.length != 2)
                        throw new Exception();
                    currentAddress = NumberConverter(tokenizedString[1]);
                    addresses.addElement(currentAddress);
                    //Erase .ORG directive
                    input.setElementAt("", i);
                }
                catch(Exception exception) {
                    if(!CheckErrorLine(errorLine))
                        error.addElement(new Error("Incorrect number of .ORG arguments", errorLine));
                }
            }
            //Check to see if label is present.
            else if(tokenizedString[0].contains(":")) {
                //Throw exception if more than 1 colon
                try {
                    int charCounter = 0;
                    for(int j = 0; j < s.length(); j++)
                        if(s.charAt(j) == ':')
                            charCounter++;
                    if(charCounter > 1){
                        throw new Exception();
                    }
                }
                catch(Exception exception) {
                    if(!CheckErrorLine(errorLine))
                        error.addElement(new Error("Multiple labels", errorLine));
                }
                //Check if label only line.
                if(tokenizedString.length == 1 && tokenizedString[0].charAt(tokenizedString[0].length() - 1) == ':')
                    addresses.addElement(currentAddress);
                //Else must be a label plus an instruction.
                else {
                    //Add space between label and instruction.
                    String[] labelTokenizer = s.split(":");
                    labelTokenizer[0] = labelTokenizer[0].trim();
                    labelTokenizer[1] = labelTokenizer[1].trim();
                    input.setElementAt(labelTokenizer[0] + ": " + labelTokenizer[1], i);
                    addresses.addElement(currentAddress);
                    currentAddress++;
                }
            }
            //Only possibility left is an instruction only.
            else {
                addresses.addElement(currentAddress);
                currentAddress++;
            }
            //Throw exception if spaces in label.
            try {
                for(int k = 1; k < tokenizedString.length; k++)
                    if(tokenizedString[k].contains(":"))
                        throw new Exception();
            }
            catch(Exception exception) {
                if(!CheckErrorLine(errorLine))
                    error.addElement(new Error("Invalid label", errorLine));
            }
        }
    }
 
    void LabelChecker() {
        for(int i = 0; i < input.size(); i++) {
            errorLine = i + 1;
            String newString = "";
            String s = input.elementAt(i);
            String[] tokenizedString = s.split(" ");
            //Fill labels vector.
            if(tokenizedString[0].length() > 0 && tokenizedString[0].charAt(tokenizedString[0].length() - 1) == ':') {
                labels.addElement(new Labels(tokenizedString[0], addresses.elementAt(i), errorLine));
                //Remove label from input vector.
                if(tokenizedString.length > 1) {
                    for(int j = 1; j < tokenizedString.length; j++)
                        newString = newString + tokenizedString[j] + " ";
                    newString.trim();
                    input.setElementAt(newString, i);
                }
                else
                    input.setElementAt("", i);
            }
        }
        //Remove colons from labels and throw exceptions on empty labels.
        for(int i = 0; i < labels.size(); i++) {
            try {
                errorLine = labels.elementAt(i).lineNumber;
                labels.elementAt(i).labelName = labels.elementAt(i).labelName.split(":")[0];
            }
             catch(Exception exception) {
                 if(!CheckErrorLine(errorLine))
                     error.addElement(new Error("Invalid label", errorLine));
             }
        }
        //Check for reserved words.
        for(int i = 0; i < labels.size(); i++) {
            try {
                errorLine = labels.elementAt(i).lineNumber;
                for(int j = 0; j < reserved.length; j++)
                    if(labels.elementAt(i).labelName.toLowerCase().equals(reserved[j].toLowerCase()))
                        throw new Exception();
            }        
            catch(Exception exception) {
                if(!CheckErrorLine(errorLine))
                    error.addElement(new Error("Reserved word used in label", errorLine));
            }
        }
        //Check for invalid characters.
        for(int i = 0; i < labels.size(); i++) {
            try {
                errorLine = labels.elementAt(i).lineNumber;
                for(int j = 0; j < invalidChars.length; j++)
                    if(labels.elementAt(i).labelName.contains(invalidChars[j]))
                        throw new Exception();
            }        
            catch(Exception exception) {
                if(!CheckErrorLine(errorLine))
                    error.addElement(new Error("Invalid character in label", errorLine));
            }
        }
        //Check to make sure label does not start with a number.
        for(int i = 0; i < labels.size(); i++) {
            try {
                errorLine = labels.elementAt(i).lineNumber;
                if(Character.isDigit(labels.elementAt(i).labelName.charAt(0)))
                    throw new Exception();
            }        
            catch(Exception exception) {
                if(!CheckErrorLine(errorLine))
                    error.addElement(new Error("Label starting with a number", errorLine));
            }
        }
        //Check for duplicate labels.
        for(int i = 0; i < labels.size() - 1; i++) {
            try {
                for(int j = i + 1; j < labels.size(); j++) {
                    errorLine = labels.elementAt(j).lineNumber;
                    if(labels.elementAt(i).labelName.equals(labels.elementAt(j).labelName))
                        throw new Exception();
                }
            }
            catch(Exception exception) {
                if(!CheckErrorLine(errorLine))
                    error.addElement(new Error("Duplicate label", errorLine));
            //System.err.println("Duplicate label. Line " + errorLine);
            //System.exit(1);
            }
        }
        //Check for labels already being used as aliases.
        for(int i = 0; i < labels.size(); i++) {
            try{
                for(int j = 0; j < aliases.size(); j++) {
                    errorLine = labels.elementAt(i).lineNumber;
                    if(labels.elementAt(i).labelName.equals(aliases.elementAt(j).aliasString))
                        throw new Exception();
                }
            }
            catch(Exception exception) {
                if(!CheckErrorLine(errorLine))
                    error.addElement(new Error("Label already used as alias", errorLine));
            }            
        }   
    }
 
    void ProcessCode() {
        for(int i = 0; i < input.size(); i++) {
            int instType, argument1, argument2;
            String argHex1, argHex2;
            errorLine = i + 1;
            String s = input.elementAt(i);
            if(s.length() != 0) {
                String[] tokenizedString = s.split(" ");
                instType = GetInstType(tokenizedString[0]);
                //Check to see if instruction is a valid instruction.
                try {
                    if(instType == -1)
                        throw new Exception();
                }
                catch(Exception exception) {
                    if(!CheckErrorLine(errorLine))
                        error.addElement(new Error("Undefined instruction", errorLine));
                }
                try {
                    if(tokenizedString.length != instType)
                        throw new Exception();
                }
                catch(Exception exception) {
                    if(!CheckErrorLine(errorLine))
                        error.addElement(new Error("Incorrect number of arguments", errorLine));
                }
                //Check if instruction is a constant instruction and change it accordingly.
                if(instType == 3 && tokenizedString[2].startsWith("#")) {
                    tokenizedString[0] = tokenizedString[0] + "k";
                    tokenizedString[2] = tokenizedString[2].substring(1, tokenizedString[2].length());
                    //Special case for LOAD rx, #k for loading labels.
                    if(tokenizedString[0].toLowerCase().equals("loadk"))
                        for(int j = 0; j < labels.size(); j++)
                            if(tokenizedString[2].equals(labels.elementAt(j).labelName))
                                tokenizedString[2] = "" + labels.elementAt(j).labelAddress;
                    input.setElementAt((tokenizedString[0] + " " + tokenizedString[1] + " " + tokenizedString[2]), i);
                }
                if(instType == 2 && tokenizedString[1].startsWith("#")) {
                    tokenizedString[0] = tokenizedString[0] + "k";
                    tokenizedString[1] = tokenizedString[1].substring(1, tokenizedString[1].length());
                    input.setElementAt((tokenizedString[0] + " " + tokenizedString[1]), i);
                }
                //Check if instruction is an indirect instruction and change it accordingly.
                if(instType == 3 && tokenizedString[2].startsWith("(") && tokenizedString[2].endsWith(")")) {
                    tokenizedString[0] = tokenizedString[0] + "i";
                    tokenizedString[2] = tokenizedString[2].substring(1, tokenizedString[2].length() - 1);
                    input.setElementAt((tokenizedString[0] + " " + tokenizedString[1] + " " + tokenizedString[2]), i);
                }
                if(instType == 2 && tokenizedString[1].startsWith("(") && tokenizedString[1].endsWith(")")) {
                    tokenizedString[0] = tokenizedString[0] + "i";
                    tokenizedString[1] = tokenizedString[1].substring(1, tokenizedString[1].length() - 1);
                    input.setElementAt((tokenizedString[0] + " " + tokenizedString[1]), i);
                }
                //Check to see if illegal addressing mode for this instruction.
                try {
                    for(int j = 0; j < invalidInst.length; j++)
                        if(tokenizedString[0].toLowerCase().equals(invalidInst[j]))
                            throw new Exception();
                }
                 catch(Exception exception) {
                    if(!CheckErrorLine(errorLine))
                        error.addElement(new Error("Invalid addressing mode", errorLine));
                }
                //Substitute labels for addresses.
                if(tokenizedString[0].toLowerCase().equals("jump") || tokenizedString[0].toLowerCase().equals("jpnz") ||
                   tokenizedString[0].toLowerCase().equals("jpz")  || tokenizedString[0].toLowerCase().equals("jpnc") ||
                   tokenizedString[0].toLowerCase().equals("jpc")  || tokenizedString[0].toLowerCase().equals("call") ||
                   tokenizedString[0].toLowerCase().equals("clnz") || tokenizedString[0].toLowerCase().equals("clz")  ||
                   tokenizedString[0].toLowerCase().equals("clnc") || tokenizedString[0].toLowerCase().equals("clc"))
                    for(int j = 0; j < labels.size(); j++)
                        if(tokenizedString[1].equals(labels.elementAt(j).labelName))
                            input.setElementAt((tokenizedString[0] + " " + labels.elementAt(j).labelAddress), i);
                //Validate parameters and replace instructions with opcodes.
                try {
                    //Single argument instruction.
                    if(instType == 1)
                        for(int j = 0; j < completeInst.length; j++)
                            if(tokenizedString[0].toLowerCase().equals(completeInst[j]))
                                input.setElementAt((opcodes[j] + "0000000"), i);
                    //Two argument, indirect instruction or direct instruction.
                    if(instType == 2 && (tokenizedString[0].endsWith("i") || tokenizedString[0].toLowerCase().equals("asl")  ||
                           tokenizedString[0].toLowerCase().equals("rol") || tokenizedString[0].toLowerCase().equals("lsr")  ||
                           tokenizedString[0].toLowerCase().equals("ror") || tokenizedString[0].toLowerCase().equals("push") ||
                           tokenizedString[0].toLowerCase().equals("pop"))) {
                        argument1 = NumberConverter(tokenizedString[1]);
                        try {
                            if(argument1 >= 0x400)
                                throw new Exception();
                        }
                        catch (Exception excepion) {
                            if(!CheckErrorLine(errorLine))
                                error.addElement(new Error("Register address out of range", errorLine));
                        }
                        //convert integer to hex string.
                        argHex1 = Integer.toHexString(argument1);
                        //Add leading zeroes, if necessary.
                        if(argHex1.length() == 1)
                            argHex1 = "00" + argHex1;
                        if(argHex1.length() == 2)
                            argHex1 = "0" + argHex1;
                        //Replace command in input vector with opcode.
                        for(int j = 0; j < completeInst.length; j++)
                            if(tokenizedString[0].toLowerCase().equals(completeInst[j]))
                                input.setElementAt((opcodes[j] + argHex1.toUpperCase() + "0000"), i);
                    }
                    //Two argument, address instruction.
                    if(tokenizedString[0].toLowerCase().equals("jump") || tokenizedString[0].toLowerCase().equals("jpnz") ||
                       tokenizedString[0].toLowerCase().equals("jpz")  || tokenizedString[0].toLowerCase().equals("jpnc") ||
                       tokenizedString[0].toLowerCase().equals("jpc")  || tokenizedString[0].toLowerCase().equals("call") ||
                       tokenizedString[0].toLowerCase().equals("clnz") || tokenizedString[0].toLowerCase().equals("clz")  ||
                       tokenizedString[0].toLowerCase().equals("clnc") || tokenizedString[0].toLowerCase().equals("clc")) {
                        //Retokenize line string.
                        s = input.elementAt(i);
                        tokenizedString = s.split(" ");
                        argument1 = NumberConverter(tokenizedString[1]);
                        try {
                            if(argument1 >= 0x10000)
                                throw new Exception();
                        }
                        catch (Exception excepion) {
                            if(!CheckErrorLine(errorLine))
                                error.addElement(new Error("ROM address out of range", errorLine));                            
                        }
                        //Jump out of program size limit.
                        try {
                            if(argument1 > sizeLimit)
                                throw new Exception();
                        }
                        catch (Exception excepion) {
                            if(!CheckErrorLine(errorLine))
                                error.addElement(new Error("JUMP/CALL address greater than program size limit", errorLine));
                        }
                        //convert integer to hex string.
                        argHex1 = Integer.toHexString(argument1);
                        //Add leading zeroes, if necessary.
                        if(argHex1.length() == 1)
                            argHex1 = "000" + argHex1;
                        if(argHex1.length() == 2)
                            argHex1 = "00" + argHex1;
                        if(argHex1.length() == 3)
                            argHex1 = "0" + argHex1;
                        //Replace command in input vector with opcode.
                        for(int j = 0; j < completeInst.length; j++)
                            if(tokenizedString[0].toLowerCase().equals(completeInst[j]))
                                input.setElementAt((opcodes[j] + "000" + argHex1.toUpperCase()), i);
                    }
                    //Three argument, indirect instruction and immediate instruction.
                    if(instType == 3) {
                        //Identify instruction.
                        for(int j = 0; j < completeInst.length; j++) {
                            if(tokenizedString[0].toLowerCase().equals(completeInst[j])) {
                                //First argument same type regardless of instruction type.
                                argument1 = NumberConverter(tokenizedString[1]);
                                try {
                                    if(argument1 >= 0x400)
                                        throw new Exception();
                                }
                                catch (Exception excepion) {
                                    if(!CheckErrorLine(errorLine))
                                        error.addElement(new Error("Register address out of range", errorLine));                                    
                                }
                                //Add leading zeroes, if necessary.
                                argHex1 = Integer.toHexString(argument1);
                                if(argHex1.length() == 1)
                                    argHex1 = "00" + argHex1;
                                if(argHex1.length() == 2)
                                    argHex1 = "0" + argHex1;
                                //Indirect instruction.
                                if(tokenizedString[0].endsWith("i")) {
                                    argument2 = NumberConverter(tokenizedString[2]);
                                    try {
                                        if(argument2 >= 0x400)
                                        throw new Exception();
                                    }
                                    catch (Exception excepion) {
                                        if(!CheckErrorLine(errorLine))
                                            error.addElement(new Error("Register address out of range", errorLine));                                       
                                    }
                                    //Add leading zeroes, if necessary.
                                    argHex2 = Integer.toHexString(argument2);
                                    if(argHex2.length() == 1)
                                        argHex2 = "000" + argHex2;
                                    if(argHex2.length() == 2)
                                        argHex2 = "00" + argHex2;
                                    if(argHex2.length() == 3)
                                        argHex2 = "0" + argHex2;
                                }
                                //Immediate instruction.
                                else if(tokenizedString[0].endsWith("k")){
                                    argument2 = NumberConverter(tokenizedString[2]);
                                    try {
                                        if(argument2 >= 0x10000)
                                        throw new Exception();
                                    }
                                    catch (Exception excepion) {
                                        if(!CheckErrorLine(errorLine))
                                            error.addElement(new Error("Constant value out of range", errorLine));                                      
                                    }
                                    //Add leading zeroes, if necessary.
                                    argHex2 = Integer.toHexString(argument2);
                                    if(argHex2.length() == 1)
                                        argHex2 = "000" + argHex2;
                                    if(argHex2.length() == 2)
                                        argHex2 = "00" + argHex2;
                                    if(argHex2.length() == 3)
                                        argHex2 = "0" + argHex2;
                                }
                                //Direct instruction.
                                else {
                                    argument2 = NumberConverter(tokenizedString[2]);
                                    try {
                                        if(argument2 >= 0x400)
                                        throw new Exception();
                                    }
                                    catch (Exception excepion) {
                                        if(!CheckErrorLine(errorLine))
                                            error.addElement(new Error("Register address out of range", errorLine));                                       
                                    }
                                    //Add leading zeroes, if necessary.
                                    argHex2 = Integer.toHexString(argument2);
                                    if(argHex2.length() == 1)
                                        argHex2 = "000" + argHex2;
                                    if(argHex2.length() == 2)
                                        argHex2 = "00" + argHex2;
                                    if(argHex2.length() == 3)
                                        argHex2 = "0" + argHex2;
                                }
                                //Replace command in input vector with opcode.
                                input.setElementAt((opcodes[j] + argHex1.toUpperCase() + argHex2.toUpperCase()), i);
                            }
                        }
                    }
                }
                catch(Exception exception) {
                    if(!CheckErrorLine(errorLine))
                        error.addElement(new Error("Invalid parameter", errorLine));
                }
            }
        }
    }
 
    int GetInstType(String s) {
        //Search through the instructions to make sure they are valid and
        //determine how many parameters each instruction should have.
        for(int i = 0; i < inst1.length; i++) {
            if(s.toLowerCase().equals(inst1[i]))
                return 1;
        }
        for(int i = 0; i < inst2.length; i++) {
            if(s.toLowerCase().equals(inst2[i]))
                return 2;
        }
        for(int i = 0; i < inst3.length; i++) {
            if(s.toLowerCase().equals(inst3[i]))
                return 3;
        }
        return -1;
    }
 
    void FillOutput() {
        for(int i = 0; i < input.size(); i++) {
            errorLine = i + 1;
            //Process element only if it contains data.
            if(input.elementAt(i).length() != 0) {
                //Make sure address is within program size limit.
                try {
                    if(addresses.elementAt(i) >= sizeLimit)
                        throw new Exception();
                }
                catch(Exception exception) {                    
                    error.addElement(new Error("Instruction address exceeds program size limit", errorLine));                   
                }
                //Check to see if instruction address is not already occupied.
                try {
                    if(!output[addresses.elementAt(i)].equals("000000000"))
                        throw new Exception();
                }
                catch(Exception exception) {
                    if(!CheckErrorLine(errorLine))
                        error.addElement(new Error("Instruction address already occupied", errorLine));
                }
                //Write opcode to output vector.
                if(error.isEmpty())
                    output[addresses.elementAt(i)] = input.elementAt(i);
            }
        }
    }
 
    void WriteOutput() {
        String memInit = "memory_initialization_radix=16;";
        String initVector = "memory_initialization_vector=";
        try {
            write.setLength(0); //Erase any previous contents.
            write.writeBytes(memInit); //Write init strings.
            write.writeByte(0x0D); //Notepad new lines.
            write.writeByte(0x0A);
            write.writeBytes(initVector);
            //Write opcodes.
            for(int i = 0; i < output.length - 1; i++) {
                //New line after every eight opcodes.
                if(i % 8 == 0) {
                    write.writeByte(0x0D); //Notepad new lines.
                    write.writeByte(0x0A);
                }
                write.writeBytes(output[i] + ", ");
            }
            //Write last instruction in file.
            if((output.length % 8 == 1) && (output.length > 1)) {
                write.writeByte(0x0D); //Notepad new lines.
                write.writeByte(0x0A);
            }
            write.writeBytes(output[output.length - 1] + ";");
        }
        catch (IOException ioException) {
            System.err.println("Error writing to .coe file: " + ioException);
            System.exit(1);
        }
    }
 
    void PrintErrors() {
        if(error.isEmpty()) {
            System.out.println("\nNo errors detected.");
            return;
        }
        System.out.println("\nErrors:");
        for(int i = 0; i < error.size(); i++) {
            System.out.println(error.elementAt(i).errorString + " " + error.elementAt(i).errorLine);
        }
        System.out.println("Total errors: " + error.size());
        System.exit(1);
    }
 
    boolean CheckErrorLine(int errorLine) {
        for(int i = 0; i < error.size(); i++)
            if(error.elementAt(i).errorLine == errorLine)
                return true;
        return false;
    }
 
/////////////////////////////////Main method////////////////////////////////////
    public static void main(String[] args) {
       NMPSM3 nmpsm3 = new NMPSM3(args);
    }
}


NMPSM3软件

下面的第一个文件是控制项目的汇编语言程序。下一个文件是汇编器的编译版本。第三个文件是一个简单的批处理文件,它运行汇编程序并将NMPSM3代码汇编为.coe文件。

program.asm
.size 1024
 
;------------------------------------Addressable hardware list-------------------------------------
;0x0000 - 0x0007 ROM controller.
;0x0010          Timer 0.
;0x0011          Timer 1.
;0x0012          Input MUX - ROM data.
;0x0013          Input MUX - Switches.
;0x0020          LED controller.
;0x0024 - 0x0027 Seven segment controller.
;0x0030 - 0x0033 Input MUX - Clock data.
;0x0034          Input MUX - Microphone data.
 
;-------------------------------------VGA Controller addresses-------------------------------------
;0x8000 - 0x87FF Background pattern table A.
;0x8800 - 0x8FFF Background pattern table B.
;0x9000 - 0x97FF Sprite pattern table A.
;0x9800 - 0x9FFF Sprite pattern table B.
;0xA000 - 0xA3FF Name table.
;0xA400 - 0xA4FF Unused.
;0xA500 - 0xA5FF Background attribute table.
;0xA600 - 0xA60F Background pallettes 0 through 15.
;0xA610 - 0xA61F Sprite pallettes 0 through 15.
;0xA700          Base color (background color).
;0xB000 - 0xB3FF Sprite RAM (256 sprites).
 
;--------------------------------------Sprite RAM Memory Map---------------------------------------
;0xB000 - 0xb01F Bouncing sprites (8 sprites).
;0xB020 - 0xB05F Rotation sprites (16 sprites).
;0xB0D0 - 0xB0FF Samus sprites (12 sprites).
;0xB100 - 0xB2FF Audio sprites.
 
;---------------------------------------------Defines----------------------------------------------
;ASCII numbers.
.alias ZERO                 #$30
.alias ONE                  #$31
.alias TWO                  #$32
.alias THREE                #$33
.alias FOUR                 #$34
.alias FIVE                 #$35
.alias SIX                  #$36
.alias SEVEN                #$37
.alias EIGHT                #$38
.alias NINE                 #$39
 
;ASCII letters.
.alias A                    #$41
.alias B                    #$42
.alias C                    #$43
.alias D                    #$44
.alias E                    #$45
.alias F                    #$46
.alias G                    #$47
.alias H                    #$48
.alias I                    #$49
.alias J                    #$4A
.alias K                    #$4B
.alias L                    #$4C
.alias M                    #$4D
.alias N                    #$4E
.alias O                    #$4F
.alias P                    #$50
.alias Q                    #$51
.alias R                    #$52
.alias S                    #$53
.alias T                    #$54
.alias U                    #$55
.alias V                    #$56
.alias W                    #$57
.alias X                    #$58
.alias Y                    #$59
.alias Z                    #$5A
 
.alias a                    #$61
.alias b                    #$62
.alias c                    #$63
.alias d                    #$64
.alias e                    #$65
.alias f                    #$66
.alias g                    #$67
.alias h                    #$68
.alias i                    #$69
.alias j                    #$6A
.alias k                    #$6B
.alias l                    #$6C
.alias m                    #$6D
.alias n                    #$6E
.alias o                    #$6F
.alias p                    #$70
.alias q                    #$71
.alias r                    #$72
.alias s                    #$73
.alias t                    #$74
.alias u                    #$75
.alias v                    #$76
.alias w                    #$77
.alias x                    #$78
.alias y                    #$79
.alias z                    #$7A
 
;ASCII symbols.
.alias SPACE                #$20
.alias COLON                #$3A
.alias COMMA                #$2C
.alias PERIOD               #$2E
.alias CR                   #$0D                    ;Carriage return.
.alias FSLASH               #$2F                    ;Forward slash.
.alias LBAR                 #$5F                    ;Underscore.
.alias MBAR                 #$2D                    ;Minus sign.
.alias UBAR                 #$FF                    ;Upper bar.
.alias STAR                 #$2A                    ;Multiply sign.
.alias OPEN_C_BRACE         #$7B                    ;Open curly brace.
 
;Output port IDs.
.alias LEDTBL               #$0000                  ;
.alias TIMELOTBL            #$0001                  ;
.alias SEG7INDEXTBL         #$0002                  ;
.alias SEG7TBL              #$0003                  ;
.alias LOOKUPADDR           #$0004                  ;ROM addresses.
.alias MESSAGETBL           #$0005                  ;
.alias PALETTETBL           #$0006                  ;
.alias SPRITETBL            #$0007                  ;
.alias SAMUSTBL             #$0006                  ;
 
.alias SET_BAUD             #$0200                  ;
.alias TX_STORE_BYTE        #$0201                  ;
.alias TX_FLUSH             #$0202                  ;UART control.
.alias TX_PURGE             #$0203                  ;
.alias RX_NEXT_BYTE         #$0204                  ;
.alias RX_PURGE             #$0205                  ;
 
.alias DOT0                 #$A288                  ;
.alias DOT1                 #$A294                  ;Name table addresses-->
.alias DOT2                 #$A2E8                  ;for clock dots.
.alias DOT3                 #$A2F4                  ;
 
.alias LOSEC                #$A29B                  ;
.alias HISEC                #$A296                  ;Starting addresses of-->
.alias LOMIN                #$A28F                  ;clock digits in name-->
.alias HIMIN                #$A28A                  ;table.
.alias LOHOUR               #$A283                  ;
 
.alias A                    #$A29F                  ;Name table positions-->
.alias B                    #$A2FF                  ;of A and P in clock.
 
.alias TIMER0               #$0010                  ;Timers
.alias TIMER1               #$0011                  ;
 
.alias LEDIO                #$0020                  ;LED controller.
.alias LEDIO2               #$0021                  ;Upper LED controller.
 
.alias SEG0                 #$0024                  ;
.alias SEG1                 #$0025                  ;7 segment display
.alias SEG2                 #$0026                  ;
.alias SEG3                 #$0027                  ;
 
;Input port IDs.
.alias UARTDATA             #$0003                  ;
.alias TXCOUNT              #$0004                  ;UART ports.
.alias RXCOUNT              #$0005                  ;
 
.alias ROMDATA              #$0012                  ;ROM data
.alias SWITCHES             #$0013                  ;Switches
 
.alias SEC                  #$0030                  ;
.alias MIN                  #$0031                  ;Clock data
.alias HOUR                 #$0032                  ;
.alias BLINK                #$0033                  ;
 
.alias MICDATA              #$0034                  ;Mic data
 
;RAM aliases.
.alias ledIndex             $0000
.alias timeIndex            $0001
.alias segIndex             $0002
.alias switchReg            $0003
.alias waitReg              $0004
 
.alias sp0y                 $0010                   ;
.alias sp1y                 $0011                   ;
.alias sp2y                 $0012                   ;
.alias sp3y                 $0013                   ;Bouncing sprite y positions.
.alias sp4y                 $0014                   ;
.alias sp5y                 $0015                   ;
.alias sp6y                 $0016                   ;
.alias sp7y                 $0017                   ;
 
.alias sp0x                 $0018                   ;
.alias sp1x                 $0019                   ;
.alias sp2x                 $001A                   ;
.alias sp3x                 $001B                   ;Bouncing sprite x positions.
.alias sp4x                 $001C                   ;
.alias sp5x                 $001D                   ;
.alias sp6x                 $001E                   ;
.alias sp7x                 $001F                   ;
 
.alias sp0m                 $0020                   ;
.alias sp1m                 $0021                   ;
.alias sp2m                 $0022                   ;
.alias sp3m                 $0023                   ;Bouncing sprite move directions.
.alias sp4m                 $0024                   ;
.alias sp5m                 $0025                   ;
.alias sp6m                 $0026                   ;
.alias sp7m                 $0027                   ;
 
.alias palRegs              $0030                   ;Thru $4F
.alias tempReg0             $0050
.alias tempReg1             $0051
.alias tempReg2             $0052
.alias tempReg3             $0053
.alias colCount             $0054
.alias rowCount             $0055
.alias numIn                $0056
.alias numOffset            $0057
.alias AMPMReg0             $0058
.alias AMPMReg1             $0059
.alias startReg             $005A
.alias stopReg              $005B
.alias mIndexReg            $005C
.alias bcDelReg             $005D
.alias bcReg                $005E
.alias checkReg             $005F
.alias palDelReg            $0060
.alias mirDelReg            $0061
.alias mirPtrReg            $0062
.alias audPtrReg            $0063
.alias audCtrReg            $0064
.alias audHldReg            $0065
.alias miscReg              $0066
.alias atDelReg             $0067
.alias atStatReg            $0068
.alias callReg              $0069
.alias clearReg             $006A
.alias swReg                $006B
.alias anDelReg             $006C
.alias samROMReg            $006D
.alias samXReg              $006E
.alias movDelReg            $006F
.alias samM0Reg             $0090
.alias samM1Reg             $0091
.alias samM2Reg             $0092
.alias micDelReg            $0093
.alias micStaReg            $0094
.alias micSmpReg            $0095
.alias waitStateReg         $0096
.alias audioRegs            $0100                   ;Through $17F(128 total).
 
.alias uartTxByte           $0180                   ;
.alias uartRxByte           $0181                   ;UART value registers.
.alias uartTxCount          $0182                   ;
.alias uartRxCount          $0183                   ;
 
.alias bufCurPointer        $0184                   ;Pointer to current position in uart buffer.
.alias bufEndPointer        $0185                   ;Pointer to last position in uart buffer.               
.alias uartBuf              $0186                   ;thru $01A1.
 
;Constants.
.alias UPRIGHT              #$20
.alias UPLEFT               #$60
.alias DOWNRIGHT            #$A0
.alias DOWNLEFT             #$E0
.alias PALREGS              #$30
.alias AT0                  #$1B
.alias AT1                  #$C6
.alias AT2                  #$B1
.alias AT3                  #$6C
 
.alias SPRITEREGS           #$0100                  ;Start of sprite audio regs.
.alias ENDAUDIOREGS         #$0180                  ;End of sprite audio regs.
.alias PPUAUDSPSTART        #$B100                  ;Start address of audio sprites in PPU.
.alias PPUAUDSPEND          #$B300                  ;End address of audio sprites in PPU.
 
;-------------------------------------------Start of code------------------------------------------
    jump Reset                                      ;
    jump Interrupt0                                 ;
    jump Interrupt1                                 ;Reset and interrupt vectors.
    jump Interrupt2                                 ;
    jump Interrupt3                                 ;
 
Reset:
    call ClearRegs
    call ClearBouncingSprites
    call SetDefaultPalettes
    call InitLEDIndex
    call Init7SegsIndex
 
    load micSmpReg, #$0080  
    load samROMReg, #$40
    load samXReg  , #$E5
    load samM0Reg , #$03
    load samM1Reg , #$03
    load samM2Reg , #$03
    load AMPMReg1 , #$11
    load tempReg0 , #5
    out  tempReg0 , TIMER0
    out  tempReg0 , TIMER1  
 
    load uartTxByte #$D9                            ;Set UART baud rate to 230400.
    out  uartTxByte SET_BAUD                        ;
 
    ein0
    ein1
    ein2
 
MainLoop:
    comp waitReg  , #1                              ;Check to see if current-->
    jpz  MainLoop                                   ;frame processing is done.
    din2                                            ;Disable VBlank interrupt.
 
    load waitReg  , #1                              ;Process current frame data.
    add  micDelReg, #1
    comp micDelReg, #3
    clz GetAudioData
 
    ein2                                            ;Enable VBlank interrupt.
    jump MainLoop                                   ;Run main loop forever.
 
;The following function sets all the register values to 0.
ClearRegs:
    load 0 #$3FF                                    ;
    load 1 #0                                       ;
    ClearRegsLoop:                                  ;Start at top register and-->
    stor 1 (0)                                      ;decrement through them setting-->
    sub  0 #1                                       ;them all to 0.
    jpnz ClearRegsLoop                              ;
    ret                                             ;
 
Interrupt0:
    out  timeIndex, TIMELOTBL
    in   tempReg0 , ROMDATA
    or   tempReg0 , #0
    clz  InitLEDIndex
 
    out  timeIndex, TIMELOTBL
    in   tempReg0 , ROMDATA
    out  tempReg0 , TIMER0
 
    out  ledIndex , LEDTBL
    in   tempReg0 , ROMDATA
    out  tempReg0 , LEDIO
 
    add  timeIndex, #1
    add  ledIndex , #1
    rtie
 
InitLEDIndex:
    load ledIndex , #0
    load timeIndex, #0
    ret
 
Interrupt1:
    comp segIndex , #$20
    clz  Init7SegsIndex
 
    load tempReg0 , segIndex
    load tempReg2 , SEG0
    call DoSeg
 
    add  tempReg0 , #1
    load tempReg2 , SEG1
    call DoSeg
 
    add  tempReg0 , #1
    load tempReg2 , SEG2
    call DoSeg
 
    add  tempReg0 , #1
    load tempReg2 , SEG3
    call DoSeg
 
    load tempReg0 , #$B0
    out  tempReg0 , TIMER1
 
    add  segIndex , #1    
    rtie
 
DoSeg:
    out  tempReg0 , SEG7INDEXTBL
    in   tempReg1 , ROMDATA
    out  tempReg1 , SEG7TBL
    in   tempReg1 , ROMDATA
    out  tempReg1 , tempReg2
    ret
 
Init7SegsIndex:
    load segIndex , #0
    ret
 
Interrupt2:
Interrupt3:
    load waitReg  , #0
    call DoMessage
    call DoClock
    call DoBaseColor
    call DoBouncingSprites
    call DoPaletteChange
    call DoSpriteMirroring
    call DoSpriteAudio
    call DoAttribChange
    call DoSpritePriority
    call DoUART                                 ;Check for waiting data in UART.
    rtie
 
DoFunction:
    in   switchReg, SWITCHES
    and  switchReg, swReg
    DoSubFunction:
    comp switchReg, swReg
    jpz  RunFunction
    jump ClearFunction
    RunFunction:
    jump (callReg)   
    ClearFunction:
    jump (clearReg)
    DoZeroFunction:
    in   switchReg, SWITCHES
    jump DoSubFunction
 
DoUART:
    call CheckUART                                  ;;Get any waiting bytes from UART.
    call EchoByte                                   ;Echo byte back to terminal.
    ret
 
CheckUART:
    in   uartRxByte, UARTDATA                       ;Get UART byte.
    comp uartRxByte, #0                             ;See if it is a valid byte.
    rtz                                             ;If not, return.
 
    out  uartRxByte, LEDIO2                         ;Echo byte to the upper LEDs.
    out  uartRxByte, TX_STORE_BYTE                  ;Echo byte back to terminal.
    out  uartRxByte, RX_NEXT_BYTE                   ;Move to next position.
    jump CheckUART  
 
EchoByte:
    out  tempReg0,   TX_FLUSH                       ;Flush tx output.
    ret                                             ;
 
DoClock:
    load swReg    , #$01
    load callReg  , #LoadClock
    load clearReg , #ClearClock
    jump DoFunction
 
LoadClock:
    in   tempReg0 , BLINK
    or   tempReg0 , #0
    clnz DrawDots
    or   tempReg0 , #0
    clz  ClearDots
    in   tempReg0 , HOUR
    and  tempReg0 , #$00F0
    clnz DrawOne
    and  tempReg0 , #$00F0
    clz  ClearOne
 
    in   tempReg0 , SEC
    call NibbleShift
    load numOffset, LOSEC
    call DisplayDigit
 
    in   tempReg0 , SEC
    and  tempReg0 , #$F0
    load numOffset, HISEC
    call DisplayDigit
 
    in   tempReg0 , MIN
    call NibbleShift
    load numOffset, LOMIN
    call DisplayDigit
 
    in   tempReg0 , MIN
    and  tempReg0 , #$F0
    load numOffset, HIMIN
    call DisplayDigit
 
    in   tempReg0 , HOUR
    call NibbleShift
    load numOffset, LOHOUR
    call DisplayDigit
 
    call AMPM
    load tempReg0 , AMPMReg0
    comp tempReg0 , #0
    clz  AM
    load tempReg0 , AMPMReg0
    comp tempReg0 , #0
    clnz PM            
    ret
 
DrawDots:
    load tempReg0 , #$6F
    out  tempReg0 , DOT0
    out  tempReg0 , DOT1
    out  tempReg0 , DOT2
    out  tempReg0 , DOT3    
    ret
 
ClearDots:
    load tempReg0 , #$FF
    out  tempReg0 , DOT0
    out  tempReg0 , DOT1
    out  tempReg0 , DOT2
    out  tempReg0 , DOT3
    ret
 
DrawOne:
    load tempReg0 , #$44
    out  tempReg0 , #$A280
    load tempReg0 , #$4D
    out  tempReg0 , #$A281
    load tempReg0 , #$50
    out  tempReg0 , #$A2A0
    load tempReg0 , #$47
    out  tempReg0 , #$A2A1
    out  tempReg0 , #$A2C1
    load tempReg0 , #$55
    out  tempReg0 , #$A2E1
    ret
 
ClearOne:
    load tempReg0 , #$FF
    out  tempReg0 , #$A280
    out  tempReg0 , #$A281
    out  tempReg0 , #$A2A0
    out  tempReg0 , #$A2A1
    out  tempReg0 , #$A2C1
    out  tempReg0 , #$A2E1
    ret
 
NibbleShift:
    asl  tempReg0
    asl  tempReg0
    asl  tempReg0
    asl  tempReg0
    ret
 
DisplayDigit:
    load colCount , #4
    load rowCount , #4
    DoCol:
    out  tempReg0 , LOOKUPADDR
    in   numIn    , ROMDATA
    out  numIn    , numOffset
    add  tempReg0 , #1
    add  numOffset, #1
    sub  colCount , #1
    jpnz DoCol
    load colCount , #4
    DoRow:
    sub rowCount  , #1
    add numOffset , #$1C
    or  rowCount  , #0
    rtz
    jump DoCol
 
AMPM:
    load tempReg0 , AMPMReg1
    in   tempReg1 , HOUR
    stor tempReg1 , AMPMReg1
    comp tempReg0 , #%00010001
    rtnz
    comp tempReg1 , #%00010010
    rtnz
 
ToggleAMPM:
    xor  AMPMReg0 , #$00FF
    ret
 
AM:
    load tempReg1 , #$0A
    out  tempReg1 , A
    load tempReg1 , #$FF
    out  tempReg1 , B    
    ret
 
PM:
    load tempReg1 , #$FF
    out  tempReg1 , A
    load tempReg1 , #$19
    out  tempReg1 , B   
    ret
 
ClearClock:
    load startReg , #$A2FF
    load stopReg ,  #$A27F
    call ClearMessage
    ret
 
;Draw and clear on screen messages.
DoMessage:
    load swReg     , #$00
    load callReg   , #ClearDemoMessage
    load clearReg  , #DrawDemoMessage
    call DoZeroFunction    
    load swReg     , #$01
    load callReg   , #DrawTiledClockMessage
    load clearReg  , #ClearTiledClockMessage
    call DoFunction    
    load swReg     , #$02
    load callReg   , #DrawSpriteAudioMessage
    load clearReg  , #ClearSpriteAudioMessage
    call DoFunction    
    load swReg     , #$04
    load callReg   , #DrawBaseColorMessage
    load clearReg  , #ClearBaseColorMessage
    call DoFunction    
    load swReg     , #$08
    load callReg   , #DrawBouncingSpritesMessage
    load clearReg  , #ClearBouncingSpritesMessage
    call DoFunction    
    load swReg     , #$10
    load callReg   , #DrawAttributeTableMessage
    load clearReg  , #ClearAttributeTableMessage
    call DoFunction       
    load swReg     , #$20
    load callReg   , #DrawSpritePriorityMessage
    load clearReg  , #ClearSpritePriorityMessage
    call DoFunction    
    load swReg     , #$40
    load callReg   , #DrawPaletteChangeMessage
    load clearReg  , #ClearPaletteChangeMessage
    call DoFunction    
    load swReg     , #$80
    load callReg   , #DrawSpriteMirroringMessage
    load clearReg  , #ClearSpriteMirroringMessage
    call DoFunction
    ret
 
DrawDemoMessage:
    load mIndexReg , #$15
    load startReg  , #$A1F5
    load stopReg   , #$A1DF
    call DrawMessage
    ret    
 
ClearDemoMessage:
    load startReg , #$A1F5
    load stopReg  , #$A1DF
    call ClearMessage
    ret    
 
DrawTiledClockMessage:
    load mIndexReg, #$20
    load startReg , #$A20A
    load stopReg  , #$A1FF
    call DrawMessage
    ret
 
ClearTiledClockMessage:
    load startReg , #$A20A
    load stopReg  , #$A1FF
    call ClearMessage
    ret
 
DrawSpriteAudioMessage:
    load mIndexReg, #$2C
    load startReg , #$A21B
    load stopReg  , #$A20F
    call DrawMessage
    ret
 
ClearSpriteAudioMessage:
    load startReg , #$A21B
    load stopReg  , #$A20F
    call ClearMessage
    ret
 
DrawBaseColorMessage:
    load mIndexReg, #$36
    load startReg , #$A229
    load stopReg  , #$A21F
    call DrawMessage
    ret
 
ClearBaseColorMessage:
    load startReg , #$A229
    load stopReg  , #$A21F
    call ClearMessage
    ret
 
DrawBouncingSpritesMessage:
    load mIndexReg, #$46
    load startReg , #$A23F
    load stopReg  , #$A22F
    call DrawMessage
    ret
 
ClearBouncingSpritesMessage:
    load startReg , #$A23F
    load stopReg  , #$A22F
    call ClearMessage
    ret   
 
DrawAttributeTableMessage:
    load mIndexReg, #$55
    load startReg , #$A24E
    load stopReg  , #$A23F
    call DrawMessage
    ret
 
ClearAttributeTableMessage:
    load startReg , #$A24E
    load stopReg  , #$A23F
    call ClearMessage
    ret
 
DrawSpritePriorityMessage:
    load mIndexReg, #$64
    load startReg , #$A25E
    load stopReg  , #$A24F
    call DrawMessage
    ret
 
ClearSpritePriorityMessage:
    load startReg , #$A25E
    load stopReg  , #$A24F
    call ClearMessage
    ret
 
DrawPaletteChangeMessage:
    load mIndexReg, #$72
    load startReg , #$A26D
    load stopReg  , #$A25F
    call DrawMessage
    ret
 
ClearPaletteChangeMessage:
    load startReg , #$A26D
    load stopReg  , #$A25F
    call ClearMessage
    ret
 
DrawSpriteMirroringMessage:
    load mIndexReg, #$82
    load startReg , #$A27F
    load stopReg  , #$A26F
    call DrawMessage
    ret
 
ClearSpriteMirroringMessage:
    load startReg , #$A27F
    load stopReg  , #$A26F
    call ClearMessage
    ret
 
DrawMessage:
    out  mIndexReg, MESSAGETBL
    in   tempReg0 , ROMDATA
    out  tempReg0 , startReg
    sub  startReg , #1
    sub  mIndexReg, #1
    comp startReg , stopReg
    jpnz DrawMessage
    ret
 
ClearMessage:
    load mIndexReg, #$FF
    out  mIndexReg, startReg
    sub  startReg , #1
    comp startReg , stopReg
    jpnz ClearMessage
    ret
 
DoBaseColor:
    in   switchReg , SWITCHES
    and  switchReg , #$04
    comp switchReg , #$04
    clz  UpdateBaseColor
    comp switchReg , #$04
    clnz ClearBaseColor
    ret
 
UpdateBaseColor:
    add  bcDelReg  , #1
    comp bcDelReg  , #$20
    clz  IncrementBaseColor
    out  bcReg     , #$A700
    ret
 
IncrementBaseColor:
    add  bcReg     , #1
    load bcDelReg  , #0
    ret
 
ClearBaseColor:
    load bcReg     , #0
    out  bcReg     , #$A700
    load bcDelReg  , #0
    ret
 
DoBouncingSprites:
    load swReg     , #$08
    load callReg   , #UpdateBouncingSprites
    load clearReg  , #ClearBouncingSprites
    call DoFunction
    call DrawBouncingSprites
    ret
 
UpdateBouncingSprites:
    call CheckBouncingSpritesStart    
    load tempReg0 , #$20
    UpdateBouncingSpritesLoop:
    load tempReg3 , (tempReg0)
    comp tempReg3 , UPLEFT
    clz  MoveUpLeft
    comp tempReg3 , UPRIGHT
    clz  MoveUpRight
    comp tempReg3 , DOWNLEFT
    clz  MoveDownLeft
    comp tempReg3 , DOWNRIGHT
    clz  MoveDownRight    
    add  tempReg0 , #1
    comp tempReg0 , #$28
    jpnz UpdateBouncingSpritesLoop    
    ret
 
MoveUpRight:
    call CheckYMin
    comp checkReg , #1
    jpz  ChangeToDownRight
    call CheckXMax
    comp checkReg , #1
    jpz  ChangeToUpLeft
    load tempReg1 , tempReg0
    sub  tempReg1 , #8
    load tempReg2 , (tempReg1)
    add  tempReg2 , #1
    stor tempReg2 , (tempReg1)
    sub  tempReg1 , #8
    load tempReg2 , (tempReg1)
    sub  tempReg2 , #1
    stor tempReg2 , (tempReg1)
    ret
 
MoveUpLeft:
    call CheckYMin
    comp checkReg , #1
    jpz  ChangeToDownLeft
    call CheckXMin
    comp checkReg , #1
    jpz  ChangeToUpRight
    load tempReg1 , tempReg0
    sub  tempReg1 , #8
    load tempReg2 , (tempReg1)
    sub  tempReg2 , #1
    stor tempReg2 , (tempReg1)
    sub  tempReg1 , #8
    load tempReg2 , (tempReg1)
    sub  tempReg2 , #1
    stor tempReg2 , (tempReg1)
    ret
 
MoveDownRight:
    call CheckYMax
    comp checkReg , #1
    jpz  ChangeToUpRight
    call CheckXMax
    comp checkReg , #1
    jpz  ChangeToDownLeft
    load tempReg1 , tempReg0
    sub  tempReg1 , #8
    load tempReg2 , (tempReg1)
    add  tempReg2 , #1
    stor tempReg2 , (tempReg1)
    sub  tempReg1 , #8
    load tempReg2 , (tempReg1)
    add  tempReg2 , #1
    stor tempReg2 , (tempReg1)
    ret
 
MoveDownLeft:
    call CheckXMin
    comp checkReg , #1
    jpz  ChangeToDownRight
    call CheckYMax
    comp checkReg , #1
    jpz  ChangeToUpLeft
    load tempReg1 , tempReg0
    sub  tempReg1 , #8
    load tempReg2 , (tempReg1)
    sub  tempReg2 , #1
    stor tempReg2 , (tempReg1)
    sub  tempReg1 , #8
    load tempReg2 , (tempReg1)
    add  tempReg2 , #1
    stor tempReg2 , (tempReg1)
    ret
 
CheckYMin:
    load tempReg1 , tempReg0
    sub  tempReg1 , #16
    load tempReg2 , (tempReg1)
    comp tempReg2 , #0
    jpz  ExtentReached
    load checkReg , #0
    ret
 
CheckYMax:
    load tempReg1 , tempReg0
    sub  tempReg1 , #16
    load tempReg2 , (tempReg1)
    comp tempReg2 , #231
    jpz  ExtentReached
    load checkReg , #0
    ret
 
CheckXMin:
    load tempReg1 , tempReg0
    sub  tempReg1 , #8
    load tempReg2 , (tempReg1)
    comp tempReg2 , #0
    jpz  ExtentReached
    load checkReg , #0
    ret
 
CheckXMax:
    load tempReg1 , tempReg0
    sub  tempReg1 , #8
    load tempReg2 , (tempReg1)
    comp tempReg2 , #247
    jpz  ExtentReached
    load checkReg , #0
    ret
 
ExtentReached:
    load checkReg , #1
    ret
 
ChangeToDownRight:
    load tempReg1 , DOWNRIGHT
    stor tempReg1 , (tempReg0)
    ret
 
ChangeToDownLeft:
    load tempReg1 , DOWNLEFT
    stor tempReg1 , (tempReg0)
    ret
 
ChangeToUpRight:
    load tempReg1 , UPRIGHT
    stor tempReg1 , (tempReg0)
    ret
 
ChangeToUpLeft:
    load tempReg1 , UPLEFT
    stor tempReg1 , (tempReg0)
    ret
 
ClearBouncingSprites:
    load tempReg0 , #$0F
    load tempReg1 , #$FF
    YClearLoop:
    add  tempReg0 , #1
    stor tempReg1 , (tempReg0)
    comp tempReg0 , #$17
    jpnz YClearLoop
    ret
 
CheckBouncingSpritesStart:
    comp sp0y     , #$FF
    rtnz
    load sp0y     , #11
    load sp1y     , #22
    load sp2y     , #33
    load sp3y     , #44
    load sp4y     , #55
    load sp5y     , #66
    load sp6y     , #77
    load sp7y     , #88
    load sp0x     , #11
    load sp1x     , #22
    load sp2x     , #33
    load sp3x     , #44
    load sp4x     , #55
    load sp5x     , #66
    load sp6x     , #77
    load sp7x     , #88
    load sp0m     , DOWNRIGHT
    load sp1m     , DOWNRIGHT
    load sp2m     , DOWNRIGHT
    load sp3m     , DOWNRIGHT
    load sp4m     , DOWNRIGHT
    load sp5m     , DOWNRIGHT
    load sp6m     , DOWNRIGHT
    load sp7m     , DOWNRIGHT
    ret
 
DrawBouncingSprites:
    load tempReg0 , #$10
    load tempReg1 , #$B000
    FillYLoop:
    load tempReg2 , (tempReg0)
    out  tempReg2 , tempReg1
    add  tempReg0 , #1
    add  tempReg1 , #4
    comp tempReg0 , #$18
    jpnz FillYLoop
 
    load tempReg0 , #$18
    load tempReg1 , #$B003
    FillXLoop:
    load tempReg2 , (tempReg0)
    out  tempReg2 , tempReg1
    add  tempReg0 , #1
    add  tempReg1 , #4
    comp tempReg0 , #$20
    jpnz FillXLoop
 
    load tempReg0 , #$20
    load tempReg1 , #$B002
    FillMLoop:    
    load tempReg2 , (tempReg0)
    out  tempReg2 , tempReg1
    add  tempReg0 , #1
    add  tempReg1 , #4
    comp tempReg0 , #$28
    jpnz FillMLoop
 
    load tempReg0 , #$04
    load tempReg1 , #$B001
    FillPatternLoop:
    out  tempReg0 , tempReg1
    add  tempReg1 , #4
    comp tempReg1 , #$B021
    jpnz FillPatternLoop
    ret
 
DoPaletteChange:
    load swReg    , #$40
    load callReg  , #ChangePalettes
    load clearReg , #SetDefaultPalettes
    jump DoFunction
 
ChangePalettes:
    add  palDelReg, #1
    comp palDelReg, #$10
    rtnz
    load palDelReg, #0
    load tempReg0 , #$A600
    load tempReg2 , PALREGS
    ChangePalettesLoop:
    comp tempReg2 , #$30
    jpz  NextPalette
    comp tempReg2 , #$34
    jpz  NextPalette
    comp tempReg2 , #$38
    jpz  NextPalette
    comp tempReg2 , #$3C
    jpz  NextPalette
    comp tempReg2 , #$40
    jpz  NextPalette
    comp tempReg2 , #$44
    jpz  NextPalette
    comp tempReg2 , #$48
    jpz  NextPalette
    comp tempReg2 , #$4C
    jpz  NextPalette
    load tempReg1 , (tempReg2)
    add  tempReg1 , #1
    stor tempReg1 , (tempReg2)
    out  tempReg1 , tempReg0
    NextPalette:
    add  tempReg0 , #1
    add  tempReg2 , #1
    comp tempReg0 , #$A620
    jpnz ChangePalettesLoop
    ret
 
SetDefaultPalettes:
    load tempReg0 , #$A600
    load tempReg3 , PALREGS
    load tempReg1 , #0
    SetDefaultPalettesLoop:
    out  tempReg1 , PALETTETBL
    in   tempReg2 , ROMDATA
    out  tempReg2 , tempReg0
    stor tempReg2 , (tempReg3)
    add  tempReg1 , #1
    add  tempReg0 , #1
    add  tempReg3 , #1
    comp tempReg0 , #$A620
    jpnz SetDefaultPalettesLoop
    ret
 
;------------------------------------Sprite Mirroring Routines-------------------------------------
DoSpriteMirroring:
    load swReg    , #$80                            ;Switch 8 controls the sprite mirroring.
    load callReg  , #SpriteMirror                   ;Mirroring entry function.
    load clearReg , #ClearSpriteMirror              ;Clear mirroring sprites.
    jump DoFunction                                 ;
 
SpriteMirror:
    add  mirDelReg, #1                              ;
    comp mirDelReg, #$04                            ;Update mirroring sprites every 4th frame.
    rtnz                                            ;
 
    load tempReg0 , #$B020                          ;Set address to PPU mirroring sprite RAM.
 
    SpriteLoadLoop:
    out  mirPtrReg, SPRITETBL
    in   tempReg1 , ROMDATA
    out  tempReg1 , tempReg0
    add  mirPtrReg, #1
    add  tempReg0 , #1
    and  mirPtrReg, #$FF
    comp mirPtrReg, #$40
    jpz  FinishSpriteLoadLoop
    comp mirPtrReg, #$80
    jpz  FinishSpriteLoadLoop
    comp mirPtrReg, #$C0
    jpz  FinishSpriteLoadLoop
    comp mirPtrReg, #$00
    jpz  FinishSpriteLoadLoop
    jump SpriteLoadLoop    
    FinishSpriteLoadLoop:    
    load mirDelReg, #0  
    ret
 
ClearSpriteMirror:
    load tempReg0 , #$B020
    load tempReg1 , #$FF
    ClearSpriteMirrorLoop:
    out  tempReg1 , tempReg0    
    add  tempReg0 , #1
    comp tempReg0 , #$B060
    jpnz ClearSpriteMirrorLoop
    load mirDelReg, #0
    load mirPtrReg, #0   
    ret
 
;--------------------------------------Audio Sprite Routines---------------------------------------
DoSpriteAudio:
    load swReg    , #$02                            ;2nd switch controls audio sprites.
    load callReg  , #SpriteAudio                    ;Audio sprite entry function.
    load clearReg , #ClearSpriteAudio               ;Clear audio sprites function.
    jump DoFunction                                 ;
 
SpriteAudio:
    load tempReg0 , #$A000
    load tempReg1 , #$78
    AudioBackgroundTopLoop:
    out  tempReg1 , tempReg0
    add  tempReg0 , #1
    comp tempReg0 , #$A020
    jpnz AudioBackgroundTopLoop
    load tempReg1 , #$79
    AudioBackgroundMidLoop:
    out  tempReg1 , tempReg0
    add  tempReg0 , #1
    comp tempReg0 , #$A1A0
    jpnz AudioBackgroundMidLoop
    load tempReg1 , #$7A
    AudioBackgroundBotLoop:
    out  tempReg1 , tempReg0
    add  tempReg0 , #1
    comp tempReg0 , #$A1C0
    jpnz AudioBackgroundBotLoop
    call DisplayAudioSprites                        ;Draw audio sprites on the display.
    call DisplayMag                                 ;Draw magnification factor on display.
    ret                                             ;
 
ClearSpriteAudio:
    load tempReg1 , #$FF                            ;Blank sprite.
    load tempReg0 , #$A000                          ;
 
    ClearSpriteAudioLoop:
    out  tempReg1 , tempReg0
    add  tempReg0 , #1
    comp tempReg0 , #$A1C0
    jpnz ClearSpriteAudioLoop
 
    out  tempReg1 , tempReg0                        ;
    add  tempReg0 , #1                              ;Clear magnification factor from display.
    out  tempReg1 , tempReg0                        ;
    add  tempReg0 , #1                              ;
    out  tempReg1 , tempReg0                        ;
 
    load tempReg0 , PPUAUDSPSTART                   ;Base address in PPU sprite RAM.
    load tempReg1 , #$FF                            ;Move sprite off screen.
 
    RemoveAudioSprites:
    out  tempReg1 , tempReg0                        ;
    add  tempReg0 , #1                              ;Loop to write #$FF into all-->
    comp tempReg0 , PPUAUDSPEND                     ;audio sprite RAM.  This will-->
    jpnz RemoveAudioSprites                         ;move the sprites off screen.
    ret                                             ;
 
DisplayAudioSprites:
    load tempReg0 , PPUAUDSPSTART                   ;Base address in PPU sprite RAM.
    load tempReg1 , #0                              ;Sprite X location.
    load tempReg2 , SPRITEREGS                      ;Base address in CPU audio sprite RAM.
    load tempReg3 , #$A0                            ;Audio sprite pattern table address.
 
    DisplayAudioSpritesLoop:
    load miscReg  , (tempReg2)                      ;Get sprite audio data from CPU memory.
    xor  miscReg  , #$007F                          ;Compute proper positon on display.
    sub  miscReg  , #$10                            ;
    out  miscReg  , tempReg0                        ;Set sprite Y position in PPU RAM.
 
    add  tempReg0 , #1                              ;Set sprite pattern in PPU RAM.
    out  tempReg3 , tempReg0                        ;
 
    add  tempReg0 , #1                              ;Set property bit in PPU RAM.
    load miscReg  , #2                              ;No flipping, foreground sprite,-->
    out  miscReg  , tempReg0                        ;pallette %$10.
 
    add  tempReg0 , #1                              ;Store sprite X position in PPU RAM.
    out  tempReg1 , tempReg0                        ;
 
    add  tempReg2 , #1                              ;Move to next sprite in CPU memory.
    add  tempReg1 , #2                              ;Move x by 2 pixels for next sprite.
    add  tempReg0 , #1                              ;Move to next sprite in PPU RAM.
 
    comp tempReg0 , PPUAUDSPEND                     ;Check if more sprites to process(128 total).
    jpnz DisplayAudioSpritesLoop                    ;Loop if more sprites to process.
    ret                                             ;
 
DisplayMag:
    comp micSmpReg, #$0200
    jpnz Check02X
    load tempReg1 , #$78
    load tempReg2 , #$01
    load tempReg3 , #$21
 
    Check02X:
    comp micSmpReg, #$0100
    jpnz Check04X
    load tempReg1 , #$78
    load tempReg2 , #$02
    load tempReg3 , #$21    
 
    Check04X:
    comp micSmpReg, #$0080
    jpnz Check08X
    load tempReg1 , #$78
    load tempReg2 , #$04
    load tempReg3 , #$21    
 
    Check08X:
    comp micSmpReg, #$0040
    jpnz Check16X
    load tempReg1 , #$78
    load tempReg2 , #$08
    load tempReg3 , #$21    
 
    Check16X:
    comp micSmpReg, #$0020
    jpnz Check32X
    load tempReg1 , #$01
    load tempReg2 , #$06
    load tempReg3 , #$21  
 
    Check32X:
    comp micSmpReg, #$0010
    jpnz LoadMag
    load tempReg1 , #$03
    load tempReg2 , #$02
    load tempReg3 , #$21  
 
LoadMag:
    load tempReg0 , #$A000
    out  tempReg1 , tempReg0
    add  tempReg0 , #1
    out  tempReg2 , tempReg0
    add  tempReg0 , #1
    out  tempReg3 , tempReg0
    ret
 
GetAudioData:
    load micDelReg, #0                              ;Zero the mic delay register.
    load audPtrReg, SPRITEREGS                      ;Get base address of audio sprites RAM.
 
    in   audHldReg, MICDATA                         ;Get audio input data.
    asl  audHldReg                                  ;Check if mag button depressed.
    clc  MagChangeButtonPushed                      ;If so, change magnification.
 
    in   audHldReg, MICDATA
    asl  audHldReg
    clnc MagChangeButtonReleased
 
    GetAudioLoop:
    add  audCtrReg, #1                              ;Delay to for specified sampling time.
    comp audCtrReg, micSmpReg                       ;Check if tie for another sample.
    jpnz GetAudioLoop
    load audCtrReg, #0
 
    in   audHldReg, MICDATA                         ;Get audio data from port.
    and  audHldReg, #$0FFF                          ;Keep only audio data bits.
    lsr  audHldReg                                  ;
    lsr  audHldReg                                  ;Keep only upper 7 bits.
    lsr  audHldReg                                  ;
    lsr  audHldReg                                  ;
    lsr  audHldReg                                  ;
 
    sub  audHldReg, #8
    stor audHldReg, (audPtrReg)
    add  audPtrReg, #1
    comp audPtrReg, ENDAUDIOREGS
    jpnz GetAudioLoop
    load audPtrReg, #0
    ret
 
MagChangeButtonReleased:
    load micStaReg, #0
    ret
 
MagChangeButtonPushed:
    rol  micStaReg
    jpc  DebounceDone
    load micStaReg, #$8000
    ret
 
DebounceDone:
    ror  micStaReg
    ror  micStaReg
    clnc ChangeMag
    load micStaReg, #$8001
    ret
 
ChangeMag:
    comp micSmpReg, #$0200                          ;If at 1x magnification, -->
    jpz  ChangeTo2X                                 ;change to 2x magnification.
 
    comp micSmpReg, #$0100                          ;If at 2x magnification, -->
    jpz  ChangeTo4X                                 ;change to 4x magnification.
 
    comp micSmpReg, #$0080                          ;If at 4x magnification, -->
    jpz  ChangeTo8X                                 ;change to 8x magnification.
 
    comp micSmpReg, #$0040                          ;If at 8x magnification, -->
    jpz  ChangeTo16X                                ;change to 16x magnification.
 
    comp micSmpReg, #$0020                          ;If at 16x magnification, -->
    jpz  ChangeTo32X                                ;change to 32x magnification.
 
    comp micSmpReg, #$0010                          ;If at 32x magnification, -->
    jump ChangeTo1X                                 ;change to 1x magnification.
 
ChangeTo1X:
    load micSmpReg, #$0200                          ;Change to 1x magnification.
    ret                                             ;
ChangeTo2X:
    load micSmpReg, #$0100                          ;Change to 2x magnification.
    ret                                             ;
ChangeTo4X:
    load micSmpReg, #$0080                          ;Change to 4x magnification.
    ret                                             ;
ChangeTo8X:
    load micSmpReg, #$0040                          ;Change to 8x magnification.
    ret                                             ;
ChangeTo16X:
    load micSmpReg, #$0020                          ;Change to 16x magnification.
    ret                                             ;
ChangeTo32X:
    load micSmpReg, #$0010                          ;Change to 32x magnification.
    ret                                             ;
;--------------------------------------------------------------------------------------------------
 
DoAttribChange:
    load swReg    , #$10
    load callReg  , #AttributeTable
    load clearReg , #ClearAttributeTable
    jump DoFunction
 
AttributeTable:
    add  atDelReg , #1
    comp atDelReg , #8
    rtnz
    load atDelReg , #0
    add  atStatReg, #1
    comp atStatReg, #4
    clz  ResetAttributeReg
    load tempReg0 , #$A580
    SetAttributeTableLoop:
    comp atStatReg, #0
    jpnz NextCheck1
    load tempReg1 , AT0    
    NextCheck1:
    comp atStatReg, #1
    jpnz NextCheck2
    load tempReg1 , AT1
    NextCheck2:
    comp atStatReg, #2
    jpnz NextCheck3
    load tempReg1 , AT2
    NextCheck3:
    comp atStatReg, #3
    jpnz FinishCheck
    load tempReg1 , AT3    
    FinishCheck:
    out  tempReg1, tempReg0
    add  tempReg0 , #1    
    comp tempReg0 , #$A5A0
    jpnz SetAttributeTableLoop
    ret
 
ResetAttributeReg:
    load atStatReg, #0
    ret
 
ClearAttributeTable:
    load tempReg0 , #$A580
    load tempReg1 , #0
    ClearAttributeTableLoop:
    out  tempReg1 , tempReg0
    add  tempReg0 , #1    
    comp tempReg0 , #$A5A0
    jpnz ClearAttributeTableLoop
    ret
 
DoSpritePriority:
    load swReg    , #$20
    load callReg  , #UpdateSpritePriority
    load clearReg , #ClearSpritePriority
    jump DoFunction
 
    ;anDelReg, samROMReg, samXReg, movDelReg
    ;samM0Reg, samM1Reg, samM2Reg
 
UpdateSpritePriority:
    load tempReg0 , #$A33F
    load tempReg1 , #$7C
    DrawPillarsLoop:
    add  tempReg0 , #3
    out  tempReg1 , tempReg0
    add  tempReg0 , #1
    out  tempReg1 , tempReg0
    comp tempReg0 , #$A3BF
    jpnz DrawPillarsLoop
 
    add anDelReg  , #1
    add movDelReg , #1
 
    call CheckSamusMovement
    call CheckSamusAnimation
 
    DrawSamus:
    load tempReg0 , #$B0D0
    load tempReg1 , samROMReg
 
    GetSamusROMLoop:
    out  tempReg1 , PALETTETBL
    in   tempReg2 , ROMDATA
    out  tempReg2 , tempReg0
    add  tempReg0 , #1
    add  tempReg1 , #1
    out  tempReg1 , PALETTETBL
    in   tempReg2 , ROMDATA
    out  tempReg2 , tempReg0
    add  tempReg0 , #3
    add  tempReg1 , #1
    comp tempReg0 , #$B100
    jpnz GetSamusROMLoop
 
    load tempReg0 , samXReg
 
    LoadSamusMX:
    out  samM0Reg , #$B0D2
    out  tempReg0 , #$B0D3
    out  samM0Reg , #$B0DA
    out  tempReg0 , #$B0DB
    out  samM0Reg , #$B0E2
    out  tempReg0 , #$B0E3
    out  samM0Reg , #$B0EE
    out  tempReg0 , #$B0EF
 
    add  tempReg0 , #8
 
    out  samM1Reg , #$B0D6
    out  tempReg0 , #$B0D7
    out  samM1Reg , #$B0DE
    out  tempReg0 , #$B0DF
    out  samM1Reg , #$B0E6
    out  tempReg0 , #$B0E7
    out  samM1Reg , #$B0F2
    out  tempReg0 , #$B0F3
 
    add  tempReg0 , #8
 
    out  samM2Reg , #$B0EA
    out  tempReg0 , #$B0EB
    out  samM2Reg , #$B0F6
    out  tempReg0 , #$B0F7
 
    ret
 
CheckSamusMovement:
    comp movDelReg, #2
    jpz  UpdateSamusPosition
    ret
 
CheckSamusAnimation:
    comp anDelReg , #8
    jpz  UpdateSamusAnimation
    ret
 
UpdateSamusAnimation:
    add  samROMReg, #$18
    comp samROMReg, #$A0
    clz  ResetSamusROMReg
    load anDelReg , #0
    ret
 
ResetSamusROMReg:
    load samROMReg, #$40
    ret
 
UpdateSamusPosition:
    load movDelReg, #0
    sub  samXReg  , #1
    and  samXReg  , #$FF
 
    load tempReg0 , samXReg
 
    comp tempReg0 , #$20
    clz  SwitchM0Priority
    comp tempReg0 , #$40
    clz  SwitchM0Priority
    comp tempReg0 , #$60
    clz  SwitchM0Priority
    comp tempReg0 , #$80
    clz  SwitchM0Priority
    comp tempReg0 , #$A0
    clz  SwitchM0Priority
    comp tempReg0 , #$C0
    clz  SwitchM0Priority
    comp tempReg0 , #$E0
    clz  SwitchM0Priority
 
    add  tempReg0 , #8
 
    comp tempReg0 , #$20
    clz  SwitchM1Priority
    comp tempReg0 , #$40
    clz  SwitchM1Priority
    comp tempReg0 , #$60
    clz  SwitchM1Priority
    comp tempReg0 , #$80
    clz  SwitchM1Priority
    comp tempReg0 , #$A0
    clz  SwitchM1Priority
    comp tempReg0 , #$C0
    clz  SwitchM1Priority
    comp tempReg0 , #$E0
    clz  SwitchM1Priority
 
    add  tempReg0 , #8
 
    comp tempReg0 , #$20
    clz  SwitchM2Priority
    comp tempReg0 , #$40
    clz  SwitchM2Priority
    comp tempReg0 , #$60
    clz  SwitchM2Priority
    comp tempReg0 , #$80
    clz  SwitchM2Priority
    comp tempReg0 , #$A0
    clz  SwitchM2Priority
    comp tempReg0 , #$C0
    clz  SwitchM2Priority
    comp tempReg0 , #$E0
    clz  SwitchM2Priority
 
    ret
 
SwitchM0Priority:
    xor  samM0Reg , #$20
    ret
 
SwitchM1Priority:
    xor  samM1Reg , #$20
    ret
 
SwitchM2Priority:
    xor  samM2Reg , #$20
    ret
 
ClearSpritePriority:
    load tempReg0 , #$A320
    load tempReg1 , #$FF
    ClearPillarsLoop:
    out  tempReg1 , tempReg0
    add  tempReg0 , #1
    comp tempReg0 , #$A3C0    
    jpnz ClearPillarsLoop
    load tempReg0 , #$B0D0
    ClearWalkingSpritesLoop:
    out  tempReg1 , tempReg0    
    add  tempReg0 , #1
    comp tempReg0 , #$B100
    jpnz ClearWalkingSpritesLoop
    load samROMReg, #$40
    load samXReg  , #$E5
    load samM0Reg , #$03
    load samM1Reg , #$03
    load samM2Reg , #$03
    ret


NMPSM3.jar (Download)

NMPSM3.jar (Download)


NMPSM3.bat
java -jar NMPSM3.jar program.asm
@echo off
pause


program.coe
memory_initialization_radix = 16;
memory_initialization_vector =
100000005100000028100000038100000052100000052230000022,2300001FE,230000262230000035230000050,010950080,0106D0040,0106E00E5,010900003,010910003,010920003,
010590011,010500005,530500010530500011,0118000D9,531800200,A60000000,A90000000,
AC0000000,8C0040001,190000019,B90000000,010040001,6C0930001,8C0930003,2C00002F4,
AC0000000,100000019,0100003FF,010010000,0D0010000,7900000011600000243.6530010001,4C0500012,600500000,2C0000035,530010001,4C0500012,5305000105.3亿,
4C0500012, 530500020、6C0010001、6C0000001、460460、010000000、010010000、360000000,
8C0020020,2C0000050,040500002,010520024,23000004A,6C0500001,010520025,23000004A,
6C0500001,010520026,23000004A,6C0500001,010520027,23000004A,0105000B0,530500011,
6C0020001,4.6亿,530500002,4C0510012,530510003,4C0510012,5605100523.6亿,
010020000, 3.6亿,010040000,2300000E8,230000073,23000016C,23000017F,23000023F,
23000026F,2300002912300003312300003572300000674.6亿,4C0030013,5C003006B,
90003006B,190000063100000064130690000,1306A0000,4C0030013,100000060,23000006A,
2300000713.6亿, 4C1810003、8C1810000、3C0000000、531810021531810201531810204、10000006A,
530500202360000000、0106B0001、010690077、0106A00E4、10000005E,4C0500033,
600500000,29000009D,600500000,2C00000A3,4C0500032,5905000F0,2900000A9,5905000F0,
2C00000B5,4C0500030,2300000BD,01057A29B,2300000C2,4C0500030,5905000F0,01057A296,
2300000C2,4C0500031,2300000BD,01057A28F,2300000C2,4C0500031,5905000F0,01057A28A,
2300000C2, 4C0500032,2300000BD,01057A283,2300000C2,2300000D1,040500058,8C0500000,
2C00000DA,040500058,8C0500000,2900000DF,3.6亿,01050006F,53050A288,53050A294,
53050A2E8,53050A2F4,3.6亿,0105000FF,53050A288,53050A294,53050A2E8,53050A2F4,
3.6亿,010500044, 53050A280,01050004D,
53050A281,010500050,53050A2A0,010500047,53050A2A1,53050A2C1,010500055,53050A2E1,360000000,0105000FF,53050A280,53050A281,
53050A2A0,53050A2A1,53050A2C1,53050A2E1,3.6亿,9305000009305000009305000009305000003.6亿,010540004,010550004,530500004,4C0560012,560560057,6C0500001,
6C0570001,790540001,1600000C4,010540004,790550001,6C057001C,600550000,3C0000000,
1000000C4, 040500059,4C0510032,0A0510059,8C0500011,3.9亿,8C0510012,3.9亿,
6605800FF,3.6亿,01051000A,530510041,0105100FF,5305100423.6亿,0105100FF,
530510041,010510019,5305100423.6亿,0105AA2FF,0105BA27F,2300001663.6亿,
0106B0000,010690112, 0106A010D,230000065、0106B0001、010690116、0106A011B,23000005E,
0106B0002、01069011F,0106A0124、23000005E,0106B0004、010690128、0106A012D,23000005E,
0106B0008,010690131,0106A0136,23000005E,0106B0010,01069013A,0106A013F,23000005E,
0106B0020,010690143,0106A0148,23000005E,0106B0040,01069014C,0106A0151,23000005E,
0106B0080,010690155,0106A015A,23000005E,3.6亿,0105C0015,0105AA1F5,0105BA1DF,
23000015E, 360000000、0105AA1F5、0105BA1DF,230000166360000000、0105C0020、0105AA20A,0105BA1FF,23000015E,360000000、0105AA20A,
0105BA1FF
,230000166360000000、0105C002C,0105AA21B,0105BA20F,
23000015E,360000000、0105AA2000, 0105BA21F,23000015E,
360000000、0105AA229、0105BA21F,230000166360000000、0105C0046、0105AA23F,0105BA22F,23000015E,360000000、0105AA23F,0105BA22F,
2300001663.6亿,0105C0055,0105AA24E,0105BA23F,23000015E,3.6亿,0105AA24E,
0105BA23F,2300001663.6亿,0105C0064,0105AA25E,0105BA24F,23000015E,3.6亿,
0105AA25E,0105BA24F,2300001663.6亿,0105C0072,0105AA26D,0105BA25F,23000015E,
3.6亿, 0105AA26D,0105BA25F,2300001663.6亿,0105C0082,0105AA27F,0105BA26F,
23000015E,3.6亿,0105AA27F,0105BA26F,2300001663.6亿,5305C0005,4C0500012,
56050005A,7905A0001,7905C0001,9005A005B,16000015E,3.6亿,0105C00FF,5605C005A,
7905A0001,9005A005B, 160000166360000000、4C0030013、590030004、8C0030004、2C0000173、8C0030004、29000017B,
360000000、6C05D0001、8C05D0020、2C0000178、5305EA700、360000000,
6C05E0001,0105D0000,3.6亿,0105E0000,5305EA700,0105D0000,3.6亿,0106B0008,
010690185,0106A01FE,23000005E,2300002203.6亿,230000205,010500020,070530050,
8C0530060,2C00001A4,8C0530020,2C0000194,8C05300E0,2C00001C4,8C05300A0,2C00001B4,
6C0500001, 8C0500028,1600001873.6亿,2300001D4,8C05F0001,1900001F2,2300001E9,
8C05F0001,1900001FB,040510050,790510008,070520051,6C0520001,0D0520051,790510008,
070520051,790520001,0D0520051,3.6亿,2300001D4,8C05F0001,1900001F5,2300001E2,
8C05F0001,1900001F8, 040510050、790510008、070520051、790520001、0D0520051、790510008、070520051、790520001、0D0520051、360000000、2300001DB
,8C05F0001、1900001F8、2300001E9,
8C05F0001,1900001F5,040510050,790510008,070520051,6C0520001,0D0520051,790510008,
070520051,6C0520001,0D0520051,3.6亿,2300001E2,8C05F0001,1900001F2,2300001DB,
8C05F0001,1900001FB,040510050,790510008,070520051,790520001,0D0520051,790510008,
070520051, 6C0520001,0D0520051,3.6亿,040510050,790510010,070520051,8C0520000,
1900001F0,0105F0000,3.6亿,040510050,790510010,070520051,8C05200E7,1900001F0,
0105F0000,3.6亿,040510050,790510008,070520051,8C0520000,1900001F0,0105F0000,
3.6亿,040510050, 790510008、070520051、8C05200F7、1900001F0、0105F0000、360000000、0105F0001、360000000、0105100A0、0D0510050、360000000、0105100E0、0D0510050、360000000
,
010510020,0D0510050,3.6亿,010510060,0D0510050,3.6亿,01050000F,0105100FF,
6C0500001,0D0510050,8C0500017,1600002003.6亿,8C01000FF,3.9亿,01010000B,
010110016,010120021,01013002C,010140037,010150042,01016004D,010170058,01018000B,
010190016, 0101A0021,0101B002C,0101C0037,0101D0042,0101E004D,0101F0058,0102000A0,
0102100A0,0102200A0,0102300A0,0102400A0,0102500A0,0102600A0,0102700A0,3.6亿,
010500010,01051B000,070520050,560520051,6C0500001,6C0510004,8C0500018,160000222,
010500018,01051B003, 070520050、560520051、6C0500001、6C0510004、8C0500020、16000022A
,010500020、01051B002、070520050、560520051、6C0500001、6C0510004、8C0500028、160000232,
010500004,01051B001,560500051,6C0510004,8C051B021,16000023A,3.6亿,0106B0040,
010690243,0106A0262,10000005E,6C0600001,8C0600010,3.9亿,010600000,01050A600,
010520030,8C0520030,19000025D,8C0520034,19000025D,8C0520038,19000025D,8C052003C,
19000025D, 8C0520040,19000025D,8C0520044,19000025D,8C0520048,19000025D,8C052004C,
19000025D,070510052,6C0510001,0D0510052,560510050,6C0500001,6C0520001,8C050A620,
1600002493.6亿,01050A600,010530030,010510000,530510006,4C0520012,560520050,
0D0520053,6C0510001, 6C0500001、6C0530001、8C050A620、160000265360000000、0106B0080、010690273、0106A0288、10000005E
,6C0610001、8C0610004、390000000、0150B020、530620007,
4C0510012,560510050,6C0620001,6C0500001,5906200FF,8C0620040,190000286,8C0620080,
190000286,8C06200C0,190000286,8C0620000,190000286100000277,010610000,3.6亿,
01050B020,0105100FF,560510050,6C0500001,8C050B060,16000028A,010610000,010620000,
3.6亿, 0106B0002,010690295,0106A02A8,10000005E,01050A000,010510078,560510050,
6C0500001,8C050A020,160000297,010510079,560510050,6C0500001,8C050A1A0,16000029C,
01051007A,560510050,6C0500001,8C050A1C0,1600002A1,2300002BA,2300002CF,3.6亿,
0105100FF,01050A000, 560510050、6C0500001、8C050A1C0、1600002AA,
560510050、6C0500001、560510050、6C0500001、560510050、01050B100、0105100FF,560510050、6C0500001、8C050B300,
1600002B5,3.6亿,01050B100,010510000,010520100,0105300A0,070660052,66066007F,
790660010560660050,6C0500001,560530050,6C0500001,010660002,560660050,6C0500001,
560510050,6C0520001,6C0510002,6C0500001,8C050B300,1600002BE,3.6亿,8C0950200,
1600002D4, 010510078,010520001,010530021,8C0950100,1600002D9,010510078,010520002,
010530021,8C0950080,1600002DE,010510078,010520004,010530021,8C0950040,1600002E3,
010510078,010520008,010530021,8C0950020,1600002E8,010510001,010520006,010530021,
8C0950010,1600002ED, 010510003,010520002,010530021,01050A000,560510050,6C0500001,
560520050,6C0500001,5605300503.6亿,010930000,010630100,4C0650034,930650000330000310,4C0650034,930650000,30000030E,6C0640001,900640095,1600002FC,010640000,
4C0650034,590650FFF,990650000990650000990650000990650000990650000790650008,
0D0650063,6C0630001,8C0630180,1600002FC,010630000,3.6亿,010940000,3.6亿,
960940000200000314,010948000,3.6亿,9C0940000,9C0940000,300000319,010948001,
3.6亿,8C0950200,190000327,8C0950100,190000329,8C0950080,19000032B,8C0950040,
19000032D,8C0950020,19000032F,8C0950010,100000325,010950200,3.6亿,010950100,
3.6亿,010950080, 3.6亿,010950040,3.6亿,010950020,3.6亿,010950010,
3.6亿,0106B0010,010690335,0106A0350,10000005E,6C0670001,8C0670008,3.9亿,
010670000,6C0680001,8C0680004,2C000034E,01050A580,8C0680000,160000340,01051001B,
8C0680001,160000343,0105100C6,8C0680002,160000346,0105100B1,8C0680003,160000349,
01051006C,560510050,6C0500001,8C050A5A0,16000033D,3.6亿,010680000,3.6亿,
01050A580, 010510000,560510050,6C0500001,8C050A5A0,1600003523.6亿,0106B0020,
01069035B,0106A03D1,10000005E,01050A33F,01051007C,6C0500003,560510050,6C0500001,
560510050,8C050A3BF,16000035D,6C06C0001,6C06F0001,23000038D,230000390,01050B0D0,
04051006D,530510006, 4C0520012、560520050、6C0500001、6C0510001、530510006、4C0520012、560520050、6C0500003、6C0510001、8C050B100、160000369、04050006E
,53090B0D2、53050B0D3,
53090B0DA,53050B0DB,53090B0E2,53050B0E3,53090B0EE,53050B0EF,6C0500008,53091B0D6,
53050B0D7,53091B0DE,53050B0DF,53091B0E6,53050B0E7,53091B0F2,53050B0F3,6C0500008,
53092B0EA,53050B0EB,53092B0F6,53050B0F7,3.6亿,8C06F0002,19000039A,3.6亿,
8C06C0008, 190000393360000000、6C06D0018、8C06D00A0、2C0000398、0106C0000、360000000、0106D0040、360000000、0106F0000、7906E0001、5906E00FF,04050006E,8C0500020、2C00003CB,8C0500040、2C00003CB,8C0C0C,
0C0C0C,0C0C0C,0C0C0C,
0C0C0C,0C0C0C,0C0C0C,0C0C0C,0C0C0C,0C0C0C,0C0C0C,0C0C0C,
0C0C0C,0C0C0C0C05000C 8C05000E0、2C00003CB,6C0500008、8C0500020、2C00003CD,8C0500040、2C00003CD,
8C0500060、2C00003CD,8C0500080、2C00003CD,8C05000A0、2C00003CD,8C05000C0,
2C00003CD,8C05000E0,2C00003CD,6C0500008,8C0500020,2C00003CF,8C0500040,2C00003CF,
8C0500060,2C00003CF,8C0500080,2C00003CF,8C05000A0,2C00003CF,8C05000C0,2C00003CF,
8C05000E0,2C00003CF,3.6亿,6609000203.6亿,6609100203.6亿,6609200203.6亿, 01050A320,0105100FF,560510050,6C0500001,8C050A3C0,1600003D3,01050B0D0,
560510050,6C0500001,8C050B100,1600003D8,0106D0040,0106E00E5,010900003,010910003,
010920003,3.6亿,000000000,000000000,000000000,000000000,000000000,000000000,
000000000,000000000, 000000000,000000000,000000000,000000000,000000000,000000000,
000000000,000000000,000000000,000000000,000000000,000000000,000000000,000000000,
000000000,000000000,000000000,000000000,000000000,000000000,000000000,000000000;