diff --git a/LX9Co-6502fast.xise b/LX9Co-6502fast.xise index a12a024..7279295 100644 --- a/LX9Co-6502fast.xise +++ b/LX9Co-6502fast.xise @@ -16,52 +16,52 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -70,7 +70,7 @@ - + @@ -79,7 +79,7 @@ - + @@ -91,15 +91,15 @@ - + - + - + @@ -107,11 +107,35 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AlanD/R65Cx2.vhd b/src/AlanD/R65Cx2.vhd index c63583a..ea4e30a 100644 --- a/src/AlanD/R65Cx2.vhd +++ b/src/AlanD/R65Cx2.vhd @@ -23,8 +23,11 @@ entity R65C02 is irq_n : in std_logic; di : in unsigned(7 downto 0); do : out unsigned(7 downto 0); + do_next : out unsigned(7 downto 0); addr : out unsigned(15 downto 0); + addr_next : out unsigned(15 downto 0); nwe : out std_logic; + nwe_next : out std_logic; sync : out std_logic; sync_irq : out std_logic @@ -570,7 +573,6 @@ architecture Behavioral of R65C02 is ); signal opcInfo : decodedBitsDef; signal nextOpcInfo : decodedBitsDef; -- Next opcode (decoded) - signal nextOpcInfoReg : decodedBitsDef; -- Next opcode (decoded) pipelined signal theOpcode : unsigned(7 downto 0); signal nextOpcode : unsigned(7 downto 0); @@ -595,13 +597,16 @@ architecture Behavioral of R65C02 is nextAddrRelative ); signal nextAddr : nextAddrDef; + signal myAddrNext : unsigned(15 downto 0); -- DMB Lookahead output signal myAddr : unsigned(15 downto 0); signal myAddrIncr : unsigned(15 downto 0); signal myAddrIncrH : unsigned(7 downto 0); signal myAddrDecrH : unsigned(7 downto 0); + signal theWeNext : std_logic; -- DMB Lookahead output signal theWe : std_logic; signal irqActive : std_logic; -- Output register + signal doNext : unsigned(7 downto 0); -- DMB Lookahead output signal doReg : unsigned(7 downto 0); -- Buffer register signal T : unsigned(7 downto 0); @@ -703,7 +708,7 @@ processCmpInput: process(clk, opcInfo, A, X, Y) --hardware interrupts IRQ & NMI will push the B flag as being 0. -processAlu: process(clk, opcInfo, aluInput, aluCmpInput, A, T, irqActive, N, V, D, I, Z, C) +processAlu: process(clk, opcInfo, aluInput, aluCmpInput, A, T, irqActive, N, V, R, D, I, Z, C) variable lowBits: unsigned(5 downto 0); variable nineBits: unsigned(8 downto 0); variable rmwBits: unsigned(8 downto 0); @@ -848,14 +853,15 @@ processAlu: process(clk, opcInfo, aluInput, aluCmpInput, A, T, irqActive, N, V, when others => null; end case; - if rising_edge(clk) then +-- DMB Remove Pipelining +-- if rising_edge(clk) then aluRmwOut <= rmwBits(7 downto 0); aluRegisterOut <= ninebits(7 downto 0); aluC <= varC; aluZ <= varZ; aluV <= varV; aluN <= varN; - end if; +-- end if; end process; @@ -909,13 +915,6 @@ calcNextOpcode: process(clk, di, reset, processIrq) nextOpcInfo <= opcodeInfoTable(to_integer(nextOpcode)); - process(clk) - begin - if rising_edge(clk) then - nextOpcInfoReg <= nextOpcInfo; - end if; - end process; - -- Read bits and flags from opcodeInfoTable and store in opcInfo. -- This info is used to control the execution of the opcode. calcOpcInfo: process(clk) @@ -1293,53 +1292,70 @@ calcT: process(clk) -- ----------------------------------------------------------------------- -- Data out -- ----------------------------------------------------------------------- -calcDo: process(clk) +calcDoComb: process(nextCpuCycle, aluRmwOut, opcInfo(opcIRQ), irqActive, myAddrIncr, PC, di) + begin + doNext <= aluRmwOut; + case nextCpuCycle is + when cycleStack2 => if opcInfo(opcIRQ) = '1' and irqActive = '0' then + doNext <= myAddrIncr(15 downto 8); + else + doNext <= PC(15 downto 8); + end if; + when cycleStack3 => doNext <= PC(7 downto 0); + when cycleRmw => doNext <= di; -- Read-modify-write write old value first. + when others => null; + end case; + end process; + + -- DMB Lookahead data output + do_next <= doNext when enable = '1' else DoReg; + +calcDoReg: process(clk) begin if rising_edge(clk) then if enable = '1' then - doReg <= aluRmwOut; - case nextCpuCycle is - when cycleStack2 => if opcInfo(opcIRQ) = '1' and irqActive = '0' then - doReg <= myAddrIncr(15 downto 8); - else - doReg <= PC(15 downto 8); - end if; - when cycleStack3 => doReg <= PC(7 downto 0); - when cycleRmw => doReg <= di; -- Read-modify-write write old value first. - when others => null; - end case; + doReg <= doNext; end if; end if; end process; - do <= doReg; - + -- DMB Registered data output + do <= doReg; -- ----------------------------------------------------------------------- -- Write enable -- ----------------------------------------------------------------------- -calcWe: process(clk) +calcWeComb: process(nextCpuCycle, opcInfo(opcStackUp), opcInfo(opcStackAddr), opcInfo(opcStackData)) begin + theWeNext <= '1'; + case nextCpuCycle is + when cycleStack1 => + if opcInfo(opcStackUp) = '0' and ((opcInfo(opcStackAddr) = '0') or (opcInfo(opcStackData) = '1')) then + theWeNext <= '0'; + end if; + when cycleStack2 | cycleStack3 | cycleStack4 => + if opcInfo(opcStackUp) = '0' then + theWeNext <= '0'; + end if; + when cycleRmw => theWeNext <= '0'; + when cycleWrite => theWeNext <= '0'; + when others => null; + end case; + end process; + + -- DMB Lookahead we output + nwe_next <= theWeNext when enable = '1' else theWe; + +calcWeReg: process(clk) + begin if rising_edge(clk) then if enable = '1' then - theWe <= '1'; - case nextCpuCycle is - when cycleStack1 => - if opcInfo(opcStackUp) = '0' and ((opcInfo(opcStackAddr) = '0') or (opcInfo(opcStackData) = '1')) then - theWe <= '0'; - end if; - when cycleStack2 | cycleStack3 | cycleStack4 => - if opcInfo(opcStackUp) = '0' then - theWe <= '0'; - end if; - when cycleRmw => theWe <= '0'; - when cycleWrite => theWe <= '0'; - when others => null; - end case; + theWe <= theWeNext; end if; end if; - --nwe <= theWe; end process; + + -- DMB Registered we output nwe <= theWe; -- ----------------------------------------------------------------------- @@ -1462,43 +1478,54 @@ indexAlu: process(opcInfo, myAddr, T, X, Y) end if; end process; -calcAddr: process(clk) +calcAddrComb: process(myAddr, nextAddr, myAddrIncr, myAddrIncrH, myAddrDecrH, PC, nmiReg, di, theOpcode, indexOut, S, T, X) begin - if rising_edge(clk) then - if enable = '1' then - case nextAddr is - when nextAddrIncr => myAddr <= myAddrIncr; - when nextAddrIncrL => myAddr(7 downto 0) <= myAddrIncr(7 downto 0); - when nextAddrIncrH => myAddr(15 downto 8) <= myAddrIncrH; - when nextAddrDecrH => myAddr(15 downto 8) <= myAddrDecrH; - when nextAddrPc => myAddr <= PC; - when nextAddrIrq =>myAddr <= X"FFFE"; + myAddrNext <= myAddr; + case nextAddr is + when nextAddrIncr => myAddrNext <= myAddrIncr; + when nextAddrIncrL => myAddrNext(7 downto 0) <= myAddrIncr(7 downto 0); + when nextAddrIncrH => myAddrNext(15 downto 8) <= myAddrIncrH; + when nextAddrDecrH => myAddrNext(15 downto 8) <= myAddrDecrH; + when nextAddrPc => myAddrNext <= PC; + when nextAddrIrq =>myAddrNext <= X"FFFE"; if nmiReg = '0' then - myAddr <= X"FFFA"; + myAddrNext <= X"FFFA"; end if; - when nextAddrReset => myAddr <= X"FFFC"; - when nextAddrAbs => myAddr <= di & T; - when nextAddrAbsIndexed =>--myAddr <= di & indexOut(7 downto 0); + when nextAddrReset => myAddrNext <= X"FFFC"; + when nextAddrAbs => myAddrNext <= di & T; + when nextAddrAbsIndexed =>--myAddrNext <= di & indexOut(7 downto 0); if theOpcode = x"7C" then - myAddr <= (di & T) + (x"00"& X); + myAddrNext <= (di & T) + (x"00"& X); else - myAddr <= di & indexOut(7 downto 0); + myAddrNext <= di & indexOut(7 downto 0); end if; - when nextAddrZeroPage => myAddr <= "00000000" & di; - when nextAddrZPIndexed => myAddr <= "00000000" & indexOut(7 downto 0); - when nextAddrStack => myAddr <= "00000001" & S; - when nextAddrRelative => myAddr(7 downto 0) <= indexOut(7 downto 0); + when nextAddrZeroPage => myAddrNext <= "00000000" & di; + when nextAddrZPIndexed => myAddrNext <= "00000000" & indexOut(7 downto 0); + when nextAddrStack => myAddrNext <= "00000001" & S; + when nextAddrRelative => myAddrNext(7 downto 0) <= indexOut(7 downto 0); when others => null; - end case; + end case; + end process; + + -- DMB Lookahead address output + addr_next <= myAddrNext when enable = '1' else myAddr; + +calcAddrReg: process(clk) + begin + if rising_edge(clk) then + if enable = '1' then + myAddr <= myAddrNext; end if; end if; end process; - + myAddrIncr <= myAddr + 1; myAddrIncrH <= myAddr(15 downto 8) + 1; myAddrDecrH <= myAddr(15 downto 8) - 1; + + -- DMB Registered address output addr <= myAddr; - + -- DMB This looked plain broken and inferred a latch -- -- calcsync: process(clk) @@ -1514,8 +1541,8 @@ calcAddr: process(clk) sync <= '1' when theCpuCycle = opcodeFetch else '0'; - sync_irq <= irqActive; - + sync_irq <= irqActive; + end architecture; diff --git a/src/Arlet/ALU.v b/src/Arlet/ALU.v new file mode 100644 index 0000000..8d05fc0 --- /dev/null +++ b/src/Arlet/ALU.v @@ -0,0 +1,108 @@ +/* + * ALU. + * + * AI and BI are 8 bit inputs. Result in OUT. + * CI is Carry In. + * CO is Carry Out. + * + * op[3:0] is defined as follows: + * + * 0011 AI + BI + * 0111 AI - BI + * 1011 AI + AI + * 1100 AI | BI + * 1101 AI & BI + * 1110 AI ^ BI + * 1111 AI + * + */ + +module ALU( clk, op, right, AI, BI, CI, CO, BCD, OUT, V, Z, N, HC, RDY ); + input clk; + input right; + input [3:0] op; // operation + input [7:0] AI; + input [7:0] BI; + input CI; + input BCD; // BCD style carry + output [7:0] OUT; + output CO; + output V; + output Z; + output N; + output HC; + input RDY; + +reg [7:0] OUT; +reg CO; +wire V; +wire Z; +reg N; +reg HC; + +reg AI7; +reg BI7; +reg [8:0] temp_logic; +reg [7:0] temp_BI; +reg [4:0] temp_l; +reg [4:0] temp_h; +wire [8:0] temp = { temp_h, temp_l[3:0] }; +wire adder_CI = (right | (op[3:2] == 2'b11)) ? 0 : CI; + +// calculate the logic operations. The 'case' can be done in 1 LUT per +// bit. The 'right' shift is a simple mux that can be implemented by +// F5MUX. +always @* begin + case( op[1:0] ) + 2'b00: temp_logic = AI | BI; + 2'b01: temp_logic = AI & BI; + 2'b10: temp_logic = AI ^ BI; + 2'b11: temp_logic = AI; + endcase + + if( right ) + temp_logic = { AI[0], CI, AI[7:1] }; +end + +// Add logic result to BI input. This only makes sense when logic = AI. +// This stage can be done in 1 LUT per bit, using carry chain logic. +always @* begin + case( op[3:2] ) + 2'b00: temp_BI = BI; // A+B + 2'b01: temp_BI = ~BI; // A-B + 2'b10: temp_BI = temp_logic; // A+A + 2'b11: temp_BI = 0; // A+0 + endcase +end + +// HC9 is the half carry bit when doing BCD add +wire HC9 = BCD & (temp_l[3:1] >= 3'd5); + +// CO9 is the carry-out bit when doing BCD add +wire CO9 = BCD & (temp_h[3:1] >= 3'd5); + +// combined half carry bit +wire temp_HC = temp_l[4] | HC9; + +// perform the addition as 2 separate nibble, so we get +// access to the half carry flag +always @* begin + temp_l = temp_logic[3:0] + temp_BI[3:0] + adder_CI; + temp_h = temp_logic[8:4] + temp_BI[7:4] + temp_HC; +end + +// calculate the flags +always @(posedge clk) + if( RDY ) begin + AI7 <= AI[7]; + BI7 <= temp_BI[7]; + OUT <= temp[7:0]; + CO <= temp[8] | CO9; + N <= temp[7]; + HC <= temp_HC; + end + +assign V = AI7 ^ BI7 ^ CO ^ N; +assign Z = ~|OUT; + +endmodule diff --git a/src/Arlet/README b/src/Arlet/README new file mode 100644 index 0000000..dc2056b --- /dev/null +++ b/src/Arlet/README @@ -0,0 +1,67 @@ +======================================================== +A Verilog HDL version of the old MOS 6502 and 65C02 CPUs +======================================================== + +Original 6502 core by Arlet Ottens + +65C02 extensions by David Banks and Ed Spittles + +========== +6502 Core +========== + +Arlet's original 6502 core (cpu.v) is unchanged. + +Note: the 6502/65C02 cores assumes a synchronous memory. This means +that valid data (DI) is expected on the cycle *after* valid +address. This allows direct connection to (Xilinx) block RAMs. When +using asynchronous memory, I suggest registering the address/control +lines for glitchless output signals. + +Have fun. + +========== +65C02 Core +========== + +A second core (cpu_65c02.v) has been added, based on Arlet's 6502 +core, with additional 65C02 instructions and addressing modes: +- PHX, PHY, PLX, PLY +- BRA +- INC A, DEC A +- (zp) addressing mode +- STZ +- BIT zpx, absx, imm +- TSB/TRB +- JMP (,X) +- NOPs (optional) +- 65C02 BCD N/Z flags (optional, disabled) + +The Rockwell/WDC specific instructions (RMB/SMB/BBR/BBS/WAI/STP) are +not currently implemented + +The 65C02 core passes the Dormann 6502 test suite, and also passes the +Dormann 65C02 test suite if the optional support for NOPs and 65C02 +BCD flags is enabled. + +It has been tested as a BBC Micro "Matchbox" 65C02 Co Processor, in a +XC6SLX9-2 FPGA, running at 80MHz using 64KB of internel block RAM. It +just meets timing at 80MHz in this environment. It successfully runs +BBC Basic IV and Tube Elite. + +============ +Known Issues +============ + +The Matchbox Co Processor needed one wait state (via RDY) to be added +to each ROM access (only needed early in the boot process, as +eventually everything runs from RAM). The DIHOLD logic did not work +correctly with a single wait state, and so has been commented out. + +I now believe the correct fix is actually just: + +always @(posedge clk ) + if( RDY ) + DIHOLD <= DI; + +assign DIMUX = ~RDY ? DIHOLD : DI; diff --git a/src/Arlet/cpu_65c02.v b/src/Arlet/cpu_65c02.v new file mode 100644 index 0000000..a0f0c73 --- /dev/null +++ b/src/Arlet/cpu_65c02.v @@ -0,0 +1,1395 @@ +/* + * verilog model of 65C02 CPU. + * + * Based on original 6502 "Arlet 6502 Core" by Arlet Ottens + * + * (C) Arlet Ottens, + * + * Feel free to use this code in any project (commercial or not), as long as you + * keep this message, and the copyright notice. This code is provided "as is", + * without any warranties of any kind. + * + * Support for 65C02 instructions and addressing modes by David Banks and Ed Spittles + * + * (C) 2016 David Banks and Ed Spittles + * + * Feel free to use this code in any project (commercial or not), as long as you + * keep this message, and the copyright notice. This code is provided "as is", + * without any warranties of any kind. + * + */ + +/* + * Note that not all 6502 interface signals are supported (yet). The goal + * is to create an Acorn Atom model, and the Atom didn't use all signals on + * the main board. + * + * The data bus is implemented as separate read/write buses. Combine them + * on the output pads if external memory is required. + */ + +/* + * Two things were needed to correctly implement 65C02 NOPs + * 1. Ensure the microcode state machine uses an appropriate addressing mode for the opcode length + * 2. Ensure there are no side-effects (e.g. register updates, memory stores, etc) + * + * If IMPLEMENT_NOPS is defined, the state machine is modified accordingly. + */ + +`define IMPLEMENT_NOPS + +/* + * Two things were needed to correctly implement 65C02 BCD arithmentic + * 1. The Z flag needs calculating over the BCD adjusted ALU output + * 2. The N flag needs calculating over the BCD adjusted ALU output + * + * If IMPLEMENT_CORRECT_BCD_FLAGS is defined, this additional logic is added + */ + +// `define IMPLEMENT_CORRECT_BCD_FLAGS + +module cpu_65c02( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY ); + +input clk; // CPU clock +input reset; // reset signal +output reg [15:0] AB; // address bus +input [7:0] DI; // data in, read bus +output [7:0] DO; // data out, write bus +output WE; // write enable +input IRQ; // interrupt request +input NMI; // non-maskable interrupt request +input RDY; // Ready signal. Pauses CPU when RDY=0 + +/* + * internal signals + */ + +reg [15:0] PC; // Program Counter +reg [7:0] ABL; // Address Bus Register LSB +reg [7:0] ABH; // Address Bus Register MSB +wire [7:0] ADD; // Adder Hold Register (registered in ALU) + +reg [7:0] DIHOLD; // Hold for Data In +reg DIHOLD_valid; // +wire [7:0] DIMUX; // + +reg [7:0] IRHOLD; // Hold for Instruction register +reg IRHOLD_valid; // Valid instruction in IRHOLD + +reg [7:0] AXYS[3:0]; // A, X, Y and S register file + +reg C = 0; // carry flag (init at zero to avoid X's in ALU sim) +reg Z = 0; // zero flag +reg I = 0; // interrupt flag +reg D = 0; // decimal flag +reg V = 0; // overflow flag +reg N = 0; // negative flag +wire AZ; // ALU Zero flag +wire AZ1; // ALU Zero flag (BCD adjusted) +reg AZ2; // ALU Second Zero flag, set using TSB/TRB semantics +wire AV; // ALU overflow flag +wire AN; // ALU negative flag +wire AN1; // ALU negative flag (BCD adjusted) +wire HC; // ALU half carry + +reg [7:0] AI; // ALU Input A +reg [7:0] BI; // ALU Input B +wire [7:0] DI; // Data In +wire [7:0] IR; // Instruction register +reg [7:0] DO; // Data Out +wire [7:0] AO; // ALU output after BCD adjustment +reg WE; // Write Enable +reg CI; // Carry In +wire CO; // Carry Out +wire [7:0] PCH = PC[15:8]; +wire [7:0] PCL = PC[7:0]; + +reg NMI_edge = 0; // captured NMI edge + +reg [1:0] regsel; // Select A, X, Y or S register +wire [7:0] regfile = AXYS[regsel]; // Selected register output + +parameter + SEL_A = 2'd0, + SEL_S = 2'd1, + SEL_X = 2'd2, + SEL_Y = 2'd3; + +/* + * define some signals for watching in simulator output + */ + + +`ifdef SIM +wire [7:0] A = AXYS[SEL_A]; // Accumulator +wire [7:0] X = AXYS[SEL_X]; // X register +wire [7:0] Y = AXYS[SEL_Y]; // Y register +wire [7:0] S = AXYS[SEL_S]; // Stack pointer +`endif + +wire [7:0] P = { N, V, 2'b11, D, I, Z, C }; + +/* + * instruction decoder/sequencer + */ + +reg [5:0] state; + +/* + * control signals + */ + +reg PC_inc; // Increment PC +reg [15:0] PC_temp; // intermediate value of PC + +reg [1:0] src_reg; // source register index +reg [1:0] dst_reg; // destination register index + +reg index_y; // if set, then Y is index reg rather than X +reg load_reg; // loading a register (A, X, Y, S) in this instruction +reg inc; // increment +reg write_back; // set if memory is read/modified/written +reg load_only; // LDA/LDX/LDY instruction +reg store; // doing store (STA/STX/STY) +reg adc_sbc; // doing ADC/SBC +reg compare; // doing CMP/CPY/CPX +reg shift; // doing shift/rotate instruction +reg rotate; // doing rotate (no shift) +reg backwards; // backwards branch +reg cond_true; // branch condition is true +reg [3:0] cond_code; // condition code bits from instruction +reg shift_right; // Instruction ALU shift/rotate right +reg alu_shift_right; // Current cycle shift right enable +reg [3:0] op; // Main ALU operation for instruction +reg [3:0] alu_op; // Current cycle ALU operation +reg adc_bcd; // ALU should do BCD style carry +reg adj_bcd; // results should be BCD adjusted + +/* + * some flip flops to remember we're doing special instructions. These + * get loaded at the DECODE state, and used later + */ +reg store_zero; // doing STZ instruction +reg trb_ins; // doing TRB instruction +reg txb_ins; // doing TSB/TRB instruction +reg bit_ins; // doing BIT instruction +reg bit_ins_nv; // doing BIT instruction that will update the n and v flags (i.e. not BIT imm) +reg plp; // doing PLP instruction +reg php; // doing PHP instruction +reg clc; // clear carry +reg sec; // set carry +reg cld; // clear decimal +reg sed; // set decimal +reg cli; // clear interrupt +reg sei; // set interrupt +reg clv; // clear overflow +reg brk; // doing BRK + +reg res; // in reset + +/* + * ALU operations + */ + +parameter + OP_OR = 4'b1100, + OP_AND = 4'b1101, + OP_EOR = 4'b1110, + OP_ADD = 4'b0011, + OP_SUB = 4'b0111, + OP_ROL = 4'b1011, + OP_A = 4'b1111; + +/* + * Microcode state machine. Basically, every addressing mode has its own + * path through the state machine. Additional information, such as the + * operation, source and destination registers are decoded in parallel, and + * kept in separate flops. + */ + +parameter + ABS0 = 6'd0, // ABS - fetch LSB + ABS1 = 6'd1, // ABS - fetch MSB + ABSX0 = 6'd2, // ABS, X - fetch LSB and send to ALU (+X) + ABSX1 = 6'd3, // ABS, X - fetch MSB and send to ALU (+Carry) + ABSX2 = 6'd4, // ABS, X - Wait for ALU (only if needed) + BRA0 = 6'd5, // Branch - fetch offset and send to ALU (+PC[7:0]) + BRA1 = 6'd6, // Branch - fetch opcode, and send PC[15:8] to ALU + BRA2 = 6'd7, // Branch - fetch opcode (if page boundary crossed) + BRK0 = 6'd8, // BRK/IRQ - push PCH, send S to ALU (-1) + BRK1 = 6'd9, // BRK/IRQ - push PCL, send S to ALU (-1) + BRK2 = 6'd10, // BRK/IRQ - push P, send S to ALU (-1) + BRK3 = 6'd11, // BRK/IRQ - write S, and fetch @ fffe + DECODE = 6'd12, // IR is valid, decode instruction, and write prev reg + FETCH = 6'd13, // fetch next opcode, and perform prev ALU op + INDX0 = 6'd14, // (ZP,X) - fetch ZP address, and send to ALU (+X) + INDX1 = 6'd15, // (ZP,X) - fetch LSB at ZP+X, calculate ZP+X+1 + INDX2 = 6'd16, // (ZP,X) - fetch MSB at ZP+X+1 + INDX3 = 6'd17, // (ZP,X) - fetch data + INDY0 = 6'd18, // (ZP),Y - fetch ZP address, and send ZP to ALU (+1) + INDY1 = 6'd19, // (ZP),Y - fetch at ZP+1, and send LSB to ALU (+Y) + INDY2 = 6'd20, // (ZP),Y - fetch data, and send MSB to ALU (+Carry) + INDY3 = 6'd21, // (ZP),Y) - fetch data (if page boundary crossed) + JMP0 = 6'd22, // JMP - fetch PCL and hold + JMP1 = 6'd23, // JMP - fetch PCH + JMPI0 = 6'd24, // JMP IND - fetch LSB and send to ALU for delay (+0) + JMPI1 = 6'd25, // JMP IND - fetch MSB, proceed with JMP0 state + JSR0 = 6'd26, // JSR - push PCH, save LSB, send S to ALU (-1) + JSR1 = 6'd27, // JSR - push PCL, send S to ALU (-1) + JSR2 = 6'd28, // JSR - write S + JSR3 = 6'd29, // JSR - fetch MSB + PULL0 = 6'd30, // PLP/PLA/PLX/PLY - save next op in IRHOLD, send S to ALU (+1) + PULL1 = 6'd31, // PLP/PLA/PLX/PLY - fetch data from stack, write S + PULL2 = 6'd32, // PLP/PLA/PLX/PLY - prefetch op, but don't increment PC + PUSH0 = 6'd33, // PHP/PHA/PHX/PHY - send A to ALU (+0) + PUSH1 = 6'd34, // PHP/PHA/PHX/PHY - write A/P, send S to ALU (-1) + READ = 6'd35, // Read memory for read/modify/write (INC, DEC, shift) + REG = 6'd36, // Read register for reg-reg transfers + RTI0 = 6'd37, // RTI - send S to ALU (+1) + RTI1 = 6'd38, // RTI - read P from stack + RTI2 = 6'd39, // RTI - read PCL from stack + RTI3 = 6'd40, // RTI - read PCH from stack + RTI4 = 6'd41, // RTI - read PCH from stack + RTS0 = 6'd42, // RTS - send S to ALU (+1) + RTS1 = 6'd43, // RTS - read PCL from stack + RTS2 = 6'd44, // RTS - write PCL to ALU, read PCH + RTS3 = 6'd45, // RTS - load PC and increment + WRITE = 6'd46, // Write memory for read/modify/write + ZP0 = 6'd47, // Z-page - fetch ZP address + ZPX0 = 6'd48, // ZP, X - fetch ZP, and send to ALU (+X) + ZPX1 = 6'd49, // ZP, X - load from memory + IND0 = 6'd50, // (ZP) - fetch ZP address, and send to ALU (+0) + JMPIX0 = 6'd51, // JMP (,X)- fetch LSB and send to ALU (+X) + JMPIX1 = 6'd52, // JMP (,X)- fetch MSB and send to ALU (+Carry) + JMPIX2 = 6'd53; // JMP (,X)- Wait for ALU (only if needed) + +`ifdef SIM + +/* + * easy to read names in simulator output + */ +reg [8*6-1:0] statename; + +always @* + case( state ) + DECODE: statename = "DECODE"; + REG: statename = "REG"; + ZP0: statename = "ZP0"; + ZPX0: statename = "ZPX0"; + ZPX1: statename = "ZPX1"; + ABS0: statename = "ABS0"; + ABS1: statename = "ABS1"; + ABSX0: statename = "ABSX0"; + ABSX1: statename = "ABSX1"; + ABSX2: statename = "ABSX2"; + IND0: statename = "IND0"; + INDX0: statename = "INDX0"; + INDX1: statename = "INDX1"; + INDX2: statename = "INDX2"; + INDX3: statename = "INDX3"; + INDY0: statename = "INDY0"; + INDY1: statename = "INDY1"; + INDY2: statename = "INDY2"; + INDY3: statename = "INDY3"; + READ: statename = "READ"; + WRITE: statename = "WRITE"; + FETCH: statename = "FETCH"; + PUSH0: statename = "PUSH0"; + PUSH1: statename = "PUSH1"; + PULL0: statename = "PULL0"; + PULL1: statename = "PULL1"; + PULL2: statename = "PULL2"; + JSR0: statename = "JSR0"; + JSR1: statename = "JSR1"; + JSR2: statename = "JSR2"; + JSR3: statename = "JSR3"; + RTI0: statename = "RTI0"; + RTI1: statename = "RTI1"; + RTI2: statename = "RTI2"; + RTI3: statename = "RTI3"; + RTI4: statename = "RTI4"; + RTS0: statename = "RTS0"; + RTS1: statename = "RTS1"; + RTS2: statename = "RTS2"; + RTS3: statename = "RTS3"; + BRK0: statename = "BRK0"; + BRK1: statename = "BRK1"; + BRK2: statename = "BRK2"; + BRK3: statename = "BRK3"; + BRA0: statename = "BRA0"; + BRA1: statename = "BRA1"; + BRA2: statename = "BRA2"; + JMP0: statename = "JMP0"; + JMP1: statename = "JMP1"; + JMPI0: statename = "JMPI0"; + JMPI1: statename = "JMPI1"; + JMPIX0: statename = "JMPIX0"; + JMPIX1: statename = "JMPIX1"; + JMPIX2: statename = "JMPIX2"; + + endcase + +//always @( PC ) +// $display( "%t, PC:%04x IR:%02x A:%02x X:%02x Y:%02x S:%02x C:%d Z:%d V:%d N:%d P:%02x", $time, PC, IR, A, X, Y, S, C, Z, V, N, P ); + +`endif + + + +/* + * Program Counter Increment/Load. First calculate the base value in + * PC_temp. + */ +always @* + case( state ) + DECODE: if( (~I & IRQ) | NMI_edge ) + PC_temp = { ABH, ABL }; + else + PC_temp = PC; + + + JMP1, + JMPI1, + JMPIX1, + JSR3, + RTS3, + RTI4: PC_temp = { DIMUX, ADD }; + + BRA1: PC_temp = { ABH, ADD }; + + JMPIX2, + BRA2: PC_temp = { ADD, PCL }; + + BRK2: PC_temp = res ? 16'hfffc : + NMI_edge ? 16'hfffa : 16'hfffe; + + default: PC_temp = PC; + endcase + +/* + * Determine wether we need PC_temp, or PC_temp + 1 + */ +always @* + case( state ) + DECODE: if( (~I & IRQ) | NMI_edge ) + PC_inc = 0; + else + PC_inc = 1; + + ABS0, + JMPIX0, + JMPIX2, + ABSX0, + FETCH, + BRA0, + BRA2, + BRK3, + JMPI1, + JMP1, + RTI4, + RTS3: PC_inc = 1; + + JMPIX1: PC_inc = ~CO; // Don't increment PC if we are going to go through JMPIX2 + + BRA1: PC_inc = CO ^~ backwards; + + default: PC_inc = 0; + endcase + +/* + * Set new PC + */ +always @(posedge clk) + if( RDY ) + PC <= PC_temp + PC_inc; + +/* + * Address Generator + */ + +parameter + ZEROPAGE = 8'h00, + STACKPAGE = 8'h01; + +always @* + case( state ) + JMPIX1, + ABSX1, + INDX3, + INDY2, + JMP1, + JMPI1, + RTI4, + ABS1: AB = { DIMUX, ADD }; + + BRA2, + INDY3, + JMPIX2, + ABSX2: AB = { ADD, ABL }; + + BRA1: AB = { ABH, ADD }; + + JSR0, + PUSH1, + RTS0, + RTI0, + BRK0: AB = { STACKPAGE, regfile }; + + BRK1, + JSR1, + PULL1, + RTS1, + RTS2, + RTI1, + RTI2, + RTI3, + BRK2: AB = { STACKPAGE, ADD }; + + INDY1, + INDX1, + ZPX1, + INDX2: AB = { ZEROPAGE, ADD }; + + ZP0, + INDY0: AB = { ZEROPAGE, DIMUX }; + + REG, + READ, + WRITE: AB = { ABH, ABL }; + + default: AB = PC; + endcase + +/* + * ABH/ABL pair is used for registering previous address bus state. + * This can be used to keep the current address, freeing up the original + * source of the address, such as the ALU or DI. + */ +always @(posedge clk) + if( state != PUSH0 && state != PUSH1 && RDY && + state != PULL0 && state != PULL1 && state != PULL2 ) + begin + ABL <= AB[7:0]; + ABH <= AB[15:8]; + end + +/* + * Data Out MUX + */ +always @* + case( state ) + WRITE: DO = ADD; + + JSR0, + BRK0: DO = PCH; + + JSR1, + BRK1: DO = PCL; + + PUSH1: DO = php ? P : ADD; + + BRK2: DO = (IRQ | NMI_edge) ? (P & 8'b1110_1111) : P; + + default: DO = store_zero ? 0 : regfile; + endcase + +/* + * Write Enable Generator + */ + +always @* + case( state ) + BRK0, // writing to stack or memory + BRK1, + BRK2, + JSR0, + JSR1, + PUSH1, + WRITE: WE = 1; + + INDX3, // only if doing a STA, STX or STY + INDY3, + ABSX2, + ABS1, + ZPX1, + ZP0: WE = store; + + default: WE = 0; + endcase + +/* + * register file, contains A, X, Y and S (stack pointer) registers. At each + * cycle only 1 of those registers needs to be accessed, so they combined + * in a small memory, saving resources. + */ + +reg write_register; // set when register file is written + +always @* + case( state ) + DECODE: write_register = load_reg & ~plp; + + PULL1, + RTS2, + RTI3, + BRK3, + JSR0, + JSR2 : write_register = 1; + + default: write_register = 0; + endcase + +/* + * BCD adjust logic + */ + +always @(posedge clk) + adj_bcd <= adc_sbc & D; // '1' when doing a BCD instruction + +reg [3:0] ADJL; +reg [3:0] ADJH; + +// adjustment term to be added to ADD[3:0] based on the following +// adj_bcd: '1' if doing ADC/SBC with D=1 +// adc_bcd: '1' if doing ADC with D=1 +// HC : half carry bit from ALU +always @* begin + casex( {adj_bcd, adc_bcd, HC} ) + 3'b0xx: ADJL = 4'd0; // no BCD instruction + 3'b100: ADJL = 4'd10; // SBC, and digital borrow + 3'b101: ADJL = 4'd0; // SBC, but no borrow + 3'b110: ADJL = 4'd0; // ADC, but no carry + 3'b111: ADJL = 4'd6; // ADC, and decimal/digital carry + endcase +end + +// adjustment term to be added to ADD[7:4] based on the following +// adj_bcd: '1' if doing ADC/SBC with D=1 +// adc_bcd: '1' if doing ADC with D=1 +// CO : carry out bit from ALU +always @* begin + casex( {adj_bcd, adc_bcd, CO} ) + 3'b0xx: ADJH = 4'd0; // no BCD instruction + 3'b100: ADJH = 4'd10; // SBC, and digital borrow + 3'b101: ADJH = 4'd0; // SBC, but no borrow + 3'b110: ADJH = 4'd0; // ADC, but no carry + 3'b111: ADJH = 4'd6; // ADC, and decimal/digital carry + endcase +end + +assign AO = { ADD[7:4] + ADJH, ADD[3:0] + ADJL }; + +`ifdef IMPLEMENT_CORRECT_BCD_FLAGS + +assign AN1 = AO[7]; +assign AZ1 = ~|AO; + +`else + +assign AN1 = AN; +assign AZ1 = AZ; + +`endif + +/* + * write to a register. Usually this is the (BCD corrected) output of the + * ALU, but in case of the JSR0 we use the S register to temporarily store + * the PCL. This is possible, because the S register itself is stored in + * the ALU during those cycles. + */ +always @(posedge clk) + if( write_register & RDY ) + AXYS[regsel] <= (state == JSR0) ? DIMUX : AO; + +/* + * register select logic. This determines which of the A, X, Y or + * S registers will be accessed. + */ + +always @* + case( state ) + INDY1, + INDX0, + ZPX0, + JMPIX0, + ABSX0 : regsel = index_y ? SEL_Y : SEL_X; + + + DECODE : regsel = dst_reg; + + BRK0, + BRK3, + JSR0, + JSR2, + PULL0, + PULL1, + PUSH1, + RTI0, + RTI3, + RTS0, + RTS2 : regsel = SEL_S; + + default: regsel = src_reg; + endcase + +/* + * ALU + */ + +ALU ALU( .clk(clk), + .op(alu_op), + .right(alu_shift_right), + .AI(AI), + .BI(BI), + .CI(CI), + .BCD(adc_bcd & (state == FETCH)), + .CO(CO), + .OUT(ADD), + .V(AV), + .Z(AZ), + .N(AN), + .HC(HC), + .RDY(RDY) ); + +/* + * Select current ALU operation + */ + +always @* + case( state ) + READ: alu_op = op; + + BRA1: alu_op = backwards ? OP_SUB : OP_ADD; + + FETCH, + REG : alu_op = op; + + DECODE, + ABS1: alu_op = 1'bx; + + PUSH1, + BRK0, + BRK1, + BRK2, + JSR0, + JSR1: alu_op = OP_SUB; + + default: alu_op = OP_ADD; + endcase + +/* + * Determine shift right signal to ALU + */ + +always @* + if( state == FETCH || state == REG || state == READ ) + alu_shift_right = shift_right; + else + alu_shift_right = 0; + +/* + * Sign extend branch offset. + */ + +always @(posedge clk) + if( RDY ) + backwards <= DIMUX[7]; + +/* + * ALU A Input MUX + */ + +always @* + case( state ) + JSR1, + RTS1, + RTI1, + RTI2, + BRK1, + BRK2, + INDX1: AI = ADD; + + REG, + ZPX0, + INDX0, + JMPIX0, + ABSX0, + RTI0, + RTS0, + JSR0, + JSR2, + BRK0, + PULL0, + INDY1, + PUSH0, + PUSH1: AI = regfile; + + BRA0, + READ: AI = DIMUX; + + BRA1: AI = ABH; // don't use PCH in case we're + + FETCH: AI = load_only ? 0 : regfile; + + DECODE, + ABS1: AI = 8'hxx; // don't care + + default: AI = 0; + endcase + + +/* + * ALU B Input mux + */ + +always @* + case( state ) + BRA1, + RTS1, + RTI0, + RTI1, + RTI2, + INDX1, + REG, + JSR0, + JSR1, + JSR2, + BRK0, + BRK1, + BRK2, + PUSH0, + PUSH1, + PULL0, + RTS0: BI = 8'h00; + + READ: BI = txb_ins ? (trb_ins ? ~regfile : regfile) : 8'h00; + + BRA0: BI = PCL; + + DECODE, + ABS1: BI = 8'hxx; + + default: BI = DIMUX; + endcase + +/* + * ALU CI (carry in) mux + */ + +always @* + case( state ) + INDY2, + BRA1, + JMPIX1, + ABSX1: CI = CO; + + DECODE, + ABS1: CI = 1'bx; + + READ, + REG: CI = rotate ? C : + shift ? 0 : inc; + + FETCH: CI = rotate ? C : + compare ? 1 : + (shift | load_only) ? 0 : C; + + PULL0, + RTI0, + RTI1, + RTI2, + RTS0, + RTS1, + INDY0, + INDX1: CI = 1; + + default: CI = 0; + endcase + +/* + * Processor Status Register update + * + */ + +/* + * Update C flag when doing ADC/SBC, shift/rotate, compare + */ +always @(posedge clk ) + if( shift && state == WRITE ) + C <= CO; + else if( state == RTI2 ) + C <= DIMUX[0]; + else if( ~write_back && state == DECODE ) begin + if( adc_sbc | shift | compare ) + C <= CO; + else if( plp ) + C <= ADD[0]; + else begin + if( sec ) C <= 1; + if( clc ) C <= 0; + end + end + +/* + * Special Z flag got TRB/TSB + */ +always @(posedge clk) + AZ2 <= ~|(AI & regfile); + +/* + * Update Z, N flags when writing A, X, Y, Memory, or when doing compare + */ + +always @(posedge clk) + if( state == WRITE) + Z <= txb_ins ? AZ2 : AZ1; + else if( state == RTI2 ) + Z <= DIMUX[1]; + else if( state == DECODE ) begin + if( plp ) + Z <= ADD[1]; + else if( (load_reg & (regsel != SEL_S)) | compare | bit_ins ) + Z <= AZ1; + end + +always @(posedge clk) + if( state == WRITE && ~txb_ins) + N <= AN1; + else if( state == RTI2 ) + N <= DIMUX[7]; + else if( state == DECODE ) begin + if( plp ) + N <= ADD[7]; + else if( (load_reg & (regsel != SEL_S)) | compare ) + N <= AN1; + end else if( state == FETCH && bit_ins_nv ) + N <= DIMUX[7]; + +/* + * Update I flag + */ + +always @(posedge clk) + if( state == BRK3 ) + I <= 1; + else if( state == RTI2 ) + I <= DIMUX[2]; + else if( state == REG ) begin + if( sei ) I <= 1; + if( cli ) I <= 0; + end else if( state == DECODE ) + if( plp ) I <= ADD[2]; + +/* + * Update D flag + */ +always @(posedge clk ) + if( state == RTI2 ) + D <= DIMUX[3]; + else if( state == DECODE ) begin + if( sed ) D <= 1; + if( cld ) D <= 0; + if( plp ) D <= ADD[3]; + end + +/* + * Update V flag + */ +always @(posedge clk ) + if( state == RTI2 ) + V <= DIMUX[6]; + else if( state == DECODE ) begin + if( adc_sbc ) V <= AV; + if( clv ) V <= 0; + if( plp ) V <= ADD[6]; + end else if( state == FETCH && bit_ins_nv ) + V <= DIMUX[6]; + +/* + * Instruction decoder + */ + +/* + * IR register/mux. Hold previous DI value in IRHOLD in PULL0 and PUSH0 + * states. In these states, the IR has been prefetched, and there is no + * time to read the IR again before the next decode. + */ + +//reg RDY1 = 1; + +//always @(posedge clk ) +// RDY1 <= RDY; + +//always @(posedge clk ) +// if( ~RDY && RDY1 ) +// DIHOLD <= DI; + +always @(posedge clk ) + if( reset ) + IRHOLD_valid <= 0; + else if( RDY ) begin + if( state == PULL0 || state == PUSH0 ) begin + IRHOLD <= DIMUX; + IRHOLD_valid <= 1; + end else if( state == DECODE ) + IRHOLD_valid <= 0; + end + +assign IR = (IRQ & ~I) | NMI_edge ? 8'h00 : + IRHOLD_valid ? IRHOLD : DIMUX; + +//assign DIMUX = ~RDY1 ? DIHOLD : DI; + +assign DIMUX = DI; + +/* + * Microcode state machine + */ +always @(posedge clk or posedge reset) + if( reset ) + state <= BRK0; + else if( RDY ) case( state ) + DECODE : + casex ( IR ) + // TODO Review for simplifications as in verilog the first matching case has priority + 8'b0000_0000: state <= BRK0; + 8'b0010_0000: state <= JSR0; + 8'b0010_1100: state <= ABS0; // BIT abs + 8'b1001_1100: state <= ABS0; // STZ abs + 8'b000x_1100: state <= ABS0; // TSB/TRB + 8'b0100_0000: state <= RTI0; // + 8'b0100_1100: state <= JMP0; + 8'b0110_0000: state <= RTS0; + 8'b0110_1100: state <= JMPI0; + 8'b0111_1100: state <= JMPIX0; +`ifdef IMPLEMENT_NOPS + 8'bxxxx_xx11: state <= REG; // (NOP1: 3/7/B/F column) + 8'bxxx0_0010: state <= FETCH; // (NOP2: 2 column, 4 column handled correctly below) + 8'bx1x1_1100: state <= ABS0; // (NOP3: C column) +`endif + 8'b0x00_1000: state <= PUSH0; + 8'b0x10_1000: state <= PULL0; + 8'b0xx1_1000: state <= REG; // CLC, SEC, CLI, SEI + 8'b11x0_00x0: state <= FETCH; // IMM + 8'b1x10_00x0: state <= FETCH; // IMM + 8'b1xx0_1100: state <= ABS0; // X/Y abs + 8'b1xxx_1000: state <= REG; // DEY, TYA, ... + 8'bxxx0_0001: state <= INDX0; + 8'bxxx1_0010: state <= IND0; // (ZP) odd 2 column + 8'b000x_0100: state <= ZP0; // TSB/TRB + 8'bxxx0_01xx: state <= ZP0; + 8'bxxx0_1001: state <= FETCH; // IMM + 8'bxxx0_1101: state <= ABS0; // even D column + 8'bxxx0_1110: state <= ABS0; // even E column + 8'bxxx1_0000: state <= BRA0; // odd 0 column (Branches) + 8'b1000_0000: state <= BRA0; // BRA + 8'bxxx1_0001: state <= INDY0; // odd 1 column + 8'bxxx1_01xx: state <= ZPX0; // odd 4,5,6,7 columns + 8'bxxx1_1001: state <= ABSX0; // odd 9 column + 8'bx011_1100: state <= ABSX0; // C column BIT (3C), LDY (BC) + 8'bxxx1_11x1: state <= ABSX0; // odd D, F columns + 8'bxxx1_111x: state <= ABSX0; // odd E, F columns + 8'bx101_1010: state <= PUSH0; // PHX/PHY + 8'bx111_1010: state <= PULL0; // PLX/PLY + 8'bx0xx_1010: state <= REG; // A, TXA, ... NOP + 8'bxxx0_1010: state <= REG; // A, TXA, ... NOP + endcase + + ZP0 : state <= write_back ? READ : FETCH; + + ZPX0 : state <= ZPX1; + ZPX1 : state <= write_back ? READ : FETCH; + + ABS0 : state <= ABS1; + ABS1 : state <= write_back ? READ : FETCH; + + ABSX0 : state <= ABSX1; + ABSX1 : state <= (CO | store | write_back) ? ABSX2 : FETCH; + ABSX2 : state <= write_back ? READ : FETCH; + + JMPIX0 : state <= JMPIX1; + JMPIX1 : state <= CO ? JMPIX2 : JMP0; + JMPIX2 : state <= JMP0; + + IND0 : state <= INDX1; + + INDX0 : state <= INDX1; + INDX1 : state <= INDX2; + INDX2 : state <= INDX3; + INDX3 : state <= FETCH; + + INDY0 : state <= INDY1; + INDY1 : state <= INDY2; + INDY2 : state <= (CO | store) ? INDY3 : FETCH; + INDY3 : state <= FETCH; + + READ : state <= WRITE; + WRITE : state <= FETCH; + FETCH : state <= DECODE; + + REG : state <= DECODE; + + PUSH0 : state <= PUSH1; + PUSH1 : state <= DECODE; + + PULL0 : state <= PULL1; + PULL1 : state <= PULL2; + PULL2 : state <= DECODE; + + JSR0 : state <= JSR1; + JSR1 : state <= JSR2; + JSR2 : state <= JSR3; + JSR3 : state <= FETCH; + + RTI0 : state <= RTI1; + RTI1 : state <= RTI2; + RTI2 : state <= RTI3; + RTI3 : state <= RTI4; + RTI4 : state <= DECODE; + + RTS0 : state <= RTS1; + RTS1 : state <= RTS2; + RTS2 : state <= RTS3; + RTS3 : state <= FETCH; + + BRA0 : state <= cond_true ? BRA1 : DECODE; + BRA1 : state <= (CO ^ backwards) ? BRA2 : DECODE; + BRA2 : state <= DECODE; + + JMP0 : state <= JMP1; + JMP1 : state <= DECODE; + + JMPI0 : state <= JMPI1; + JMPI1 : state <= JMP0; + + BRK0 : state <= BRK1; + BRK1 : state <= BRK2; + BRK2 : state <= BRK3; + BRK3 : state <= JMP0; + + endcase + +/* + * Additional control signals + */ + +always @(posedge clk) + if( reset ) + res <= 1; + else if( state == DECODE ) + res <= 0; + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) // DMB: Checked for 65C02 NOP collisions + 8'b0xx1_0010, // ORA, AND, EOR, ADC (zp) + 8'b1x11_0010, // LDA, SBC (zp) + 8'b0xxx_1010, // ASLA, INCA, ROLA, DECA, LSRA, PHY, RORA, PLY + 8'b0xxx_xx01, // ORA, AND, EOR, ADC + 8'b100x_10x0, // DEY, TYA, TXA, TXS + 8'b1010_xxx0, // LDA/LDX/LDY + 8'b1011_1010, // TSX + 8'b1011_x1x0, // LDX/LDY + 8'b1100_1010, // DEX + 8'b11x1_1010, // PHX, PLX + 8'b1x1x_xx01, // LDA, SBC + 8'bxxx0_1000: // PHP, PLP, PHA, PLA, DEY, TAY, INY, INX + load_reg <= 1; + + default: load_reg <= 0; + endcase + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'b1110_1000, // INX + 8'b1100_1010, // DEX + 8'b1111_1010, // PLX + 8'b1010_0010, // LDX imm + 8'b101x_x110, // LDX + 8'b101x_1x10: // LDX, TAX, TSX + dst_reg <= SEL_X; + + 8'b0x00_1000, // PHP, PHA + 8'bx101_1010, // PHX, PHY + 8'b1001_1010: // TXS + dst_reg <= SEL_S; + + 8'b1x00_1000, // DEY, DEX + 8'b0111_1010, // PLY + 8'b101x_x100, // LDY + 8'b1010_x000: // LDY #imm, TAY + dst_reg <= SEL_Y; + + default: dst_reg <= SEL_A; + endcase + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'b1011_1010: // TSX + src_reg <= SEL_S; + + 8'b100x_x110, // STX + 8'b100x_1x10, // TXA, TXS + 8'b1110_xx00, // INX, CPX + 8'b1101_1010, // PHX + 8'b1100_1010: // DEX + src_reg <= SEL_X; + + 8'b100x_x100, // STY + 8'b1001_1000, // TYA + 8'b1100_xx00, // CPY + 8'b0101_1010, // PHY + 8'b1x00_1000: // DEY, INY + src_reg <= SEL_Y; + + default: src_reg <= SEL_A; + endcase + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'bxxx1_0001, // INDY + 8'b10x1_0110, // LDX zp,Y / STX zp,Y + 8'b1011_1110, // LDX abs,Y + 8'bxxxx_1001: // abs, Y + index_y <= 1; + + default: index_y <= 0; + endcase + + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) // DMB: Checked for 65C02 NOP collisions + 8'b1001_0010, // STA (zp) + 8'b100x_x1x0, // STX, STY, STZ abs, STZ abs,x + 8'b011x_0100, // STZ zp, STZ zp,x + 8'b100x_xx01: // STA + store <= 1; + + default: store <= 0; + + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) // DMB: Checked for 65C02 NOP collisions + 8'b0xxx_x110, // ASL, ROL, LSR, ROR + 8'b000x_x100, // TSB/TRB + 8'b11xx_x110: // DEC/INC + write_back <= 1; + + default: write_back <= 0; + endcase + + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b101x_xxxx: // LDA, LDX, LDY + load_only <= 1; + default: load_only <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0001_1010, // INCA + 8'b111x_x110, // INC + 8'b11x0_1000: // INX, INY + inc <= 1; + + default: inc <= 0; + endcase + +always @(posedge clk ) + if( (state == DECODE || state == BRK0) && RDY ) + casex( IR ) + 8'bx111_0010, // SBC (zp), ADC (zp) + 8'bx11x_xx01: // SBC, ADC + adc_sbc <= 1; + + default: adc_sbc <= 0; + endcase + +always @(posedge clk ) + if( (state == DECODE || state == BRK0) && RDY ) + casex( IR ) + 8'b0111_0010, // ADC (zp) + 8'b011x_xx01: // ADC + adc_bcd <= D; + + default: adc_bcd <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0xxx_x110, // ASL, ROL, LSR, ROR (abs, absx, zpg, zpgx) + 8'b0xx0_1010: // ASL, ROL, LSR, ROR (acc) + shift <= 1; + + default: shift <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b1101_0010, // CMP (zp) + 8'b11x0_0x00, // CPX, CPY (imm/zp) + 8'b11x0_1100, // CPX, CPY (abs) + 8'b110x_xx01: // CMP + compare <= 1; + + default: compare <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b01xx_x110, // ROR, LSR + 8'b01xx_1x10: // ROR, LSR + shift_right <= 1; + + default: shift_right <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0x10_1010, // ROL A, ROR A + 8'b0x1x_x110: // ROR, ROL + rotate <= 1; + + default: rotate <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0000_x100: // TSB + op <= OP_OR; + + 8'b0001_x100: // TRB + op <= OP_AND; + + 8'b00xx_x110, // ROL, ASL + 8'b00x0_1010: // ROL, ASL + op <= OP_ROL; + + 8'b1000_1001, // BIT imm + 8'b001x_x100: // BIT zp/abs/zpx/absx + op <= OP_AND; + + 8'b01xx_x110, // ROR, LSR + 8'b01xx_1x10: // ROR, LSR + op <= OP_A; + + 8'b11x1_0010, // CMP, SBC (zp) + 8'b0011_1010, // DEC A + 8'b1000_1000, // DEY + 8'b1100_1010, // DEX + 8'b110x_x110, // DEC + 8'b11xx_xx01, // CMP, SBC + 8'b11x0_0x00, // CPX, CPY (imm, zpg) + 8'b11x0_1100: op <= OP_SUB; + + 8'b00x1_0010, // ORA, AND (zp) + 8'b0x01_0010, // ORA, EOR (zp) + 8'b010x_xx01, // EOR + 8'b00xx_xx01: // ORA, AND + op <= { 2'b11, IR[6:5] }; + + default: op <= OP_ADD; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b001x_x100: // BIT zp/abs/zpx/absx (update N,V,Z) + {bit_ins, bit_ins_nv} <= 2'b11; + + 8'b1000_1001: // BIT imm (update Z) + {bit_ins, bit_ins_nv} <= 2'b10; + + default: // not a BIT instruction + {bit_ins, bit_ins_nv} <= 2'b00; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b000x_x100: // TRB/TSB + txb_ins <= 1; + + default: txb_ins <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0001_x100: // TRB + trb_ins <= 1; + + default: trb_ins <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b1001_11x0, // STZ abs, STZ abs,x + 8'b011x_0100: // STZ zp, STZ zp,x + store_zero <= 1; + + default: store_zero <= 0; + endcase + +/* + * special instructions + */ +always @(posedge clk ) + if( state == DECODE && RDY ) begin + php <= (IR == 8'h08); + clc <= (IR == 8'h18); + plp <= (IR == 8'h28); + sec <= (IR == 8'h38); + cli <= (IR == 8'h58); + sei <= (IR == 8'h78); + clv <= (IR == 8'hb8); + cld <= (IR == 8'hd8); + sed <= (IR == 8'hf8); + brk <= (IR == 8'h00); + end + +always @(posedge clk) + if( RDY ) + cond_code <= IR[7:4]; + +always @* + case( cond_code ) + 4'b0001: cond_true = ~N; + 4'b0011: cond_true = N; + 4'b0101: cond_true = ~V; + 4'b0111: cond_true = V; + 4'b1001: cond_true = ~C; + 4'b1011: cond_true = C; + 4'b1101: cond_true = ~Z; + 4'b1111: cond_true = Z; + default: cond_true = 1; // BRA is 80 + endcase + + +reg NMI_1 = 0; // delayed NMI signal + +always @(posedge clk) + NMI_1 <= NMI; + +always @(posedge clk ) + if( NMI_edge && state == BRK3 ) + NMI_edge <= 0; + else if( NMI & ~NMI_1 ) + NMI_edge <= 1; + +endmodule diff --git a/src/DCM/dcm_32_100.vhd b/src/DCM/dcm_32_100.vhd new file mode 100644 index 0000000..31fd4c4 --- /dev/null +++ b/src/DCM/dcm_32_100.vhd @@ -0,0 +1,64 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +library UNISIM; +use UNISIM.Vcomponents.all; + +entity dcm_32_100 is + port (CLKIN_IN : in std_logic; + CLK0_OUT : out std_logic; + CLK0_OUT1 : out std_logic; + CLK2X_OUT : out std_logic); +end dcm_32_100; + +architecture BEHAVIORAL of dcm_32_100 is + signal CLKFX_BUF : std_logic; + signal CLK2X_BUF : std_logic; + signal CLKIN_IBUFG : std_logic; + signal GND_BIT : std_logic; +begin + + GND_BIT <= '0'; + + CLKFX_BUFG_INST : BUFG + port map (I => CLKFX_BUF, O => CLK0_OUT); + + CLK2X_BUFG_INST : BUFG + port map (I => CLK2X_BUF, O => CLK2X_OUT); + + DCM_INST : DCM + generic map(CLK_FEEDBACK => "NONE", + CLKDV_DIVIDE => 4.0, -- 100.00 = 32.000 * 25/8 + CLKFX_MULTIPLY => 25, + CLKFX_DIVIDE => 8, + CLKIN_DIVIDE_BY_2 => false, + CLKIN_PERIOD => 31.25, + CLKOUT_PHASE_SHIFT => "NONE", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", + DFS_FREQUENCY_MODE => "LOW", + DLL_FREQUENCY_MODE => "LOW", + DUTY_CYCLE_CORRECTION => true, + FACTORY_JF => x"C080", + PHASE_SHIFT => 0, + STARTUP_WAIT => false) + port map (CLKFB => GND_BIT, + CLKIN => CLKIN_IN, + DSSEN => GND_BIT, + PSCLK => GND_BIT, + PSEN => GND_BIT, + PSINCDEC => GND_BIT, + RST => GND_BIT, + CLKDV => open, + CLKFX => CLKFX_BUF, + CLKFX180 => open, + CLK0 => open, + CLK2X => CLK2X_BUF, + CLK2X180 => open, + CLK90 => open, + CLK180 => open, + CLK270 => open, + LOCKED => open, + PSDONE => open, + STATUS => open); + +end BEHAVIORAL; diff --git a/src/DCM/dcm_32_120.vhd b/src/DCM/dcm_32_120.vhd new file mode 100644 index 0000000..cd83b1c --- /dev/null +++ b/src/DCM/dcm_32_120.vhd @@ -0,0 +1,64 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +library UNISIM; +use UNISIM.Vcomponents.all; + +entity dcm_32_120 is + port (CLKIN_IN : in std_logic; + CLK0_OUT : out std_logic; + CLK0_OUT1 : out std_logic; + CLK2X_OUT : out std_logic); +end dcm_32_120; + +architecture BEHAVIORAL of dcm_32_120 is + signal CLKFX_BUF : std_logic; + signal CLK2X_BUF : std_logic; + signal CLKIN_IBUFG : std_logic; + signal GND_BIT : std_logic; +begin + + GND_BIT <= '0'; + + CLKFX_BUFG_INST : BUFG + port map (I => CLKFX_BUF, O => CLK0_OUT); + + CLK2X_BUFG_INST : BUFG + port map (I => CLK2X_BUF, O => CLK2X_OUT); + + DCM_INST : DCM + generic map(CLK_FEEDBACK => "NONE", + CLKDV_DIVIDE => 4.0, -- 120.00 = 32.000 * 15 / 4 + CLKFX_MULTIPLY => 15, + CLKFX_DIVIDE => 4, + CLKIN_DIVIDE_BY_2 => false, + CLKIN_PERIOD => 31.25, + CLKOUT_PHASE_SHIFT => "NONE", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", + DFS_FREQUENCY_MODE => "LOW", + DLL_FREQUENCY_MODE => "LOW", + DUTY_CYCLE_CORRECTION => true, + FACTORY_JF => x"C080", + PHASE_SHIFT => 0, + STARTUP_WAIT => false) + port map (CLKFB => GND_BIT, + CLKIN => CLKIN_IN, + DSSEN => GND_BIT, + PSCLK => GND_BIT, + PSEN => GND_BIT, + PSINCDEC => GND_BIT, + RST => GND_BIT, + CLKDV => open, + CLKFX => CLKFX_BUF, + CLKFX180 => open, + CLK0 => open, + CLK2X => CLK2X_BUF, + CLK2X180 => open, + CLK90 => open, + CLK180 => open, + CLK270 => open, + LOCKED => open, + PSDONE => open, + STATUS => open); + +end BEHAVIORAL; diff --git a/src/DCM/dcm_32_80.vhd b/src/DCM/dcm_32_80.vhd new file mode 100644 index 0000000..5366dcc --- /dev/null +++ b/src/DCM/dcm_32_80.vhd @@ -0,0 +1,64 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +library UNISIM; +use UNISIM.Vcomponents.all; + +entity dcm_32_80 is + port (CLKIN_IN : in std_logic; + CLK0_OUT : out std_logic; + CLK0_OUT1 : out std_logic; + CLK2X_OUT : out std_logic); +end dcm_32_80; + +architecture BEHAVIORAL of dcm_32_80 is + signal CLKFX_BUF : std_logic; + signal CLK2X_BUF : std_logic; + signal CLKIN_IBUFG : std_logic; + signal GND_BIT : std_logic; +begin + + GND_BIT <= '0'; + + CLKFX_BUFG_INST : BUFG + port map (I => CLKFX_BUF, O => CLK0_OUT); + + CLK2X_BUFG_INST : BUFG + port map (I => CLK2X_BUF, O => CLK2X_OUT); + + DCM_INST : DCM + generic map(CLK_FEEDBACK => "NONE", + CLKDV_DIVIDE => 4.0, -- 80.00 = 32.000 * 10/4 + CLKFX_MULTIPLY => 10, + CLKFX_DIVIDE => 4, + CLKIN_DIVIDE_BY_2 => false, + CLKIN_PERIOD => 31.25, + CLKOUT_PHASE_SHIFT => "NONE", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", + DFS_FREQUENCY_MODE => "LOW", + DLL_FREQUENCY_MODE => "LOW", + DUTY_CYCLE_CORRECTION => true, + FACTORY_JF => x"C080", + PHASE_SHIFT => 0, + STARTUP_WAIT => false) + port map (CLKFB => GND_BIT, + CLKIN => CLKIN_IN, + DSSEN => GND_BIT, + PSCLK => GND_BIT, + PSEN => GND_BIT, + PSINCDEC => GND_BIT, + RST => GND_BIT, + CLKDV => open, + CLKFX => CLKFX_BUF, + CLKFX180 => open, + CLK0 => open, + CLK2X => CLK2X_BUF, + CLK2X180 => open, + CLK90 => open, + CLK180 => open, + CLK270 => open, + LOCKED => open, + PSDONE => open, + STATUS => open); + +end BEHAVIORAL; diff --git a/src/DCM/dcm_32_96.vhd b/src/DCM/dcm_32_96.vhd new file mode 100644 index 0000000..cd33b9e --- /dev/null +++ b/src/DCM/dcm_32_96.vhd @@ -0,0 +1,64 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +library UNISIM; +use UNISIM.Vcomponents.all; + +entity dcm_32_96 is + port (CLKIN_IN : in std_logic; + CLK0_OUT : out std_logic; + CLK0_OUT1 : out std_logic; + CLK2X_OUT : out std_logic); +end dcm_32_96; + +architecture BEHAVIORAL of dcm_32_96 is + signal CLKFX_BUF : std_logic; + signal CLK2X_BUF : std_logic; + signal CLKIN_IBUFG : std_logic; + signal GND_BIT : std_logic; +begin + + GND_BIT <= '0'; + + CLKFX_BUFG_INST : BUFG + port map (I => CLKFX_BUF, O => CLK0_OUT); + + CLK2X_BUFG_INST : BUFG + port map (I => CLK2X_BUF, O => CLK2X_OUT); + + DCM_INST : DCM + generic map(CLK_FEEDBACK => "NONE", + CLKDV_DIVIDE => 4.0, -- 96.00 = 32.000 * 12/4 + CLKFX_MULTIPLY => 12, + CLKFX_DIVIDE => 4, + CLKIN_DIVIDE_BY_2 => false, + CLKIN_PERIOD => 31.25, + CLKOUT_PHASE_SHIFT => "NONE", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", + DFS_FREQUENCY_MODE => "LOW", + DLL_FREQUENCY_MODE => "LOW", + DUTY_CYCLE_CORRECTION => true, + FACTORY_JF => x"C080", + PHASE_SHIFT => 0, + STARTUP_WAIT => false) + port map (CLKFB => GND_BIT, + CLKIN => CLKIN_IN, + DSSEN => GND_BIT, + PSCLK => GND_BIT, + PSEN => GND_BIT, + PSINCDEC => GND_BIT, + RST => GND_BIT, + CLKDV => open, + CLKFX => CLKFX_BUF, + CLKFX180 => open, + CLK0 => open, + CLK2X => CLK2X_BUF, + CLK2X180 => open, + CLK90 => open, + CLK180 => open, + CLK270 => open, + LOCKED => open, + PSDONE => open, + STATUS => open); + +end BEHAVIORAL; diff --git a/src/LX9Co_CoPro6502fast.vhd b/src/LX9Co_CoPro6502fast.vhd index 9790a18..4dd1701 100644 --- a/src/LX9Co_CoPro6502fast.vhd +++ b/src/LX9Co_CoPro6502fast.vhd @@ -5,9 +5,8 @@ use ieee.numeric_std.all; entity LX9CoPro6502fast is generic ( - UseT65Core : boolean := false; - UseJensCore : boolean := false; - UseAlanDCore : boolean := true + UseAlanDCore : boolean := false; + UseArletCore : boolean := true ); port ( -- GOP Signals @@ -31,7 +30,7 @@ entity LX9CoPro6502fast is ram_oe : out std_logic; ram_wr : out std_logic; ram_addr : out std_logic_vector (18 downto 0); - ram_data : inout std_logic_vector (7 downto 0) + ram_data : inout std_logic_vector (15 downto 0) ); end LX9CoPro6502fast; @@ -54,17 +53,38 @@ architecture BEHAVIORAL of LX9CoPro6502fast is ------------------------------------------------- signal p_cs_b : std_logic; + signal bank_cs_b : std_logic; signal p_data_out : std_logic_vector (7 downto 0); ------------------------------------------------- -- ram/rom signals ------------------------------------------------- - signal ram_cs_b : std_logic; - signal ram_wr_int : std_logic; - signal rom_cs_b : std_logic; - signal rom_data_out : std_logic_vector (7 downto 0); - signal ram_data_out : std_logic_vector (7 downto 0); + signal ram_cs_b : std_logic; + signal rom_cs_b : std_logic; + signal rom_data_out : std_logic_vector (7 downto 0); + signal int_ram_data_out : std_logic_vector (7 downto 0); + signal ext_ram_data_out : std_logic_vector (7 downto 0); + +------------------------------------------------- +-- bank registers and physical address bus +------------------------------------------------- + + signal ext_ram : std_logic; + signal ext_ram_next : std_logic; + signal ext_ram_we : std_logic; + signal ext_ram_we_next : std_logic; + + signal int_ram : std_logic; + signal int_ram_next : std_logic; + signal int_ram_we_next : std_logic; + + signal physical_addr : std_logic_vector (20 downto 0); + signal physical_addr_next : std_logic_vector (20 downto 0); + + -- bit 7 = 0 for internal RAM, 1 for external RAM + type bank_reg_type is array (0 to 7) of std_logic_vector (7 downto 0); + signal bank_reg : bank_reg_type; ------------------------------------------------- -- cpu signals @@ -72,8 +92,8 @@ architecture BEHAVIORAL of LX9CoPro6502fast is signal debug_clk : std_logic; signal cpu_R_W_n : std_logic; - signal cpu_addr : std_logic_vector (23 downto 0); - signal cpu_addr_us: unsigned (23 downto 0); + signal cpu_addr : std_logic_vector (15 downto 0); + signal cpu_addr_us: unsigned (15 downto 0); signal cpu_din : std_logic_vector (7 downto 0); signal cpu_dout : std_logic_vector (7 downto 0); signal cpu_dout_us: unsigned (7 downto 0); @@ -83,6 +103,18 @@ architecture BEHAVIORAL of LX9CoPro6502fast is signal cpu_NMI_n_sync : std_logic; signal sync : std_logic; + -- Lookahead (unregistered) signals + signal p_cs_b_next : std_logic; + signal bank_cs_b_next : std_logic; + signal ram_cs_b_next : std_logic; + signal rom_cs_b_next : std_logic; + signal cpu_dout_next : std_logic_vector (7 downto 0); + signal cpu_dout_next_us : unsigned (7 downto 0); + signal cpu_addr_next : std_logic_vector (15 downto 0); + signal cpu_addr_next_us : unsigned (15 downto 0); + signal cpu_we_next : std_logic; + signal cpu_R_W_n_next : std_logic; + signal digit1_cs_b : std_logic; signal digit2_cs_b : std_logic; signal digit1 : std_logic_vector (7 downto 0); @@ -107,8 +139,8 @@ begin h_rdnw => h_rdnw, h_rst_b => h_rst_b ); - - inst_dcm_32_64 : entity work.dcm_32_64 port map ( + + inst_dcm_cpu_clk : entity work.dcm_32_64 port map ( CLKIN_IN => fastclk, CLK0_OUT => clk_cpu, CLK0_OUT1 => open, @@ -120,62 +152,58 @@ begin ADDR => cpu_addr(10 downto 0), DATA => rom_data_out ); - - GenT65Core: if UseT65Core generate - inst_T65 : entity work.T65 port map ( - Mode => "01", - Abort_n => '1', - SO_n => '1', - Res_n => RSTn_sync, - Enable => cpu_clken, - Clk => clk_cpu, - Rdy => '1', - IRQ_n => cpu_IRQ_n_sync, - NMI_n => cpu_NMI_n_sync, - R_W_n => cpu_R_W_n, - Sync => sync, - A(23 downto 0) => cpu_addr, - DI(7 downto 0) => cpu_din, - DO(7 downto 0) => cpu_dout - ); - end generate; - GenJensCore: if UseJensCore generate - Inst_r65c02_tc: entity work.r65c02_tc PORT MAP( - clk_clk_i => cpu_clken, - d_i => cpu_din, - irq_n_i => cpu_IRQ_n_sync, - nmi_n_i => cpu_NMI_n_sync, - rdy_i => '1', - rst_rst_n_i => RSTn_sync, - so_n_i => '1', - a_o => cpu_addr(15 downto 0), - d_o => cpu_dout, - rd_o => open, - sync_o => sync, - wr_n_o => cpu_R_W_n, - wr_o => open - ); - end generate; - GenAlanDCore: if UseAlanDCore generate inst_r65c02: entity work.r65c02 port map( - reset => RSTn_sync, - clk => clk_cpu, - enable => cpu_clken, - nmi_n => cpu_NMI_n_sync, - irq_n => cpu_IRQ_n_sync, - di => unsigned(cpu_din), - do => cpu_dout_us, - addr => cpu_addr_us(15 downto 0), - nwe => cpu_R_W_n, - sync => sync, - sync_irq => open - ); - cpu_dout <= std_logic_vector(cpu_dout_us); - cpu_addr <= std_logic_vector(cpu_addr_us); + reset => RSTn_sync, + clk => clk_cpu, + enable => cpu_clken, + nmi_n => cpu_NMI_n_sync, + irq_n => cpu_IRQ_n_sync, + di => unsigned(cpu_din), + do_next => cpu_dout_next_us, + do => cpu_dout_us, + addr_next => cpu_addr_next_us, + addr => cpu_addr_us, + nwe_next => cpu_R_W_n_next, + nwe => cpu_R_W_n, + sync => sync, + sync_irq => open + ); + + cpu_dout <= std_logic_vector(cpu_dout_us); + cpu_addr <= std_logic_vector(cpu_addr_us); + cpu_dout_next <= std_logic_vector(cpu_dout_next_us); + cpu_addr_next <= std_logic_vector(cpu_addr_next_us); end generate; + GenArletCore: if UseArletCore generate + inst_arlet_6502: entity work.cpu_65c02 port map( + clk => clk_cpu, + reset => not RSTn_sync, + AB => cpu_addr_next, + DI => cpu_din, + DO => cpu_dout_next, + WE => cpu_we_next, + IRQ => not cpu_IRQ_n_sync, + NMI => not cpu_NMI_n_sync, + RDY => cpu_clken + ); + + cpu_R_W_n_next <= not cpu_we_next; + + process(clk_cpu) + begin + if rising_edge(clk_cpu) then + if cpu_clken = '1' then + cpu_addr <= cpu_addr_next; + cpu_dout <= cpu_dout_next; + cpu_R_W_n <= cpu_R_W_n_next; + end if; + end if; + end process; + end generate; + inst_tube: entity work.tube port map ( h_addr => h_addr, h_cs_b => h_cs_b, @@ -197,14 +225,16 @@ begin Inst_RAM_64K: entity work.RAM_64K PORT MAP( clk => clk_cpu, - we_uP => ram_wr_int, - ce => '1', - addr_uP => cpu_addr(15 downto 0), - D_uP => cpu_dout, - Q_uP => ram_data_out + we_uP => int_ram_we_next, + ce => cpu_clken, + addr_uP => physical_addr_next(15 downto 0), + D_uP => cpu_dout_next, + Q_uP => int_ram_data_out ); - p_cs_b <= '0' when cpu_addr(15 downto 3) = "1111111011111" else '1'; + p_cs_b <= '0' when cpu_addr(15 downto 3) = 2#1111_1110_1111_1# else '1'; + + bank_cs_b <= '0' when cpu_addr(15 downto 3) = 2#1111_1110_1110_0# else '1'; rom_cs_b <= '0' when cpu_addr(15 downto 11) = "11111" and cpu_R_W_n = '1' and bootmode = '1' else '1'; @@ -212,40 +242,113 @@ begin digit2_cs_b <= '0' when rom_cs_b = '0' and cpu_addr(11 downto 0) = x"870" else '1'; -- Original: Acorn TUBE 65C102 Co-Processor - -- Updated: Acorn TUBE 32Mhz 65C102 Co-Pro + -- Updated: Acorn TUBE 64MHz 65C102 Co-Pro - digit1 <= x"33" when sw_out(1 downto 0) = "11" else + digit1 <= x"36" when sw_out(1 downto 0) = "11" else x"31" when sw_out(1 downto 0) = "10" else x"30"; - digit2 <= x"32" when sw_out(1 downto 0) = "11" else + digit2 <= x"38" when sw_out(1 downto 0) = "01" else x"36" when sw_out(1 downto 0) = "10" else - x"38" when sw_out(1 downto 0) = "01" else x"34"; - ram_cs_b <= '0' when p_cs_b = '1' and rom_cs_b = '1' else '1'; - - ram_wr_int <= ((not ram_cs_b) and (not cpu_R_W_n) and cpu_clken); + ram_cs_b <= '0' when bank_cs_b = '1' and p_cs_b = '1' and rom_cs_b = '1' else '1'; + + -- Look ahead versions of the chip selects + p_cs_b_next <= '0' when cpu_addr_next(15 downto 3) = 2#1111_1110_1111_1# else '1'; + bank_cs_b_next <= '0' when cpu_addr_next(15 downto 3) = 2#1111_1110_1110_0# else '1'; + rom_cs_b_next <= '0' when cpu_addr_next(15 downto 11) = "11111" and cpu_R_W_n_next = '1' and bootmode = '1' else '1'; + ram_cs_b_next <= '0' when p_cs_b_next = '1' and bank_cs_b_next = '1' and rom_cs_b_next = '1' else '1'; cpu_din <= - p_data_out when p_cs_b = '0' else - digit1 when digit1_cs_b = '0' else - digit2 when digit2_cs_b = '0' else - rom_data_out when rom_cs_b = '0' else - ram_data_out when ram_cs_b = '0' else + p_data_out when p_cs_b = '0' else + digit1 when digit1_cs_b = '0' else + digit2 when digit2_cs_b = '0' else + rom_data_out when rom_cs_b = '0' else + int_ram_data_out when int_ram = '1' else + ext_ram_data_out when ext_ram = '1' else x"f1"; - + + +-------------------------------------------------------- +-- bank registers +-------------------------------------------------------- + + process (clk_cpu, RSTn_sync) + begin + if RSTn_sync = '0' then + bank_reg(0) <= x"00"; + bank_reg(1) <= x"01"; + bank_reg(2) <= x"02"; + bank_reg(3) <= x"03"; + bank_reg(4) <= x"04"; + bank_reg(5) <= x"05"; + bank_reg(6) <= x"06"; + bank_reg(7) <= x"07"; + elsif rising_edge(clk_cpu) then + if cpu_clken = '1' then + int_ram <= int_ram_next; + ext_ram <= ext_ram_next; + if bank_cs_b = '0' and cpu_R_W_n = '0' and bootmode = '0' then + bank_reg(conv_integer(cpu_addr(2 downto 0))) <= cpu_dout; + end if; + end if; + end if; + end process; + + physical_addr_next <= bank_reg(conv_integer(cpu_addr_next(15 downto 13))) & cpu_addr_next(12 downto 0); + + int_ram_next <= '1' when ram_cs_b_next = '0' and physical_addr_next(20) = '0' else + '0'; + + ext_ram_next <= '1' when ram_cs_b_next = '0' and physical_addr_next(20) = '1' else + '0'; + + int_ram_we_next <= '1' when int_ram_next = '1' and cpu_R_W_n_next = '0' else + '0'; + + ext_ram_we_next <= '1' when ext_ram_next = '1' and cpu_R_W_n_next = '0' else + '0'; + -------------------------------------------------------- --- external Ram unused +-- external Ram +-- +-- note: dispite the naming, all control signals are active low -------------------------------------------------------- - ram_ub_b <= '1'; - ram_lb_b <= '1'; - ram_cs <= '1'; - ram_oe <= '1'; - ram_wr <= '1'; - ram_addr <= (others => '1'); - ram_data <= (others => '1'); + process (clk_cpu) + begin + if rising_edge(clk_cpu) then + if cpu_clken = '1' then + ext_ram_we <= ext_ram_we_next; + physical_addr <= physical_addr_next; + end if; + end if; + end process; + + -- With 4 wait states, an external RAM cycle lasts ~80ns + -- To provide some address setup/hold margin we generate + -- a gated write signal off the falling edge of the clock + -- which gives half a cycle of setup/hold margin + process (clk_cpu) + begin + if falling_edge(clk_cpu) then + if ext_ram_we = '1' and clken_counter > 0 then + ram_wr <= '0'; + else + ram_wr <= '1'; + end if; + end if; + end process; + ram_ub_b <= not physical_addr(19); + ram_lb_b <= physical_addr(19); + ram_cs <= not ext_ram; + ram_oe <= ext_ram_we; + ram_addr <= physical_addr(18 downto 0); + ram_data <= (cpu_dout & cpu_dout) when ext_ram_we = '1' else (others => 'Z'); + + ext_ram_data_out <= ram_data(15 downto 8) when physical_addr(19) = '1' else ram_data(7 downto 0); + -------------------------------------------------------- -- test signals -------------------------------------------------------- @@ -302,22 +405,44 @@ begin clk_gen : process(clk_cpu) begin if rising_edge(clk_cpu) then - clken_counter <= clken_counter + 1; - case "00" & sw_out(1 downto 0) is - when x"3" => - cpu_clken <= clken_counter(0); - when x"2" => - cpu_clken <= clken_counter(1) and clken_counter(0); - when x"1" => - cpu_clken <= clken_counter(2) and clken_counter(1) and clken_counter(0); - when x"0" => - cpu_clken <= clken_counter(3) and clken_counter(2) and clken_counter(1) and clken_counter(0); - when others => - cpu_clken <= clken_counter(0); - end case; + if clken_counter = 0 then + case sw_out(1 downto 0) is + when "11" => + if rom_cs_b_next = '0' then + -- Add one wait state for ROM accesses + clken_counter <= x"1"; + elsif ext_ram_next = '1' then + -- Add four wait states for external RAM accesses + clken_counter <= x"4"; + else + -- Full speed ahead! + clken_counter <= x"0"; + end if; + when "10" => + if ext_ram_next = '1' then + -- Add four wait states for external RAM accesses + clken_counter <= x"4"; + else + -- Quarter speed ahead! + clken_counter <= x"3"; + end if; + when "01" => + -- Running so slowly there is need to special case external RAM accesses + clken_counter <= x"7"; + when "00" => + -- Running so slowly there is need to special case external RAM accesses + clken_counter <= x"F"; + when others => + -- there are no others + end case; + else + clken_counter <= clken_counter - 1; + end if; end if; end process; + cpu_clken <= '1' when clken_counter = 0 else '0'; + end BEHAVIORAL; diff --git a/src/RAM/RAM_64K.vhd b/src/RAM/RAM_64K.vhd index c6e5754..5059d2c 100644 --- a/src/RAM/RAM_64K.vhd +++ b/src/RAM/RAM_64K.vhd @@ -24,11 +24,12 @@ begin process (clk) begin if rising_edge(clk) then - if (we_UP = '1' and ce = '1') then - RAM(conv_integer(addr_uP(15 downto 0))) <= D_up; + if ce = '1' then + if we_UP = '1' then + RAM(conv_integer(addr_uP(15 downto 0))) <= D_up; + end if; + Q_up <= RAM(conv_integer(addr_uP(15 downto 0))); end if; - Q_up <= RAM(conv_integer(addr_uP(15 downto 0))); - end if; end process; end BEHAVIORAL; diff --git a/src/ROM/tuberom_65c102_banner_distram.vhd b/src/ROM/tuberom_65c102_banner_distram.vhd new file mode 100644 index 0000000..7b5f20c --- /dev/null +++ b/src/ROM/tuberom_65c102_banner_distram.vhd @@ -0,0 +1,2084 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tuberom_65c102_banner is + port ( + CLK : in std_logic; + ADDR : in std_logic_vector(10 downto 0); + DATA : out std_logic_vector(7 downto 0) + ); +end; + +architecture RTL of tuberom_65c102_banner is + + type ram_type is array (0 to 2047) of std_logic_vector (7 downto 0); + + signal RAM : ram_type := ( + 16#000# => x"a2", + 16#001# => x"00", + 16#002# => x"bd", + 16#003# => x"00", + 16#004# => x"ff", + 16#005# => x"9d", + 16#006# => x"00", + 16#007# => x"ff", + 16#008# => x"ca", + 16#009# => x"d0", + 16#00a# => x"f7", + 16#00b# => x"a2", + 16#00c# => x"36", + 16#00d# => x"bd", + 16#00e# => x"80", + 16#00f# => x"ff", + 16#010# => x"9d", + 16#011# => x"00", + 16#012# => x"02", + 16#013# => x"ca", + 16#014# => x"10", + 16#015# => x"f7", + 16#016# => x"9a", + 16#017# => x"a2", + 16#018# => x"f0", + 16#019# => x"bd", + 16#01a# => x"ff", + 16#01b# => x"fd", + 16#01c# => x"9d", + 16#01d# => x"ff", + 16#01e# => x"fd", + 16#01f# => x"ca", + 16#020# => x"d0", + 16#021# => x"f7", + 16#022# => x"a0", + 16#023# => x"00", + 16#024# => x"84", + 16#025# => x"f8", + 16#026# => x"a9", + 16#027# => x"f8", + 16#028# => x"85", + 16#029# => x"f9", + 16#02a# => x"b1", + 16#02b# => x"f8", + 16#02c# => x"91", + 16#02d# => x"f8", + 16#02e# => x"c8", + 16#02f# => x"d0", + 16#030# => x"f9", + 16#031# => x"e6", + 16#032# => x"f9", + 16#033# => x"a5", + 16#034# => x"f9", + 16#035# => x"c9", + 16#036# => x"fe", + 16#037# => x"d0", + 16#038# => x"f1", + 16#039# => x"a2", + 16#03a# => x"10", + 16#03b# => x"bd", + 16#03c# => x"59", + 16#03d# => x"f8", + 16#03e# => x"9d", + 16#03f# => x"00", + 16#040# => x"01", + 16#041# => x"ca", + 16#042# => x"10", + 16#043# => x"f7", + 16#044# => x"a5", + 16#045# => x"ee", + 16#046# => x"85", + 16#047# => x"f6", + 16#048# => x"a5", + 16#049# => x"ef", + 16#04a# => x"85", + 16#04b# => x"f7", + 16#04c# => x"a9", + 16#04d# => x"00", + 16#04e# => x"85", + 16#04f# => x"ff", + 16#050# => x"85", + 16#051# => x"f2", + 16#052# => x"a9", + 16#053# => x"f8", + 16#054# => x"85", + 16#055# => x"f3", + 16#056# => x"4c", + 16#057# => x"00", + 16#058# => x"01", + 16#059# => x"ad", + 16#05a# => x"f8", + 16#05b# => x"fe", + 16#05c# => x"58", + 16#05d# => x"4c", + 16#05e# => x"60", + 16#05f# => x"f8", + 16#060# => x"20", + 16#061# => x"a5", + 16#062# => x"fe", + 16#063# => x"0a", + 16#064# => x"41", + 16#065# => x"63", + 16#066# => x"6f", + 16#067# => x"72", + 16#068# => x"6e", + 16#069# => x"20", + 16#06a# => x"54", + 16#06b# => x"55", + 16#06c# => x"42", + 16#06d# => x"45", + 16#06e# => x"20", + 16#06f# => x"3f", + 16#070# => x"3f", + 16#071# => x"4d", + 16#072# => x"48", + 16#073# => x"7a", + 16#074# => x"20", + 16#075# => x"36", + 16#076# => x"35", + 16#077# => x"43", + 16#078# => x"31", + 16#079# => x"30", + 16#07a# => x"32", + 16#07b# => x"20", + 16#07c# => x"43", + 16#07d# => x"6f", + 16#07e# => x"2d", + 16#07f# => x"50", + 16#080# => x"72", + 16#081# => x"6f", + 16#082# => x"0a", + 16#083# => x"0a", + 16#084# => x"0d", + 16#085# => x"00", + 16#086# => x"ea", + 16#087# => x"a9", + 16#088# => x"98", + 16#089# => x"8d", + 16#08a# => x"5e", + 16#08b# => x"f8", + 16#08c# => x"a9", + 16#08d# => x"f8", + 16#08e# => x"8d", + 16#08f# => x"5f", + 16#090# => x"f8", + 16#091# => x"20", + 16#092# => x"80", + 16#093# => x"f9", + 16#094# => x"c9", + 16#095# => x"80", + 16#096# => x"f0", + 16#097# => x"28", + 16#098# => x"a9", + 16#099# => x"2a", + 16#09a# => x"20", + 16#09b# => x"ee", + 16#09c# => x"ff", + 16#09d# => x"a2", + 16#09e# => x"68", + 16#09f# => x"a0", + 16#0a0# => x"f9", + 16#0a1# => x"a9", + 16#0a2# => x"00", + 16#0a3# => x"20", + 16#0a4# => x"f1", + 16#0a5# => x"ff", + 16#0a6# => x"b0", + 16#0a7# => x"0a", + 16#0a8# => x"a2", + 16#0a9# => x"36", + 16#0aa# => x"a0", + 16#0ab# => x"02", + 16#0ac# => x"20", + 16#0ad# => x"f7", + 16#0ae# => x"ff", + 16#0af# => x"4c", + 16#0b0# => x"98", + 16#0b1# => x"f8", + 16#0b2# => x"a9", + 16#0b3# => x"7e", + 16#0b4# => x"20", + 16#0b5# => x"f4", + 16#0b6# => x"ff", + 16#0b7# => x"00", + 16#0b8# => x"11", + 16#0b9# => x"45", + 16#0ba# => x"73", + 16#0bb# => x"63", + 16#0bc# => x"61", + 16#0bd# => x"70", + 16#0be# => x"65", + 16#0bf# => x"00", + 16#0c0# => x"a5", + 16#0c1# => x"f6", + 16#0c2# => x"85", + 16#0c3# => x"ee", + 16#0c4# => x"85", + 16#0c5# => x"f2", + 16#0c6# => x"a5", + 16#0c7# => x"f7", + 16#0c8# => x"85", + 16#0c9# => x"ef", + 16#0ca# => x"85", + 16#0cb# => x"f3", + 16#0cc# => x"a0", + 16#0cd# => x"07", + 16#0ce# => x"b1", + 16#0cf# => x"ee", + 16#0d0# => x"d8", + 16#0d1# => x"18", + 16#0d2# => x"65", + 16#0d3# => x"ee", + 16#0d4# => x"85", + 16#0d5# => x"fd", + 16#0d6# => x"a9", + 16#0d7# => x"00", + 16#0d8# => x"65", + 16#0d9# => x"ef", + 16#0da# => x"85", + 16#0db# => x"fe", + 16#0dc# => x"a0", + 16#0dd# => x"00", + 16#0de# => x"b1", + 16#0df# => x"fd", + 16#0e0# => x"d0", + 16#0e1# => x"23", + 16#0e2# => x"c8", + 16#0e3# => x"b1", + 16#0e4# => x"fd", + 16#0e5# => x"c9", + 16#0e6# => x"28", + 16#0e7# => x"d0", + 16#0e8# => x"1c", + 16#0e9# => x"c8", + 16#0ea# => x"b1", + 16#0eb# => x"fd", + 16#0ec# => x"c9", + 16#0ed# => x"43", + 16#0ee# => x"d0", + 16#0ef# => x"15", + 16#0f0# => x"c8", + 16#0f1# => x"b1", + 16#0f2# => x"fd", + 16#0f3# => x"c9", + 16#0f4# => x"29", + 16#0f5# => x"d0", + 16#0f6# => x"0e", + 16#0f7# => x"a0", + 16#0f8# => x"06", + 16#0f9# => x"b1", + 16#0fa# => x"ee", + 16#0fb# => x"29", + 16#0fc# => x"4f", + 16#0fd# => x"c9", + 16#0fe# => x"40", + 16#0ff# => x"90", + 16#100# => x"09", + 16#101# => x"29", + 16#102# => x"0d", + 16#103# => x"d0", + 16#104# => x"28", + 16#105# => x"a9", + 16#106# => x"01", + 16#107# => x"6c", + 16#108# => x"f2", + 16#109# => x"00", + 16#10a# => x"a9", + 16#10b# => x"50", + 16#10c# => x"8d", + 16#10d# => x"02", + 16#10e# => x"02", + 16#10f# => x"a9", + 16#110# => x"f9", + 16#111# => x"8d", + 16#112# => x"03", + 16#113# => x"02", + 16#114# => x"00", + 16#115# => x"00", + 16#116# => x"54", + 16#117# => x"68", + 16#118# => x"69", + 16#119# => x"73", + 16#11a# => x"20", + 16#11b# => x"69", + 16#11c# => x"73", + 16#11d# => x"20", + 16#11e# => x"6e", + 16#11f# => x"6f", + 16#120# => x"74", + 16#121# => x"20", + 16#122# => x"61", + 16#123# => x"20", + 16#124# => x"6c", + 16#125# => x"61", + 16#126# => x"6e", + 16#127# => x"67", + 16#128# => x"75", + 16#129# => x"61", + 16#12a# => x"67", + 16#12b# => x"65", + 16#12c# => x"00", + 16#12d# => x"a9", + 16#12e# => x"50", + 16#12f# => x"8d", + 16#130# => x"02", + 16#131# => x"02", + 16#132# => x"a9", + 16#133# => x"f9", + 16#134# => x"8d", + 16#135# => x"03", + 16#136# => x"02", + 16#137# => x"00", + 16#138# => x"00", + 16#139# => x"49", + 16#13a# => x"20", + 16#13b# => x"63", + 16#13c# => x"61", + 16#13d# => x"6e", + 16#13e# => x"6e", + 16#13f# => x"6f", + 16#140# => x"74", + 16#141# => x"20", + 16#142# => x"72", + 16#143# => x"75", + 16#144# => x"6e", + 16#145# => x"20", + 16#146# => x"74", + 16#147# => x"68", + 16#148# => x"69", + 16#149# => x"73", + 16#14a# => x"20", + 16#14b# => x"63", + 16#14c# => x"6f", + 16#14d# => x"64", + 16#14e# => x"65", + 16#14f# => x"00", + 16#150# => x"a2", + 16#151# => x"ff", + 16#152# => x"9a", + 16#153# => x"20", + 16#154# => x"e7", + 16#155# => x"ff", + 16#156# => x"a0", + 16#157# => x"01", + 16#158# => x"b1", + 16#159# => x"fd", + 16#15a# => x"f0", + 16#15b# => x"06", + 16#15c# => x"20", + 16#15d# => x"ee", + 16#15e# => x"ff", + 16#15f# => x"c8", + 16#160# => x"d0", + 16#161# => x"f6", + 16#162# => x"20", + 16#163# => x"e7", + 16#164# => x"ff", + 16#165# => x"4c", + 16#166# => x"98", + 16#167# => x"f8", + 16#168# => x"36", + 16#169# => x"02", + 16#16a# => x"ca", + 16#16b# => x"20", + 16#16c# => x"ff", + 16#16d# => x"2c", + 16#16e# => x"f8", + 16#16f# => x"fe", + 16#170# => x"ea", + 16#171# => x"50", + 16#172# => x"fa", + 16#173# => x"8d", + 16#174# => x"f9", + 16#175# => x"fe", + 16#176# => x"60", + 16#177# => x"a9", + 16#178# => x"00", + 16#179# => x"20", + 16#17a# => x"57", + 16#17b# => x"fc", + 16#17c# => x"20", + 16#17d# => x"80", + 16#17e# => x"f9", + 16#17f# => x"0a", + 16#180# => x"2c", + 16#181# => x"fa", + 16#182# => x"fe", + 16#183# => x"10", + 16#184# => x"fb", + 16#185# => x"ad", + 16#186# => x"fb", + 16#187# => x"fe", + 16#188# => x"60", + 16#189# => x"c8", + 16#18a# => x"b1", + 16#18b# => x"f8", + 16#18c# => x"c9", + 16#18d# => x"20", + 16#18e# => x"f0", + 16#18f# => x"f9", + 16#190# => x"60", + 16#191# => x"a2", + 16#192# => x"00", + 16#193# => x"86", + 16#194# => x"f0", + 16#195# => x"86", + 16#196# => x"f1", + 16#197# => x"b1", + 16#198# => x"f8", + 16#199# => x"c9", + 16#19a# => x"30", + 16#19b# => x"90", + 16#19c# => x"1f", + 16#19d# => x"c9", + 16#19e# => x"3a", + 16#19f# => x"90", + 16#1a0# => x"0a", + 16#1a1# => x"29", + 16#1a2# => x"df", + 16#1a3# => x"e9", + 16#1a4# => x"07", + 16#1a5# => x"90", + 16#1a6# => x"15", + 16#1a7# => x"c9", + 16#1a8# => x"40", + 16#1a9# => x"b0", + 16#1aa# => x"11", + 16#1ab# => x"0a", + 16#1ac# => x"0a", + 16#1ad# => x"0a", + 16#1ae# => x"0a", + 16#1af# => x"a2", + 16#1b0# => x"03", + 16#1b1# => x"0a", + 16#1b2# => x"26", + 16#1b3# => x"f0", + 16#1b4# => x"26", + 16#1b5# => x"f1", + 16#1b6# => x"ca", + 16#1b7# => x"10", + 16#1b8# => x"f8", + 16#1b9# => x"c8", + 16#1ba# => x"d0", + 16#1bb# => x"db", + 16#1bc# => x"60", + 16#1bd# => x"86", + 16#1be# => x"f8", + 16#1bf# => x"84", + 16#1c0# => x"f9", + 16#1c1# => x"a0", + 16#1c2# => x"00", + 16#1c3# => x"2c", + 16#1c4# => x"fa", + 16#1c5# => x"fe", + 16#1c6# => x"50", + 16#1c7# => x"fb", + 16#1c8# => x"b1", + 16#1c9# => x"f8", + 16#1ca# => x"8d", + 16#1cb# => x"fb", + 16#1cc# => x"fe", + 16#1cd# => x"c8", + 16#1ce# => x"c9", + 16#1cf# => x"0d", + 16#1d0# => x"d0", + 16#1d1# => x"f1", + 16#1d2# => x"a4", + 16#1d3# => x"f9", + 16#1d4# => x"60", + 16#1d5# => x"48", + 16#1d6# => x"86", + 16#1d7# => x"f8", + 16#1d8# => x"84", + 16#1d9# => x"f9", + 16#1da# => x"a0", + 16#1db# => x"00", + 16#1dc# => x"20", + 16#1dd# => x"8a", + 16#1de# => x"f9", + 16#1df# => x"c8", + 16#1e0# => x"c9", + 16#1e1# => x"2a", + 16#1e2# => x"f0", + 16#1e3# => x"f8", + 16#1e4# => x"29", + 16#1e5# => x"df", + 16#1e6# => x"aa", + 16#1e7# => x"b1", + 16#1e8# => x"f8", + 16#1e9# => x"e0", + 16#1ea# => x"47", + 16#1eb# => x"f0", + 16#1ec# => x"5e", + 16#1ed# => x"e0", + 16#1ee# => x"48", + 16#1ef# => x"d0", + 16#1f0# => x"49", + 16#1f1# => x"c9", + 16#1f2# => x"2e", + 16#1f3# => x"f0", + 16#1f4# => x"2d", + 16#1f5# => x"29", + 16#1f6# => x"df", + 16#1f7# => x"c9", + 16#1f8# => x"45", + 16#1f9# => x"d0", + 16#1fa# => x"3f", + 16#1fb# => x"c8", + 16#1fc# => x"b1", + 16#1fd# => x"f8", + 16#1fe# => x"c9", + 16#1ff# => x"2e", + 16#200# => x"f0", + 16#201# => x"20", + 16#202# => x"29", + 16#203# => x"df", + 16#204# => x"c9", + 16#205# => x"4c", + 16#206# => x"d0", + 16#207# => x"32", + 16#208# => x"c8", + 16#209# => x"b1", + 16#20a# => x"f8", + 16#20b# => x"c9", + 16#20c# => x"2e", + 16#20d# => x"f0", + 16#20e# => x"13", + 16#20f# => x"29", + 16#210# => x"df", + 16#211# => x"c9", + 16#212# => x"50", + 16#213# => x"d0", + 16#214# => x"25", + 16#215# => x"c8", + 16#216# => x"b1", + 16#217# => x"f8", + 16#218# => x"29", + 16#219# => x"df", + 16#21a# => x"c9", + 16#21b# => x"41", + 16#21c# => x"90", + 16#21d# => x"04", + 16#21e# => x"c9", + 16#21f# => x"5b", + 16#220# => x"90", + 16#221# => x"18", + 16#222# => x"20", + 16#223# => x"a5", + 16#224# => x"fe", + 16#225# => x"0a", + 16#226# => x"0d", + 16#227# => x"36", + 16#228# => x"35", + 16#229# => x"43", + 16#22a# => x"31", + 16#22b# => x"30", + 16#22c# => x"32", + 16#22d# => x"20", + 16#22e# => x"54", + 16#22f# => x"55", + 16#230# => x"42", + 16#231# => x"45", + 16#232# => x"20", + 16#233# => x"31", + 16#234# => x"2e", + 16#235# => x"31", + 16#236# => x"30", + 16#237# => x"0a", + 16#238# => x"0d", + 16#239# => x"ea", + 16#23a# => x"a9", + 16#23b# => x"02", + 16#23c# => x"20", + 16#23d# => x"57", + 16#23e# => x"fc", + 16#23f# => x"20", + 16#240# => x"c1", + 16#241# => x"f9", + 16#242# => x"20", + 16#243# => x"80", + 16#244# => x"f9", + 16#245# => x"c9", + 16#246# => x"80", + 16#247# => x"f0", + 16#248# => x"20", + 16#249# => x"68", + 16#24a# => x"60", + 16#24b# => x"29", + 16#24c# => x"df", + 16#24d# => x"c9", + 16#24e# => x"4f", + 16#24f# => x"d0", + 16#250# => x"e9", + 16#251# => x"20", + 16#252# => x"89", + 16#253# => x"f9", + 16#254# => x"20", + 16#255# => x"91", + 16#256# => x"f9", + 16#257# => x"20", + 16#258# => x"8a", + 16#259# => x"f9", + 16#25a# => x"c9", + 16#25b# => x"0d", + 16#25c# => x"d0", + 16#25d# => x"dc", + 16#25e# => x"8a", + 16#25f# => x"f0", + 16#260# => x"08", + 16#261# => x"a5", + 16#262# => x"f0", + 16#263# => x"85", + 16#264# => x"f6", + 16#265# => x"a5", + 16#266# => x"f1", + 16#267# => x"85", + 16#268# => x"f7", + 16#269# => x"a5", + 16#26a# => x"ef", + 16#26b# => x"48", + 16#26c# => x"a5", + 16#26d# => x"ee", + 16#26e# => x"48", + 16#26f# => x"20", + 16#270# => x"c0", + 16#271# => x"f8", + 16#272# => x"68", + 16#273# => x"85", + 16#274# => x"ee", + 16#275# => x"85", + 16#276# => x"f2", + 16#277# => x"68", + 16#278# => x"85", + 16#279# => x"ef", + 16#27a# => x"85", + 16#27b# => x"f3", + 16#27c# => x"68", + 16#27d# => x"60", + 16#27e# => x"f0", + 16#27f# => x"c2", + 16#280# => x"c9", + 16#281# => x"80", + 16#282# => x"b0", + 16#283# => x"25", + 16#284# => x"48", + 16#285# => x"a9", + 16#286# => x"04", + 16#287# => x"2c", + 16#288# => x"fa", + 16#289# => x"fe", + 16#28a# => x"50", + 16#28b# => x"fb", + 16#28c# => x"8d", + 16#28d# => x"fb", + 16#28e# => x"fe", + 16#28f# => x"2c", + 16#290# => x"fa", + 16#291# => x"fe", + 16#292# => x"50", + 16#293# => x"fb", + 16#294# => x"8e", + 16#295# => x"fb", + 16#296# => x"fe", + 16#297# => x"68", + 16#298# => x"2c", + 16#299# => x"fa", + 16#29a# => x"fe", + 16#29b# => x"50", + 16#29c# => x"fb", + 16#29d# => x"8d", + 16#29e# => x"fb", + 16#29f# => x"fe", + 16#2a0# => x"2c", + 16#2a1# => x"fa", + 16#2a2# => x"fe", + 16#2a3# => x"10", + 16#2a4# => x"fb", + 16#2a5# => x"ae", + 16#2a6# => x"fb", + 16#2a7# => x"fe", + 16#2a8# => x"60", + 16#2a9# => x"c9", + 16#2aa# => x"82", + 16#2ab# => x"f0", + 16#2ac# => x"5a", + 16#2ad# => x"c9", + 16#2ae# => x"83", + 16#2af# => x"f0", + 16#2b0# => x"51", + 16#2b1# => x"c9", + 16#2b2# => x"84", + 16#2b3# => x"f0", + 16#2b4# => x"48", + 16#2b5# => x"48", + 16#2b6# => x"a9", + 16#2b7# => x"06", + 16#2b8# => x"2c", + 16#2b9# => x"fa", + 16#2ba# => x"fe", + 16#2bb# => x"50", + 16#2bc# => x"fb", + 16#2bd# => x"8d", + 16#2be# => x"fb", + 16#2bf# => x"fe", + 16#2c0# => x"2c", + 16#2c1# => x"fa", + 16#2c2# => x"fe", + 16#2c3# => x"50", + 16#2c4# => x"fb", + 16#2c5# => x"8e", + 16#2c6# => x"fb", + 16#2c7# => x"fe", + 16#2c8# => x"2c", + 16#2c9# => x"fa", + 16#2ca# => x"fe", + 16#2cb# => x"50", + 16#2cc# => x"fb", + 16#2cd# => x"8c", + 16#2ce# => x"fb", + 16#2cf# => x"fe", + 16#2d0# => x"68", + 16#2d1# => x"2c", + 16#2d2# => x"fa", + 16#2d3# => x"fe", + 16#2d4# => x"50", + 16#2d5# => x"fb", + 16#2d6# => x"8d", + 16#2d7# => x"fb", + 16#2d8# => x"fe", + 16#2d9# => x"c9", + 16#2da# => x"8e", + 16#2db# => x"f0", + 16#2dc# => x"a1", + 16#2dd# => x"c9", + 16#2de# => x"9d", + 16#2df# => x"f0", + 16#2e0# => x"1b", + 16#2e1# => x"48", + 16#2e2# => x"2c", + 16#2e3# => x"fa", + 16#2e4# => x"fe", + 16#2e5# => x"10", + 16#2e6# => x"fb", + 16#2e7# => x"ad", + 16#2e8# => x"fb", + 16#2e9# => x"fe", + 16#2ea# => x"0a", + 16#2eb# => x"68", + 16#2ec# => x"2c", + 16#2ed# => x"fa", + 16#2ee# => x"fe", + 16#2ef# => x"10", + 16#2f0# => x"fb", + 16#2f1# => x"ac", + 16#2f2# => x"fb", + 16#2f3# => x"fe", + 16#2f4# => x"2c", + 16#2f5# => x"fa", + 16#2f6# => x"fe", + 16#2f7# => x"10", + 16#2f8# => x"fb", + 16#2f9# => x"ae", + 16#2fa# => x"fb", + 16#2fb# => x"fe", + 16#2fc# => x"60", + 16#2fd# => x"a6", + 16#2fe# => x"f2", + 16#2ff# => x"a4", + 16#300# => x"f3", + 16#301# => x"60", + 16#302# => x"a2", + 16#303# => x"00", + 16#304# => x"a0", + 16#305# => x"08", + 16#306# => x"60", + 16#307# => x"a2", + 16#308# => x"00", + 16#309# => x"a0", + 16#30a# => x"00", + 16#30b# => x"60", + 16#30c# => x"86", + 16#30d# => x"f8", + 16#30e# => x"84", + 16#30f# => x"f9", + 16#310# => x"a8", + 16#311# => x"f0", + 16#312# => x"71", + 16#313# => x"48", + 16#314# => x"a0", + 16#315# => x"08", + 16#316# => x"2c", + 16#317# => x"fa", + 16#318# => x"fe", + 16#319# => x"50", + 16#31a# => x"fb", + 16#31b# => x"8c", + 16#31c# => x"fb", + 16#31d# => x"fe", + 16#31e# => x"2c", + 16#31f# => x"fa", + 16#320# => x"fe", + 16#321# => x"50", + 16#322# => x"fb", + 16#323# => x"8d", + 16#324# => x"fb", + 16#325# => x"fe", + 16#326# => x"aa", + 16#327# => x"10", + 16#328# => x"08", + 16#329# => x"a0", + 16#32a# => x"00", + 16#32b# => x"b1", + 16#32c# => x"f8", + 16#32d# => x"a8", + 16#32e# => x"4c", + 16#32f# => x"3a", + 16#330# => x"fb", + 16#331# => x"bc", + 16#332# => x"c9", + 16#333# => x"fc", + 16#334# => x"e0", + 16#335# => x"15", + 16#336# => x"90", + 16#337# => x"02", + 16#338# => x"a0", + 16#339# => x"10", + 16#33a# => x"2c", + 16#33b# => x"fa", + 16#33c# => x"fe", + 16#33d# => x"50", + 16#33e# => x"fb", + 16#33f# => x"8c", + 16#340# => x"fb", + 16#341# => x"fe", + 16#342# => x"88", + 16#343# => x"30", + 16#344# => x"0d", + 16#345# => x"2c", + 16#346# => x"fa", + 16#347# => x"fe", + 16#348# => x"50", + 16#349# => x"fb", + 16#34a# => x"b1", + 16#34b# => x"f8", + 16#34c# => x"8d", + 16#34d# => x"fb", + 16#34e# => x"fe", + 16#34f# => x"88", + 16#350# => x"10", + 16#351# => x"f3", + 16#352# => x"8a", + 16#353# => x"10", + 16#354# => x"08", + 16#355# => x"a0", + 16#356# => x"01", + 16#357# => x"b1", + 16#358# => x"f8", + 16#359# => x"a8", + 16#35a# => x"4c", + 16#35b# => x"66", + 16#35c# => x"fb", + 16#35d# => x"bc", + 16#35e# => x"dd", + 16#35f# => x"fc", + 16#360# => x"e0", + 16#361# => x"15", + 16#362# => x"90", + 16#363# => x"02", + 16#364# => x"a0", + 16#365# => x"10", + 16#366# => x"2c", + 16#367# => x"fa", + 16#368# => x"fe", + 16#369# => x"50", + 16#36a# => x"fb", + 16#36b# => x"8c", + 16#36c# => x"fb", + 16#36d# => x"fe", + 16#36e# => x"88", + 16#36f# => x"30", + 16#370# => x"0d", + 16#371# => x"2c", + 16#372# => x"fa", + 16#373# => x"fe", + 16#374# => x"10", + 16#375# => x"fb", + 16#376# => x"ad", + 16#377# => x"fb", + 16#378# => x"fe", + 16#379# => x"91", + 16#37a# => x"f8", + 16#37b# => x"88", + 16#37c# => x"10", + 16#37d# => x"f3", + 16#37e# => x"a4", + 16#37f# => x"f9", + 16#380# => x"a6", + 16#381# => x"f8", + 16#382# => x"68", + 16#383# => x"60", + 16#384# => x"a9", + 16#385# => x"0a", + 16#386# => x"20", + 16#387# => x"57", + 16#388# => x"fc", + 16#389# => x"a0", + 16#38a# => x"04", + 16#38b# => x"2c", + 16#38c# => x"fa", + 16#38d# => x"fe", + 16#38e# => x"50", + 16#38f# => x"fb", + 16#390# => x"b1", + 16#391# => x"f8", + 16#392# => x"8d", + 16#393# => x"fb", + 16#394# => x"fe", + 16#395# => x"88", + 16#396# => x"c0", + 16#397# => x"01", + 16#398# => x"d0", + 16#399# => x"f1", + 16#39a# => x"a9", + 16#39b# => x"07", + 16#39c# => x"20", + 16#39d# => x"57", + 16#39e# => x"fc", + 16#39f# => x"b1", + 16#3a0# => x"f8", + 16#3a1# => x"48", + 16#3a2# => x"88", + 16#3a3# => x"2c", + 16#3a4# => x"fa", + 16#3a5# => x"fe", + 16#3a6# => x"50", + 16#3a7# => x"fb", + 16#3a8# => x"8c", + 16#3a9# => x"fb", + 16#3aa# => x"fe", + 16#3ab# => x"b1", + 16#3ac# => x"f8", + 16#3ad# => x"48", + 16#3ae# => x"a2", + 16#3af# => x"ff", + 16#3b0# => x"20", + 16#3b1# => x"80", + 16#3b2# => x"f9", + 16#3b3# => x"c9", + 16#3b4# => x"80", + 16#3b5# => x"b0", + 16#3b6# => x"1d", + 16#3b7# => x"68", + 16#3b8# => x"85", + 16#3b9# => x"f8", + 16#3ba# => x"68", + 16#3bb# => x"85", + 16#3bc# => x"f9", + 16#3bd# => x"a0", + 16#3be# => x"00", + 16#3bf# => x"2c", + 16#3c0# => x"fa", + 16#3c1# => x"fe", + 16#3c2# => x"10", + 16#3c3# => x"fb", + 16#3c4# => x"ad", + 16#3c5# => x"fb", + 16#3c6# => x"fe", + 16#3c7# => x"91", + 16#3c8# => x"f8", + 16#3c9# => x"c8", + 16#3ca# => x"c9", + 16#3cb# => x"0d", + 16#3cc# => x"d0", + 16#3cd# => x"f1", + 16#3ce# => x"a9", + 16#3cf# => x"00", + 16#3d0# => x"88", + 16#3d1# => x"18", + 16#3d2# => x"e8", + 16#3d3# => x"60", + 16#3d4# => x"68", + 16#3d5# => x"68", + 16#3d6# => x"a9", + 16#3d7# => x"00", + 16#3d8# => x"60", + 16#3d9# => x"48", + 16#3da# => x"a9", + 16#3db# => x"0c", + 16#3dc# => x"20", + 16#3dd# => x"57", + 16#3de# => x"fc", + 16#3df# => x"2c", + 16#3e0# => x"fa", + 16#3e1# => x"fe", + 16#3e2# => x"50", + 16#3e3# => x"fb", + 16#3e4# => x"8c", + 16#3e5# => x"fb", + 16#3e6# => x"fe", + 16#3e7# => x"b5", + 16#3e8# => x"03", + 16#3e9# => x"20", + 16#3ea# => x"57", + 16#3eb# => x"fc", + 16#3ec# => x"b5", + 16#3ed# => x"02", + 16#3ee# => x"20", + 16#3ef# => x"57", + 16#3f0# => x"fc", + 16#3f1# => x"b5", + 16#3f2# => x"01", + 16#3f3# => x"20", + 16#3f4# => x"57", + 16#3f5# => x"fc", + 16#3f6# => x"b5", + 16#3f7# => x"00", + 16#3f8# => x"20", + 16#3f9# => x"57", + 16#3fa# => x"fc", + 16#3fb# => x"68", + 16#3fc# => x"20", + 16#3fd# => x"57", + 16#3fe# => x"fc", + 16#3ff# => x"20", + 16#400# => x"80", + 16#401# => x"f9", + 16#402# => x"48", + 16#403# => x"20", + 16#404# => x"80", + 16#405# => x"f9", + 16#406# => x"95", + 16#407# => x"03", + 16#408# => x"20", + 16#409# => x"80", + 16#40a# => x"f9", + 16#40b# => x"95", + 16#40c# => x"02", + 16#40d# => x"20", + 16#40e# => x"80", + 16#40f# => x"f9", + 16#410# => x"95", + 16#411# => x"01", + 16#412# => x"20", + 16#413# => x"80", + 16#414# => x"f9", + 16#415# => x"95", + 16#416# => x"00", + 16#417# => x"68", + 16#418# => x"60", + 16#419# => x"48", + 16#41a# => x"a9", + 16#41b# => x"12", + 16#41c# => x"20", + 16#41d# => x"57", + 16#41e# => x"fc", + 16#41f# => x"68", + 16#420# => x"20", + 16#421# => x"57", + 16#422# => x"fc", + 16#423# => x"c9", + 16#424# => x"00", + 16#425# => x"d0", + 16#426# => x"0a", + 16#427# => x"48", + 16#428# => x"98", + 16#429# => x"20", + 16#42a# => x"57", + 16#42b# => x"fc", + 16#42c# => x"20", + 16#42d# => x"80", + 16#42e# => x"f9", + 16#42f# => x"68", + 16#430# => x"60", + 16#431# => x"20", + 16#432# => x"bd", + 16#433# => x"f9", + 16#434# => x"4c", + 16#435# => x"80", + 16#436# => x"f9", + 16#437# => x"a9", + 16#438# => x"0e", + 16#439# => x"20", + 16#43a# => x"57", + 16#43b# => x"fc", + 16#43c# => x"98", + 16#43d# => x"20", + 16#43e# => x"57", + 16#43f# => x"fc", + 16#440# => x"4c", + 16#441# => x"7c", + 16#442# => x"f9", + 16#443# => x"48", + 16#444# => x"a9", + 16#445# => x"10", + 16#446# => x"20", + 16#447# => x"57", + 16#448# => x"fc", + 16#449# => x"98", + 16#44a# => x"20", + 16#44b# => x"57", + 16#44c# => x"fc", + 16#44d# => x"68", + 16#44e# => x"20", + 16#44f# => x"57", + 16#450# => x"fc", + 16#451# => x"48", + 16#452# => x"20", + 16#453# => x"80", + 16#454# => x"f9", + 16#455# => x"68", + 16#456# => x"60", + 16#457# => x"2c", + 16#458# => x"fa", + 16#459# => x"fe", + 16#45a# => x"50", + 16#45b# => x"fb", + 16#45c# => x"8d", + 16#45d# => x"fb", + 16#45e# => x"fe", + 16#45f# => x"60", + 16#460# => x"84", + 16#461# => x"fb", + 16#462# => x"86", + 16#463# => x"fa", + 16#464# => x"48", + 16#465# => x"a9", + 16#466# => x"14", + 16#467# => x"20", + 16#468# => x"57", + 16#469# => x"fc", + 16#46a# => x"a0", + 16#46b# => x"11", + 16#46c# => x"b1", + 16#46d# => x"fa", + 16#46e# => x"20", + 16#46f# => x"57", + 16#470# => x"fc", + 16#471# => x"88", + 16#472# => x"c0", + 16#473# => x"01", + 16#474# => x"d0", + 16#475# => x"f6", + 16#476# => x"88", + 16#477# => x"b1", + 16#478# => x"fa", + 16#479# => x"aa", + 16#47a# => x"c8", + 16#47b# => x"b1", + 16#47c# => x"fa", + 16#47d# => x"a8", + 16#47e# => x"20", + 16#47f# => x"bd", + 16#480# => x"f9", + 16#481# => x"68", + 16#482# => x"20", + 16#483# => x"57", + 16#484# => x"fc", + 16#485# => x"20", + 16#486# => x"80", + 16#487# => x"f9", + 16#488# => x"48", + 16#489# => x"a0", + 16#48a# => x"11", + 16#48b# => x"20", + 16#48c# => x"80", + 16#48d# => x"f9", + 16#48e# => x"91", + 16#48f# => x"fa", + 16#490# => x"88", + 16#491# => x"c0", + 16#492# => x"01", + 16#493# => x"d0", + 16#494# => x"f6", + 16#495# => x"a4", + 16#496# => x"fb", + 16#497# => x"a6", + 16#498# => x"fa", + 16#499# => x"68", + 16#49a# => x"60", + 16#49b# => x"84", + 16#49c# => x"fb", + 16#49d# => x"86", + 16#49e# => x"fa", + 16#49f# => x"48", + 16#4a0# => x"a9", + 16#4a1# => x"16", + 16#4a2# => x"20", + 16#4a3# => x"57", + 16#4a4# => x"fc", + 16#4a5# => x"a0", + 16#4a6# => x"0c", + 16#4a7# => x"b1", + 16#4a8# => x"fa", + 16#4a9# => x"20", + 16#4aa# => x"57", + 16#4ab# => x"fc", + 16#4ac# => x"88", + 16#4ad# => x"10", + 16#4ae# => x"f8", + 16#4af# => x"68", + 16#4b0# => x"20", + 16#4b1# => x"57", + 16#4b2# => x"fc", + 16#4b3# => x"a0", + 16#4b4# => x"0c", + 16#4b5# => x"20", + 16#4b6# => x"80", + 16#4b7# => x"f9", + 16#4b8# => x"91", + 16#4b9# => x"fa", + 16#4ba# => x"88", + 16#4bb# => x"10", + 16#4bc# => x"f8", + 16#4bd# => x"a4", + 16#4be# => x"fb", + 16#4bf# => x"a6", + 16#4c0# => x"fa", + 16#4c1# => x"4c", + 16#4c2# => x"7c", + 16#4c3# => x"f9", + 16#4c4# => x"00", + 16#4c5# => x"ff", + 16#4c6# => x"42", + 16#4c7# => x"61", + 16#4c8# => x"64", + 16#4c9# => x"00", + 16#4ca# => x"00", + 16#4cb# => x"05", + 16#4cc# => x"00", + 16#4cd# => x"05", + 16#4ce# => x"04", + 16#4cf# => x"05", + 16#4d0# => x"08", + 16#4d1# => x"0e", + 16#4d2# => x"04", + 16#4d3# => x"01", + 16#4d4# => x"01", + 16#4d5# => x"05", + 16#4d6# => x"00", + 16#4d7# => x"01", + 16#4d8# => x"20", + 16#4d9# => x"10", + 16#4da# => x"0d", + 16#4db# => x"00", + 16#4dc# => x"04", + 16#4dd# => x"80", + 16#4de# => x"05", + 16#4df# => x"00", + 16#4e0# => x"05", + 16#4e1# => x"00", + 16#4e2# => x"05", + 16#4e3# => x"00", + 16#4e4# => x"00", + 16#4e5# => x"00", + 16#4e6# => x"05", + 16#4e7# => x"09", + 16#4e8# => x"05", + 16#4e9# => x"00", + 16#4ea# => x"08", + 16#4eb# => x"18", + 16#4ec# => x"00", + 16#4ed# => x"01", + 16#4ee# => x"0d", + 16#4ef# => x"80", + 16#4f0# => x"04", + 16#4f1# => x"80", + 16#4f2# => x"85", + 16#4f3# => x"fc", + 16#4f4# => x"68", + 16#4f5# => x"48", + 16#4f6# => x"29", + 16#4f7# => x"10", + 16#4f8# => x"d0", + 16#4f9# => x"10", + 16#4fa# => x"6c", + 16#4fb# => x"04", + 16#4fc# => x"02", + 16#4fd# => x"2c", + 16#4fe# => x"fe", + 16#4ff# => x"fe", + 16#500# => x"30", + 16#501# => x"4a", + 16#502# => x"2c", + 16#503# => x"f8", + 16#504# => x"fe", + 16#505# => x"30", + 16#506# => x"1e", + 16#507# => x"6c", + 16#508# => x"06", + 16#509# => x"02", + 16#50a# => x"8a", + 16#50b# => x"48", + 16#50c# => x"ba", + 16#50d# => x"bd", + 16#50e# => x"03", + 16#50f# => x"01", + 16#510# => x"d8", + 16#511# => x"38", + 16#512# => x"e9", + 16#513# => x"01", + 16#514# => x"85", + 16#515# => x"fd", + 16#516# => x"bd", + 16#517# => x"04", + 16#518# => x"01", + 16#519# => x"e9", + 16#51a# => x"00", + 16#51b# => x"85", + 16#51c# => x"fe", + 16#51d# => x"68", + 16#51e# => x"aa", + 16#51f# => x"a5", + 16#520# => x"fc", + 16#521# => x"58", + 16#522# => x"6c", + 16#523# => x"02", + 16#524# => x"02", + 16#525# => x"ad", + 16#526# => x"f9", + 16#527# => x"fe", + 16#528# => x"30", + 16#529# => x"1c", + 16#52a# => x"98", + 16#52b# => x"48", + 16#52c# => x"8a", + 16#52d# => x"48", + 16#52e# => x"20", + 16#52f# => x"8d", + 16#530# => x"fe", + 16#531# => x"a8", + 16#532# => x"20", + 16#533# => x"8d", + 16#534# => x"fe", + 16#535# => x"aa", + 16#536# => x"20", + 16#537# => x"8d", + 16#538# => x"fe", + 16#539# => x"20", + 16#53a# => x"43", + 16#53b# => x"fd", + 16#53c# => x"68", + 16#53d# => x"aa", + 16#53e# => x"68", + 16#53f# => x"a8", + 16#540# => x"a5", + 16#541# => x"fc", + 16#542# => x"40", + 16#543# => x"6c", + 16#544# => x"20", + 16#545# => x"02", + 16#546# => x"0a", + 16#547# => x"85", + 16#548# => x"ff", + 16#549# => x"a5", + 16#54a# => x"fc", + 16#54b# => x"40", + 16#54c# => x"ad", + 16#54d# => x"ff", + 16#54e# => x"fe", + 16#54f# => x"10", + 16#550# => x"21", + 16#551# => x"58", + 16#552# => x"2c", + 16#553# => x"fa", + 16#554# => x"fe", + 16#555# => x"10", + 16#556# => x"fb", + 16#557# => x"ad", + 16#558# => x"fb", + 16#559# => x"fe", + 16#55a# => x"a9", + 16#55b# => x"00", + 16#55c# => x"8d", + 16#55d# => x"36", + 16#55e# => x"02", + 16#55f# => x"a8", + 16#560# => x"20", + 16#561# => x"80", + 16#562# => x"f9", + 16#563# => x"8d", + 16#564# => x"37", + 16#565# => x"02", + 16#566# => x"c8", + 16#567# => x"20", + 16#568# => x"80", + 16#569# => x"f9", + 16#56a# => x"99", + 16#56b# => x"37", + 16#56c# => x"02", + 16#56d# => x"d0", + 16#56e# => x"f7", + 16#56f# => x"4c", + 16#570# => x"36", + 16#571# => x"02", + 16#572# => x"8d", + 16#573# => x"fa", + 16#574# => x"ff", + 16#575# => x"98", + 16#576# => x"48", + 16#577# => x"ac", + 16#578# => x"fa", + 16#579# => x"ff", + 16#57a# => x"b9", + 16#57b# => x"7d", + 16#57c# => x"fe", + 16#57d# => x"8d", + 16#57e# => x"fa", + 16#57f# => x"ff", + 16#580# => x"b9", + 16#581# => x"85", + 16#582# => x"fe", + 16#583# => x"8d", + 16#584# => x"fb", + 16#585# => x"ff", + 16#586# => x"b9", + 16#587# => x"6d", + 16#588# => x"fe", + 16#589# => x"85", + 16#58a# => x"f4", + 16#58b# => x"b9", + 16#58c# => x"75", + 16#58d# => x"fe", + 16#58e# => x"85", + 16#58f# => x"f5", + 16#590# => x"2c", + 16#591# => x"fe", + 16#592# => x"fe", + 16#593# => x"10", + 16#594# => x"fb", + 16#595# => x"ad", + 16#596# => x"ff", + 16#597# => x"fe", + 16#598# => x"c0", + 16#599# => x"05", + 16#59a# => x"f0", + 16#59b# => x"58", + 16#59c# => x"98", + 16#59d# => x"48", + 16#59e# => x"a0", + 16#59f# => x"01", + 16#5a0# => x"2c", + 16#5a1# => x"fe", + 16#5a2# => x"fe", + 16#5a3# => x"10", + 16#5a4# => x"fb", + 16#5a5# => x"ad", + 16#5a6# => x"ff", + 16#5a7# => x"fe", + 16#5a8# => x"2c", + 16#5a9# => x"fe", + 16#5aa# => x"fe", + 16#5ab# => x"10", + 16#5ac# => x"fb", + 16#5ad# => x"ad", + 16#5ae# => x"ff", + 16#5af# => x"fe", + 16#5b0# => x"2c", + 16#5b1# => x"fe", + 16#5b2# => x"fe", + 16#5b3# => x"10", + 16#5b4# => x"fb", + 16#5b5# => x"ad", + 16#5b6# => x"ff", + 16#5b7# => x"fe", + 16#5b8# => x"91", + 16#5b9# => x"f4", + 16#5ba# => x"88", + 16#5bb# => x"2c", + 16#5bc# => x"fe", + 16#5bd# => x"fe", + 16#5be# => x"10", + 16#5bf# => x"fb", + 16#5c0# => x"ad", + 16#5c1# => x"ff", + 16#5c2# => x"fe", + 16#5c3# => x"91", + 16#5c4# => x"f4", + 16#5c5# => x"2c", + 16#5c6# => x"fd", + 16#5c7# => x"fe", + 16#5c8# => x"2c", + 16#5c9# => x"fd", + 16#5ca# => x"fe", + 16#5cb# => x"2c", + 16#5cc# => x"fe", + 16#5cd# => x"fe", + 16#5ce# => x"10", + 16#5cf# => x"fb", + 16#5d0# => x"ad", + 16#5d1# => x"ff", + 16#5d2# => x"fe", + 16#5d3# => x"68", + 16#5d4# => x"c9", + 16#5d5# => x"06", + 16#5d6# => x"90", + 16#5d7# => x"1c", + 16#5d8# => x"d0", + 16#5d9# => x"1f", + 16#5da# => x"a0", + 16#5db# => x"00", + 16#5dc# => x"ad", + 16#5dd# => x"fc", + 16#5de# => x"fe", + 16#5df# => x"29", + 16#5e0# => x"80", + 16#5e1# => x"10", + 16#5e2# => x"f9", + 16#5e3# => x"b9", + 16#5e4# => x"ff", + 16#5e5# => x"ff", + 16#5e6# => x"8d", + 16#5e7# => x"fd", + 16#5e8# => x"fe", + 16#5e9# => x"c8", + 16#5ea# => x"d0", + 16#5eb# => x"f0", + 16#5ec# => x"2c", + 16#5ed# => x"fc", + 16#5ee# => x"fe", + 16#5ef# => x"10", + 16#5f0# => x"fb", + 16#5f1# => x"8d", + 16#5f2# => x"fd", + 16#5f3# => x"fe", + 16#5f4# => x"68", + 16#5f5# => x"a8", + 16#5f6# => x"a5", + 16#5f7# => x"fc", + 16#5f8# => x"40", + 16#5f9# => x"a0", + 16#5fa# => x"00", + 16#5fb# => x"ad", + 16#5fc# => x"fc", + 16#5fd# => x"fe", + 16#5fe# => x"29", + 16#5ff# => x"80", + 16#600# => x"10", + 16#601# => x"f9", + 16#602# => x"ad", + 16#603# => x"fd", + 16#604# => x"fe", + 16#605# => x"99", + 16#606# => x"ff", + 16#607# => x"ff", + 16#608# => x"c8", + 16#609# => x"d0", + 16#60a# => x"f0", + 16#60b# => x"f0", + 16#60c# => x"e7", + 16#60d# => x"48", + 16#60e# => x"ad", + 16#60f# => x"ff", + 16#610# => x"ff", + 16#611# => x"8d", + 16#612# => x"fd", + 16#613# => x"fe", + 16#614# => x"ee", + 16#615# => x"0f", + 16#616# => x"fe", + 16#617# => x"d0", + 16#618# => x"03", + 16#619# => x"ee", + 16#61a# => x"10", + 16#61b# => x"fe", + 16#61c# => x"68", + 16#61d# => x"40", + 16#61e# => x"48", + 16#61f# => x"ad", + 16#620# => x"fd", + 16#621# => x"fe", + 16#622# => x"8d", + 16#623# => x"ff", + 16#624# => x"ff", + 16#625# => x"ee", + 16#626# => x"23", + 16#627# => x"fe", + 16#628# => x"d0", + 16#629# => x"03", + 16#62a# => x"ee", + 16#62b# => x"24", + 16#62c# => x"fe", + 16#62d# => x"68", + 16#62e# => x"40", + 16#62f# => x"48", + 16#630# => x"98", + 16#631# => x"48", + 16#632# => x"a0", + 16#633# => x"00", + 16#634# => x"b1", + 16#635# => x"f6", + 16#636# => x"8d", + 16#637# => x"fd", + 16#638# => x"fe", + 16#639# => x"e6", + 16#63a# => x"f6", + 16#63b# => x"d0", + 16#63c# => x"02", + 16#63d# => x"e6", + 16#63e# => x"f7", + 16#63f# => x"b1", + 16#640# => x"f6", + 16#641# => x"8d", + 16#642# => x"fd", + 16#643# => x"fe", + 16#644# => x"e6", + 16#645# => x"f6", + 16#646# => x"d0", + 16#647# => x"02", + 16#648# => x"e6", + 16#649# => x"f7", + 16#64a# => x"68", + 16#64b# => x"a8", + 16#64c# => x"68", + 16#64d# => x"40", + 16#64e# => x"48", + 16#64f# => x"98", + 16#650# => x"48", + 16#651# => x"a0", + 16#652# => x"00", + 16#653# => x"ad", + 16#654# => x"fd", + 16#655# => x"fe", + 16#656# => x"91", + 16#657# => x"f6", + 16#658# => x"e6", + 16#659# => x"f6", + 16#65a# => x"d0", + 16#65b# => x"02", + 16#65c# => x"e6", + 16#65d# => x"f7", + 16#65e# => x"ad", + 16#65f# => x"fd", + 16#660# => x"fe", + 16#661# => x"91", + 16#662# => x"f6", + 16#663# => x"e6", + 16#664# => x"f6", + 16#665# => x"d0", + 16#666# => x"02", + 16#667# => x"e6", + 16#668# => x"f7", + 16#669# => x"68", + 16#66a# => x"a8", + 16#66b# => x"68", + 16#66c# => x"40", + 16#66d# => x"0f", + 16#66e# => x"23", + 16#66f# => x"f6", + 16#670# => x"f6", + 16#671# => x"f6", + 16#672# => x"f6", + 16#673# => x"e4", + 16#674# => x"06", + 16#675# => x"fe", + 16#676# => x"fe", + 16#677# => x"00", + 16#678# => x"00", + 16#679# => x"00", + 16#67a# => x"00", + 16#67b# => x"fd", + 16#67c# => x"fe", + 16#67d# => x"0d", + 16#67e# => x"1e", + 16#67f# => x"2f", + 16#680# => x"4e", + 16#681# => x"c0", + 16#682# => x"c0", + 16#683# => x"c0", + 16#684# => x"c0", + 16#685# => x"fe", + 16#686# => x"fe", + 16#687# => x"fe", + 16#688# => x"fe", + 16#689# => x"fe", + 16#68a# => x"fe", + 16#68b# => x"fe", + 16#68c# => x"fe", + 16#68d# => x"2c", + 16#68e# => x"f8", + 16#68f# => x"fe", + 16#690# => x"30", + 16#691# => x"0f", + 16#692# => x"2c", + 16#693# => x"fe", + 16#694# => x"fe", + 16#695# => x"10", + 16#696# => x"f6", + 16#697# => x"a5", + 16#698# => x"fc", + 16#699# => x"08", + 16#69a# => x"58", + 16#69b# => x"28", + 16#69c# => x"85", + 16#69d# => x"fc", + 16#69e# => x"4c", + 16#69f# => x"8d", + 16#6a0# => x"fe", + 16#6a1# => x"ad", + 16#6a2# => x"f9", + 16#6a3# => x"fe", + 16#6a4# => x"60", + 16#6a5# => x"68", + 16#6a6# => x"85", + 16#6a7# => x"fa", + 16#6a8# => x"68", + 16#6a9# => x"85", + 16#6aa# => x"fb", + 16#6ab# => x"a0", + 16#6ac# => x"00", + 16#6ad# => x"e6", + 16#6ae# => x"fa", + 16#6af# => x"d0", + 16#6b0# => x"02", + 16#6b1# => x"e6", + 16#6b2# => x"fb", + 16#6b3# => x"b1", + 16#6b4# => x"fa", + 16#6b5# => x"30", + 16#6b6# => x"06", + 16#6b7# => x"20", + 16#6b8# => x"ee", + 16#6b9# => x"ff", + 16#6ba# => x"4c", + 16#6bb# => x"ad", + 16#6bc# => x"fe", + 16#6bd# => x"6c", + 16#6be# => x"fa", + 16#6bf# => x"00", + 16#6c0# => x"8d", + 16#6c1# => x"fd", + 16#6c2# => x"fe", + 16#6c3# => x"40", + 16#6c4# => x"ff", + 16#6c5# => x"ff", + 16#6c6# => x"ff", + 16#6c7# => x"ff", + 16#6c8# => x"ff", + 16#6c9# => x"ff", + 16#6ca# => x"ff", + 16#6cb# => x"ff", + 16#6cc# => x"ff", + 16#6cd# => x"ff", + 16#6ce# => x"ff", + 16#6cf# => x"ff", + 16#6d0# => x"ff", + 16#6d1# => x"ff", + 16#6d2# => x"ff", + 16#6d3# => x"ff", + 16#6d4# => x"ff", + 16#6d5# => x"ff", + 16#6d6# => x"ff", + 16#6d7# => x"ff", + 16#6d8# => x"ff", + 16#6d9# => x"ff", + 16#6da# => x"ff", + 16#6db# => x"ff", + 16#6dc# => x"ff", + 16#6dd# => x"ff", + 16#6de# => x"ff", + 16#6df# => x"ff", + 16#6e0# => x"ff", + 16#6e1# => x"ff", + 16#6e2# => x"ff", + 16#6e3# => x"ff", + 16#6e4# => x"ff", + 16#6e5# => x"ff", + 16#6e6# => x"ff", + 16#6e7# => x"ff", + 16#6e8# => x"ff", + 16#6e9# => x"ff", + 16#6ea# => x"ff", + 16#6eb# => x"ff", + 16#6ec# => x"ff", + 16#6ed# => x"ff", + 16#6ee# => x"ff", + 16#6ef# => x"ff", + 16#6f0# => x"00", + 16#6f1# => x"00", + 16#6f2# => x"00", + 16#6f3# => x"00", + 16#6f4# => x"00", + 16#6f5# => x"00", + 16#6f6# => x"00", + 16#6f7# => x"00", + 16#6f8# => x"00", + 16#6f9# => x"00", + 16#6fa# => x"00", + 16#6fb# => x"00", + 16#6fc# => x"00", + 16#6fd# => x"00", + 16#6fe# => x"00", + 16#6ff# => x"00", + 16#700# => x"ff", + 16#701# => x"ff", + 16#702# => x"ff", + 16#703# => x"ff", + 16#704# => x"ff", + 16#705# => x"ff", + 16#706# => x"ff", + 16#707# => x"ff", + 16#708# => x"ff", + 16#709# => x"ff", + 16#70a# => x"ff", + 16#70b# => x"ff", + 16#70c# => x"ff", + 16#70d# => x"ff", + 16#70e# => x"ff", + 16#70f# => x"ff", + 16#710# => x"ff", + 16#711# => x"ff", + 16#712# => x"ff", + 16#713# => x"ff", + 16#714# => x"ff", + 16#715# => x"ff", + 16#716# => x"ff", + 16#717# => x"ff", + 16#718# => x"ff", + 16#719# => x"ff", + 16#71a# => x"ff", + 16#71b# => x"ff", + 16#71c# => x"ff", + 16#71d# => x"ff", + 16#71e# => x"ff", + 16#71f# => x"ff", + 16#720# => x"ff", + 16#721# => x"ff", + 16#722# => x"ff", + 16#723# => x"ff", + 16#724# => x"ff", + 16#725# => x"ff", + 16#726# => x"ff", + 16#727# => x"ff", + 16#728# => x"ff", + 16#729# => x"ff", + 16#72a# => x"ff", + 16#72b# => x"ff", + 16#72c# => x"ff", + 16#72d# => x"ff", + 16#72e# => x"ff", + 16#72f# => x"ff", + 16#730# => x"ff", + 16#731# => x"ff", + 16#732# => x"ff", + 16#733# => x"ff", + 16#734# => x"ff", + 16#735# => x"ff", + 16#736# => x"ff", + 16#737# => x"ff", + 16#738# => x"ff", + 16#739# => x"ff", + 16#73a# => x"ff", + 16#73b# => x"ff", + 16#73c# => x"ff", + 16#73d# => x"ff", + 16#73e# => x"ff", + 16#73f# => x"ff", + 16#740# => x"ff", + 16#741# => x"ff", + 16#742# => x"ff", + 16#743# => x"ff", + 16#744# => x"ff", + 16#745# => x"ff", + 16#746# => x"ff", + 16#747# => x"ff", + 16#748# => x"ff", + 16#749# => x"ff", + 16#74a# => x"ff", + 16#74b# => x"ff", + 16#74c# => x"ff", + 16#74d# => x"ff", + 16#74e# => x"ff", + 16#74f# => x"ff", + 16#750# => x"ff", + 16#751# => x"ff", + 16#752# => x"ff", + 16#753# => x"ff", + 16#754# => x"ff", + 16#755# => x"ff", + 16#756# => x"ff", + 16#757# => x"ff", + 16#758# => x"ff", + 16#759# => x"ff", + 16#75a# => x"ff", + 16#75b# => x"ff", + 16#75c# => x"ff", + 16#75d# => x"ff", + 16#75e# => x"ff", + 16#75f# => x"ff", + 16#760# => x"ff", + 16#761# => x"ff", + 16#762# => x"ff", + 16#763# => x"ff", + 16#764# => x"ff", + 16#765# => x"ff", + 16#766# => x"ff", + 16#767# => x"ff", + 16#768# => x"ff", + 16#769# => x"ff", + 16#76a# => x"ff", + 16#76b# => x"ff", + 16#76c# => x"ff", + 16#76d# => x"ff", + 16#76e# => x"ff", + 16#76f# => x"ff", + 16#770# => x"ff", + 16#771# => x"ff", + 16#772# => x"ff", + 16#773# => x"ff", + 16#774# => x"ff", + 16#775# => x"ff", + 16#776# => x"ff", + 16#777# => x"ff", + 16#778# => x"ff", + 16#779# => x"ff", + 16#77a# => x"ff", + 16#77b# => x"ff", + 16#77c# => x"ff", + 16#77d# => x"ff", + 16#77e# => x"ff", + 16#77f# => x"ff", + 16#780# => x"c4", + 16#781# => x"fc", + 16#782# => x"50", + 16#783# => x"f9", + 16#784# => x"fd", + 16#785# => x"fc", + 16#786# => x"c4", + 16#787# => x"fc", + 16#788# => x"d5", + 16#789# => x"f9", + 16#78a# => x"80", + 16#78b# => x"fa", + 16#78c# => x"0c", + 16#78d# => x"fb", + 16#78e# => x"6d", + 16#78f# => x"f9", + 16#790# => x"77", + 16#791# => x"f9", + 16#792# => x"60", + 16#793# => x"fc", + 16#794# => x"d9", + 16#795# => x"fb", + 16#796# => x"37", + 16#797# => x"fc", + 16#798# => x"43", + 16#799# => x"fc", + 16#79a# => x"9b", + 16#79b# => x"fc", + 16#79c# => x"19", + 16#79d# => x"fc", + 16#79e# => x"c4", + 16#79f# => x"fc", + 16#7a0# => x"88", + 16#7a1# => x"f9", + 16#7a2# => x"c4", + 16#7a3# => x"fc", + 16#7a4# => x"c4", + 16#7a5# => x"fc", + 16#7a6# => x"c4", + 16#7a7# => x"fc", + 16#7a8# => x"c4", + 16#7a9# => x"fc", + 16#7aa# => x"c4", + 16#7ab# => x"fc", + 16#7ac# => x"c4", + 16#7ad# => x"fc", + 16#7ae# => x"c4", + 16#7af# => x"fc", + 16#7b0# => x"88", + 16#7b1# => x"f9", + 16#7b2# => x"88", + 16#7b3# => x"f9", + 16#7b4# => x"88", + 16#7b5# => x"f9", + 16#7b6# => x"36", + 16#7b7# => x"80", + 16#7b8# => x"ff", + 16#7b9# => x"4c", + 16#7ba# => x"c4", + 16#7bb# => x"fc", + 16#7bc# => x"4c", + 16#7bd# => x"c4", + 16#7be# => x"fc", + 16#7bf# => x"4c", + 16#7c0# => x"c4", + 16#7c1# => x"fc", + 16#7c2# => x"4c", + 16#7c3# => x"c4", + 16#7c4# => x"fc", + 16#7c5# => x"4c", + 16#7c6# => x"c4", + 16#7c7# => x"fc", + 16#7c8# => x"4c", + 16#7c9# => x"77", + 16#7ca# => x"f9", + 16#7cb# => x"4c", + 16#7cc# => x"6d", + 16#7cd# => x"f9", + 16#7ce# => x"6c", + 16#7cf# => x"1c", + 16#7d0# => x"02", + 16#7d1# => x"6c", + 16#7d2# => x"1a", + 16#7d3# => x"02", + 16#7d4# => x"6c", + 16#7d5# => x"18", + 16#7d6# => x"02", + 16#7d7# => x"6c", + 16#7d8# => x"16", + 16#7d9# => x"02", + 16#7da# => x"6c", + 16#7db# => x"14", + 16#7dc# => x"02", + 16#7dd# => x"6c", + 16#7de# => x"12", + 16#7df# => x"02", + 16#7e0# => x"6c", + 16#7e1# => x"10", + 16#7e2# => x"02", + 16#7e3# => x"c9", + 16#7e4# => x"0d", + 16#7e5# => x"d0", + 16#7e6# => x"07", + 16#7e7# => x"a9", + 16#7e8# => x"0a", + 16#7e9# => x"20", + 16#7ea# => x"ee", + 16#7eb# => x"ff", + 16#7ec# => x"a9", + 16#7ed# => x"0d", + 16#7ee# => x"6c", + 16#7ef# => x"0e", + 16#7f0# => x"02", + 16#7f1# => x"6c", + 16#7f2# => x"0c", + 16#7f3# => x"02", + 16#7f4# => x"6c", + 16#7f5# => x"0a", + 16#7f6# => x"02", + 16#7f7# => x"6c", + 16#7f8# => x"08", + 16#7f9# => x"02", + 16#7fa# => x"0d", + 16#7fb# => x"fe", + 16#7fc# => x"00", + 16#7fd# => x"f8", + 16#7fe# => x"f2", + 16#7ff# => x"fc" + ); + + attribute ram_style : string; + + attribute ram_style of RAM : signal is "distributed"; + +begin + + process (CLK) + begin + if rising_edge(CLK) then + DATA <= RAM(conv_integer(ADDR)); + end if; + end process; + +end RTL; + + +