差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
nmpsm3软处理器 [2020/07/23 11:21]
zili
nmpsm3软处理器 [2020/07/23 14:06] (当前版本)
zili
行 23: 行 23:
 \\ \\
 #### NMPSM3硬件 #### NMPSM3硬件
 +与处理器一起,我还基于8位Nintendo构建了其他一些模块,包括UART和图片处理单元(PPU)。一些Verilog代码很粗糙,因为在创建此项目时我正在学习Verilog。\\
 +
 +##### Final_Project.v  ​
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +##### NMPSM3.v  ​
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +#####  VGA.v  ​
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +##### uart.v  ​
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +##### ROMcontroller.v ​
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +##### MControl.v ​
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +#####  ClockControl.v ​  
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +##### dataMUX.v ​   ​
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +##### div100k.v ​
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +##### FF.v
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +##### ledio.v  ​
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +#####  LEDIO2.v
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +#####  seg7io.v
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +#####  timer.v
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +#####  timer1.v  ​
 +<code verilog>
 +
 +`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
 +
 +</​code> ​
 +\\
 +
 +#####  lookupROM.coe
 +<code verilog>
 +
 +memory_initialization_radix = 16;
 +memory_initialization_vector =
 +
 +; LEDTbl($ 000)
 +01,02,04,08,10,20,40,80,40,20,10,08,04,02,01,02,
 +04,08,10,20,40,80,40 ,
 +20,10,08,04,02,01,02,04,08,10,20,40,80,40,20,10,08,04,02,01,02,04,08,10,20 ,
 +40、80、40、20、10、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($ 100)
 +50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
 +50,50,50,50,50,50,50 ,50,50,50,50,50,50,50,50,50,
 +50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50 ,
 +50、50、50、50、50、50、50、50、50,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,18,16,如图1A所示,10,
 +23,23,23,00,01,02,03 ,
 +04,05,06,07,08,09,23,23,23,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,67,77,5F,图7C,39,58,如图5E所示,
 +79,7B,71,6F,76,74,04 ,1E,38、37、54、5C,73、31、50、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,46,46,4D,56,51,50,47,56,41,40,47,5C,57,57,5D,;​
 +1
 +FF,44,4D,FF,FF ,50,47,FF,FF,FF,47,FF,FF,FF,55,FF,;​
 +2
 +44,46,46,4D,4E,61,4A,59,48,5B,60,5F,5C ,57,57,72,;​
 +3
 +44,46,46,4D,62,61,4A,59,63,60,5A,49,54,57,57,5D,;​
 +4
 +70,64,65,66 ,67,68,69,6A,6B,60,6C,6D,FF,FF,71,6E,;​
 +5
 +73,46,46,45,74,61,61,4F,63,60,5A,49 ,54、57、57、5D,;​
 +6
 +4C,46、46、45、56、42、61、4F,56、52、5A,49、5C,57、57、5D,;​
 +7
 +44,46、46 ,4D,FF,FF,50、47,FF,FF,FF,47,FF,FF,FF,55,;​
 +8
 +4C,46、46、4D,58、4B,4A,59、48、5B,5A ,49、5C,57、57、5D,
 +; 9
 +4C,46、46、4D,58、4B,43、47、5E,60、53、47、54、57、57、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,16、18、17、1C,1D,1B,0A,
 +1D,12、18、17C ,3F,
 +;($ 516)
 +;​平时时钟
 +1D,12,15,0E ,0D,FF,0C,15,18,0C ,14,
 +;($ 521)
 +; SPRITE AUDIO
 +1C,19,1B ,12,1 ,D ,0E ,FF,0A,1E,0D,
 +12,18 ,;($ 52D)
 +;基色
 +0B,0A,1C,0E,FF,0C,18,15,18,1B ,
 +;($ 537)
 +;弹跳
 +0B, 18,1E,17,0C,12,17,10,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,12,18,1B,12, 1D,22,
 +;($ 565)
 +;​调色板更改19,0A ,15,0E
 +,1D,1D,0E,FF,0C,11,0A ,17,10,0E ,
 +;($ 573)
 +; SPRITE MIRRORING
 +1C,19,1B ,12, 1D,0E,FF,16,12,1B,1B,18,1B,12,17,10
 +;($ 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、38、20、18、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,81、28,C0、9F,81、30,C8 ,9C,81、28,C8、9D,
 +81、30,C0、9D,41、78,C0、9C,41、80,C8、9F,41、78,C8、9E,
 +41、80,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,41、28,C0、9C,41、30,C8、9F,41、28,C8、9E,
 +41、30,C0、9E, 81、78,C0、9F,81、80,C8、9C,81、78,C8、9D,
 +81、80,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;
 +
 +</​code> ​
 +\\
 +
 +#### NMPSM3汇编程序
 +还为NMPSM3编写了汇编程序。它是一个基本的汇编器,但运行良好,已被用于在多个FPGA项目上为NMPSM3编写代码。\\
 +
 +##### NMPSM3.java
 +<code verilog>
 +
 +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);​
 +    }
 +}
 +
 +</​code> ​
 +\\
 +
 +#### NMPSM3软件
 +下面的第一个文件是控制项目的汇编语言程序。下一个文件是汇编器的编译版本。第三个文件是一个简单的批处理文件,它运行汇编程序并将NMPSM3代码汇编为.coe文件。\\
 +
 +##### program.asm
 +<code verilog>
 +
 +.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
 +
 +</​code> ​
 +\\
 +
 +##### NMPSM3.jar (Download)
 +[[https://​www.nicholasmikstas.com/​s/​NMPSM3.jar|NMPSM3.jar (Download)]]
 +\\
 +
 +\\
 +##### NMPSM3.bat
 +<code verilog>
 +
 +java -jar NMPSM3.jar program.asm
 +@echo off
 +pause
 +
 +</​code> ​
 +\\
 +
 +##### program.coe
 +<code verilog>
 +
 +memory_initialization_radix = 16;
 +memory_initialization_vector =
 +100000005,100000028,100000038,100000052,100000052,230000022,2300001FE,230000262,
 +230000035,230000050,010950080,0106D0040,0106E00E5,010900003,010910003,010920003,
 +010590011,010500005,530500010,530500011,0118000D9,531800200,A60000000,A90000000,
 +AC0000000,8C0040001,190000019,B90000000,010040001,6C0930001,8C0930003,2C00002F4,
 +AC0000000,100000019,0100003FF,010010000,0D0010000,790000001,160000024,3.6,
 +530010001,4C0500012,600500000,2C0000035,530010001,4C0500012,530500010,5.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,560510052,3.6亿,
 +010020000, 3.6亿,010040000,2300000E8,230000073,23000016C,23000017F,23000023F,
 +23000026F,230000291,230000331,230000357,230000067,4.6亿,4C0030013,5C003006B,
 +90003006B,190000063,100000064,130690000,1306A0000,4C0030013,100000060,23000006A,
 +230000071,3.6亿, 4C1810003、8C1810000、3C0000000、531810021、531810201、531810204、10000006A,
 +530500202、360000000、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亿,930500000,930500000,930500000,
 +930500000,3.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,530510042,3.6亿,0105100FF,
 +530510041,010510019,530510042,3.6亿,0105AA2FF,0105BA27F,230000166,3.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,230000166、360000000、0105C0020、0105AA20A,0105BA1FF,23000015E,360000000、0105AA20A,
 +0105BA1FF
 +,230000166、360000000、0105C002C,0105AA21B,0105BA20F,
 +23000015E,360000000、0105AA2000, 0105BA21F,23000015E,
 +360000000、0105AA229、0105BA21F,230000166、360000000、0105C0046、0105AA23F,0105BA22F,23000015E,360000000、0105AA23F,0105BA22F,
 +230000166,3.6亿,0105C0055,0105AA24E,0105BA23F,23000015E,3.6亿,0105AA24E,
 +0105BA23F,230000166,3.6亿,0105C0064,0105AA25E,0105BA24F,23000015E,3.6亿,
 +0105AA25E,0105BA24F,230000166,3.6亿,0105C0072,0105AA26D,0105BA25F,23000015E,
 +3.6亿, 0105AA26D,0105BA25F,230000166,3.6亿,0105C0082,0105AA27F,0105BA26F,
 +23000015E,3.6亿,0105AA27F,0105BA26F,230000166,3.6亿,5305C0005,4C0500012,
 +56050005A,7905A0001,7905C0001,9005A005B,16000015E,3.6亿,0105C00FF,5605C005A,
 +7905A0001,9005A005B, 160000166、360000000、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,230000220,3.6亿,230000205,010500020,070530050,
 +8C0530060,2C00001A4,8C0530020,2C0000194,8C05300E0,2C00001C4,8C05300A0,2C00001B4,
 +6C0500001, 8C0500028,160000187,3.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,160000200,3.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,
 +160000249,3.6亿,01050A600,010530030,010510000,530510006,4C0520012,560520050,
 +0D0520053,6C0510001, 6C0500001、6C0530001、8C050A620、160000265、360000000、0106B0080、010690273、0106A0288、10000005E
 +,6C0610001、8C0610004、390000000、0150B020、530620007,
 +4C0510012,560510050,6C0620001,6C0500001,5906200FF,8C0620040,190000286,8C0620080,
 +190000286,8C06200C0,190000286,8C0620000,190000286,100000277,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,
 +790660010,560660050,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,560530050,3.6亿,010930000,010630100,4C0650034,930650000,
 +330000310,4C0650034,930650000,30000030E,6C0640001,900640095,1600002FC,010640000,
 +4C0650034,590650FFF,990650000,990650000,990650000,990650000,990650000,790650008,
 +0D0650063,6C0630001,8C0630180,1600002FC,010630000,3.6亿,010940000,3.6亿,
 +960940000, 200000314,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,160000352,3.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, 190000393、360000000、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亿,660900020,3.6亿,660910020,3.6亿,660920020,
 +3.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;​
 +
 +</​code> ​
 +\\