Remove trailing whitespace
Change-Id: I25e1b337211032bb572351f8a02d3b05013330ea
This commit is contained in:
194
cpu_65c02.v
194
cpu_65c02.v
@@ -1,22 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
* verilog model of 65C02 CPU.
|
* verilog model of 65C02 CPU.
|
||||||
*
|
*
|
||||||
* Based on original 6502 "Arlet 6502 Core" by Arlet Ottens
|
* Based on original 6502 "Arlet 6502 Core" by Arlet Ottens
|
||||||
*
|
*
|
||||||
* (C) Arlet Ottens, <arlet@c-scape.nl>
|
* (C) Arlet Ottens, <arlet@c-scape.nl>
|
||||||
*
|
*
|
||||||
* Feel free to use this code in any project (commercial or not), as long as you
|
* 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",
|
* keep this message, and the copyright notice. This code is provided "as is",
|
||||||
* without any warranties of any kind.
|
* without any warranties of any kind.
|
||||||
*
|
*
|
||||||
* Support for 65C02 instructions and addressing modes by David Banks and Ed Spittles
|
* Support for 65C02 instructions and addressing modes by David Banks and Ed Spittles
|
||||||
*
|
*
|
||||||
* (C) 2016 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
|
* 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",
|
* keep this message, and the copyright notice. This code is provided "as is",
|
||||||
* without any warranties of any kind.
|
* without any warranties of any kind.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
* Two things were needed to correctly implement 65C02 NOPs
|
* Two things were needed to correctly implement 65C02 NOPs
|
||||||
* 1. Ensure the microcode state machine uses an appropriate addressing mode for the opcode length
|
* 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)
|
* 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.
|
* If IMPLEMENT_NOPS is defined, the state machine is modified accordingly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
module cpu_65c02( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY );
|
module cpu_65c02( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY );
|
||||||
|
|
||||||
input clk; // CPU clock
|
input clk; // CPU clock
|
||||||
input reset; // reset signal
|
input reset; // reset signal
|
||||||
output reg [15:0] AB; // address bus
|
output reg [15:0] AB; // address bus
|
||||||
input [7:0] DI; // data in, read bus
|
input [7:0] DI; // data in, read bus
|
||||||
@@ -58,13 +58,13 @@ output [7:0] DO; // data out, write bus
|
|||||||
output WE; // write enable
|
output WE; // write enable
|
||||||
input IRQ; // interrupt request
|
input IRQ; // interrupt request
|
||||||
input NMI; // non-maskable interrupt request
|
input NMI; // non-maskable interrupt request
|
||||||
input RDY; // Ready signal. Pauses CPU when RDY=0
|
input RDY; // Ready signal. Pauses CPU when RDY=0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* internal signals
|
* internal signals
|
||||||
*/
|
*/
|
||||||
|
|
||||||
reg [15:0] PC; // Program Counter
|
reg [15:0] PC; // Program Counter
|
||||||
reg [7:0] ABL; // Address Bus Register LSB
|
reg [7:0] ABL; // Address Bus Register LSB
|
||||||
reg [7:0] ABH; // Address Bus Register MSB
|
reg [7:0] ABH; // Address Bus Register MSB
|
||||||
wire [7:0] ADD; // Adder Hold Register (registered in ALU)
|
wire [7:0] ADD; // Adder Hold Register (registered in ALU)
|
||||||
@@ -73,7 +73,7 @@ reg [7:0] DIHOLD; // Hold for Data In
|
|||||||
reg DIHOLD_valid; //
|
reg DIHOLD_valid; //
|
||||||
wire [7:0] DIMUX; //
|
wire [7:0] DIMUX; //
|
||||||
|
|
||||||
reg [7:0] IRHOLD; // Hold for Instruction register
|
reg [7:0] IRHOLD; // Hold for Instruction register
|
||||||
reg IRHOLD_valid; // Valid instruction in IRHOLD
|
reg IRHOLD_valid; // Valid instruction in IRHOLD
|
||||||
|
|
||||||
reg [7:0] AXYS[3:0]; // A, X, Y and S register file
|
reg [7:0] AXYS[3:0]; // A, X, Y and S register file
|
||||||
@@ -96,11 +96,11 @@ reg [7:0] AI; // ALU Input A
|
|||||||
reg [7:0] BI; // ALU Input B
|
reg [7:0] BI; // ALU Input B
|
||||||
wire [7:0] DI; // Data In
|
wire [7:0] DI; // Data In
|
||||||
wire [7:0] IR; // Instruction register
|
wire [7:0] IR; // Instruction register
|
||||||
reg [7:0] DO; // Data Out
|
reg [7:0] DO; // Data Out
|
||||||
wire [7:0] AO; // ALU output after BCD adjustment
|
wire [7:0] AO; // ALU output after BCD adjustment
|
||||||
reg WE; // Write Enable
|
reg WE; // Write Enable
|
||||||
reg CI; // Carry In
|
reg CI; // Carry In
|
||||||
wire CO; // Carry Out
|
wire CO; // Carry Out
|
||||||
wire [7:0] PCH = PC[15:8];
|
wire [7:0] PCH = PC[15:8];
|
||||||
wire [7:0] PCL = PC[7:0];
|
wire [7:0] PCL = PC[7:0];
|
||||||
|
|
||||||
@@ -109,10 +109,10 @@ reg NMI_edge = 0; // captured NMI edge
|
|||||||
reg [1:0] regsel; // Select A, X, Y or S register
|
reg [1:0] regsel; // Select A, X, Y or S register
|
||||||
wire [7:0] regfile = AXYS[regsel]; // Selected register output
|
wire [7:0] regfile = AXYS[regsel]; // Selected register output
|
||||||
|
|
||||||
parameter
|
parameter
|
||||||
SEL_A = 2'd0,
|
SEL_A = 2'd0,
|
||||||
SEL_S = 2'd1,
|
SEL_S = 2'd1,
|
||||||
SEL_X = 2'd2,
|
SEL_X = 2'd2,
|
||||||
SEL_Y = 2'd3;
|
SEL_Y = 2'd3;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -123,8 +123,8 @@ parameter
|
|||||||
`ifdef SIM
|
`ifdef SIM
|
||||||
wire [7:0] A = AXYS[SEL_A]; // Accumulator
|
wire [7:0] A = AXYS[SEL_A]; // Accumulator
|
||||||
wire [7:0] X = AXYS[SEL_X]; // X register
|
wire [7:0] X = AXYS[SEL_X]; // X register
|
||||||
wire [7:0] Y = AXYS[SEL_Y]; // Y register
|
wire [7:0] Y = AXYS[SEL_Y]; // Y register
|
||||||
wire [7:0] S = AXYS[SEL_S]; // Stack pointer
|
wire [7:0] S = AXYS[SEL_S]; // Stack pointer
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
wire [7:0] P = { N, V, 2'b11, D, I, Z, C };
|
wire [7:0] P = { N, V, 2'b11, D, I, Z, C };
|
||||||
@@ -140,15 +140,15 @@ reg [5:0] state;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
reg PC_inc; // Increment PC
|
reg PC_inc; // Increment PC
|
||||||
reg [15:0] PC_temp; // intermediate value of PC
|
reg [15:0] PC_temp; // intermediate value of PC
|
||||||
|
|
||||||
reg [1:0] src_reg; // source register index
|
reg [1:0] src_reg; // source register index
|
||||||
reg [1:0] dst_reg; // destination register index
|
reg [1:0] dst_reg; // destination register index
|
||||||
|
|
||||||
reg index_y; // if set, then Y is index reg rather than X
|
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 load_reg; // loading a register (A, X, Y, S) in this instruction
|
||||||
reg inc; // increment
|
reg inc; // increment
|
||||||
reg write_back; // set if memory is read/modified/written
|
reg write_back; // set if memory is read/modified/written
|
||||||
reg load_only; // LDA/LDX/LDY instruction
|
reg load_only; // LDA/LDX/LDY instruction
|
||||||
reg store; // doing store (STA/STX/STY)
|
reg store; // doing store (STA/STX/STY)
|
||||||
reg adc_sbc; // doing ADC/SBC
|
reg adc_sbc; // doing ADC/SBC
|
||||||
@@ -158,14 +158,14 @@ reg rotate; // doing rotate (no shift)
|
|||||||
reg backwards; // backwards branch
|
reg backwards; // backwards branch
|
||||||
reg cond_true; // branch condition is true
|
reg cond_true; // branch condition is true
|
||||||
reg [3:0] cond_code; // condition code bits from instruction
|
reg [3:0] cond_code; // condition code bits from instruction
|
||||||
reg shift_right; // Instruction ALU shift/rotate right
|
reg shift_right; // Instruction ALU shift/rotate right
|
||||||
reg alu_shift_right; // Current cycle shift right enable
|
reg alu_shift_right; // Current cycle shift right enable
|
||||||
reg [3:0] op; // Main ALU operation for instruction
|
reg [3:0] op; // Main ALU operation for instruction
|
||||||
reg [3:0] alu_op; // Current cycle ALU operation
|
reg [3:0] alu_op; // Current cycle ALU operation
|
||||||
reg adc_bcd; // ALU should do BCD style carry
|
reg adc_bcd; // ALU should do BCD style carry
|
||||||
reg adj_bcd; // results should be BCD adjusted
|
reg adj_bcd; // results should be BCD adjusted
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* some flip flops to remember we're doing special instructions. These
|
* some flip flops to remember we're doing special instructions. These
|
||||||
* get loaded at the DECODE state, and used later
|
* get loaded at the DECODE state, and used later
|
||||||
*/
|
*/
|
||||||
@@ -175,14 +175,14 @@ reg txb_ins; // doing TSB/TRB instruction
|
|||||||
reg bit_ins; // doing BIT 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 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 plp; // doing PLP instruction
|
||||||
reg php; // doing PHP instruction
|
reg php; // doing PHP instruction
|
||||||
reg clc; // clear carry
|
reg clc; // clear carry
|
||||||
reg sec; // set carry
|
reg sec; // set carry
|
||||||
reg cld; // clear decimal
|
reg cld; // clear decimal
|
||||||
reg sed; // set decimal
|
reg sed; // set decimal
|
||||||
reg cli; // clear interrupt
|
reg cli; // clear interrupt
|
||||||
reg sei; // set interrupt
|
reg sei; // set interrupt
|
||||||
reg clv; // clear overflow
|
reg clv; // clear overflow
|
||||||
reg brk; // doing BRK
|
reg brk; // doing BRK
|
||||||
|
|
||||||
reg res; // in reset
|
reg res; // in reset
|
||||||
@@ -204,17 +204,17 @@ parameter
|
|||||||
* Microcode state machine. Basically, every addressing mode has its own
|
* Microcode state machine. Basically, every addressing mode has its own
|
||||||
* path through the state machine. Additional information, such as the
|
* path through the state machine. Additional information, such as the
|
||||||
* operation, source and destination registers are decoded in parallel, and
|
* operation, source and destination registers are decoded in parallel, and
|
||||||
* kept in separate flops.
|
* kept in separate flops.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
parameter
|
parameter
|
||||||
ABS0 = 6'd0, // ABS - fetch LSB
|
ABS0 = 6'd0, // ABS - fetch LSB
|
||||||
ABS1 = 6'd1, // ABS - fetch MSB
|
ABS1 = 6'd1, // ABS - fetch MSB
|
||||||
ABSX0 = 6'd2, // ABS, X - fetch LSB and send to ALU (+X)
|
ABSX0 = 6'd2, // ABS, X - fetch LSB and send to ALU (+X)
|
||||||
ABSX1 = 6'd3, // ABS, X - fetch MSB and send to ALU (+Carry)
|
ABSX1 = 6'd3, // ABS, X - fetch MSB and send to ALU (+Carry)
|
||||||
ABSX2 = 6'd4, // ABS, X - Wait for ALU (only if needed)
|
ABSX2 = 6'd4, // ABS, X - Wait for ALU (only if needed)
|
||||||
BRA0 = 6'd5, // Branch - fetch offset and send to ALU (+PC[7:0])
|
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
|
BRA1 = 6'd6, // Branch - fetch opcode, and send PC[15:8] to ALU
|
||||||
BRA2 = 6'd7, // Branch - fetch opcode (if page boundary crossed)
|
BRA2 = 6'd7, // Branch - fetch opcode (if page boundary crossed)
|
||||||
BRK0 = 6'd8, // BRK/IRQ - push PCH, send S to ALU (-1)
|
BRK0 = 6'd8, // BRK/IRQ - push PCH, send S to ALU (-1)
|
||||||
BRK1 = 6'd9, // BRK/IRQ - push PCL, send S to ALU (-1)
|
BRK1 = 6'd9, // BRK/IRQ - push PCL, send S to ALU (-1)
|
||||||
@@ -225,9 +225,9 @@ parameter
|
|||||||
INDX0 = 6'd14, // (ZP,X) - fetch ZP address, and send to ALU (+X)
|
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
|
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
|
INDX2 = 6'd16, // (ZP,X) - fetch MSB at ZP+X+1
|
||||||
INDX3 = 6'd17, // (ZP,X) - fetch data
|
INDX3 = 6'd17, // (ZP,X) - fetch data
|
||||||
INDY0 = 6'd18, // (ZP),Y - fetch ZP address, and send ZP to ALU (+1)
|
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)
|
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)
|
INDY2 = 6'd20, // (ZP),Y - fetch data, and send MSB to ALU (+Carry)
|
||||||
INDY3 = 6'd21, // (ZP),Y) - fetch data (if page boundary crossed)
|
INDY3 = 6'd21, // (ZP),Y) - fetch data (if page boundary crossed)
|
||||||
JMP0 = 6'd22, // JMP - fetch PCL and hold
|
JMP0 = 6'd22, // JMP - fetch PCL and hold
|
||||||
@@ -246,15 +246,15 @@ parameter
|
|||||||
READ = 6'd35, // Read memory for read/modify/write (INC, DEC, shift)
|
READ = 6'd35, // Read memory for read/modify/write (INC, DEC, shift)
|
||||||
REG = 6'd36, // Read register for reg-reg transfers
|
REG = 6'd36, // Read register for reg-reg transfers
|
||||||
RTI0 = 6'd37, // RTI - send S to ALU (+1)
|
RTI0 = 6'd37, // RTI - send S to ALU (+1)
|
||||||
RTI1 = 6'd38, // RTI - read P from stack
|
RTI1 = 6'd38, // RTI - read P from stack
|
||||||
RTI2 = 6'd39, // RTI - read PCL from stack
|
RTI2 = 6'd39, // RTI - read PCL from stack
|
||||||
RTI3 = 6'd40, // RTI - read PCH from stack
|
RTI3 = 6'd40, // RTI - read PCH from stack
|
||||||
RTI4 = 6'd41, // RTI - read PCH from stack
|
RTI4 = 6'd41, // RTI - read PCH from stack
|
||||||
RTS0 = 6'd42, // RTS - send S to ALU (+1)
|
RTS0 = 6'd42, // RTS - send S to ALU (+1)
|
||||||
RTS1 = 6'd43, // RTS - read PCL from stack
|
RTS1 = 6'd43, // RTS - read PCL from stack
|
||||||
RTS2 = 6'd44, // RTS - write PCL to ALU, read PCH
|
RTS2 = 6'd44, // RTS - write PCL to ALU, read PCH
|
||||||
RTS3 = 6'd45, // RTS - load PC and increment
|
RTS3 = 6'd45, // RTS - load PC and increment
|
||||||
WRITE = 6'd46, // Write memory for read/modify/write
|
WRITE = 6'd46, // Write memory for read/modify/write
|
||||||
ZP0 = 6'd47, // Z-page - fetch ZP address
|
ZP0 = 6'd47, // Z-page - fetch ZP address
|
||||||
ZPX0 = 6'd48, // ZP, X - fetch ZP, and send to ALU (+X)
|
ZPX0 = 6'd48, // ZP, X - fetch ZP, and send to ALU (+X)
|
||||||
ZPX1 = 6'd49, // ZP, X - load from memory
|
ZPX1 = 6'd49, // ZP, X - load from memory
|
||||||
@@ -326,7 +326,7 @@ always @*
|
|||||||
JMPIX0: statename = "JMPIX0";
|
JMPIX0: statename = "JMPIX0";
|
||||||
JMPIX1: statename = "JMPIX1";
|
JMPIX1: statename = "JMPIX1";
|
||||||
JMPIX2: statename = "JMPIX2";
|
JMPIX2: statename = "JMPIX2";
|
||||||
|
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
//always @( PC )
|
//always @( PC )
|
||||||
@@ -352,15 +352,15 @@ always @*
|
|||||||
JMPI1,
|
JMPI1,
|
||||||
JMPIX1,
|
JMPIX1,
|
||||||
JSR3,
|
JSR3,
|
||||||
RTS3,
|
RTS3,
|
||||||
RTI4: PC_temp = { DIMUX, ADD };
|
RTI4: PC_temp = { DIMUX, ADD };
|
||||||
|
|
||||||
BRA1: PC_temp = { ABH, ADD };
|
BRA1: PC_temp = { ABH, ADD };
|
||||||
|
|
||||||
JMPIX2,
|
JMPIX2,
|
||||||
BRA2: PC_temp = { ADD, PCL };
|
BRA2: PC_temp = { ADD, PCL };
|
||||||
|
|
||||||
BRK2: PC_temp = res ? 16'hfffc :
|
BRK2: PC_temp = res ? 16'hfffc :
|
||||||
NMI_edge ? 16'hfffa : 16'hfffe;
|
NMI_edge ? 16'hfffa : 16'hfffe;
|
||||||
|
|
||||||
default: PC_temp = PC;
|
default: PC_temp = PC;
|
||||||
@@ -396,15 +396,15 @@ always @*
|
|||||||
default: PC_inc = 0;
|
default: PC_inc = 0;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set new PC
|
* Set new PC
|
||||||
*/
|
*/
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if( RDY )
|
if( RDY )
|
||||||
PC <= PC_temp + PC_inc;
|
PC <= PC_temp + PC_inc;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Address Generator
|
* Address Generator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
parameter
|
parameter
|
||||||
@@ -444,7 +444,7 @@ always @*
|
|||||||
RTI2,
|
RTI2,
|
||||||
RTI3,
|
RTI3,
|
||||||
BRK2: AB = { STACKPAGE, ADD };
|
BRK2: AB = { STACKPAGE, ADD };
|
||||||
|
|
||||||
INDY1,
|
INDY1,
|
||||||
INDX1,
|
INDX1,
|
||||||
ZPX1,
|
ZPX1,
|
||||||
@@ -466,7 +466,7 @@ always @*
|
|||||||
* source of the address, such as the ALU or DI.
|
* source of the address, such as the ALU or DI.
|
||||||
*/
|
*/
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if( state != PUSH0 && state != PUSH1 && RDY &&
|
if( state != PUSH0 && state != PUSH1 && RDY &&
|
||||||
state != PULL0 && state != PULL1 && state != PULL2 )
|
state != PULL0 && state != PULL1 && state != PULL2 )
|
||||||
begin
|
begin
|
||||||
ABL <= AB[7:0];
|
ABL <= AB[7:0];
|
||||||
@@ -474,7 +474,7 @@ always @(posedge clk)
|
|||||||
end
|
end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data Out MUX
|
* Data Out MUX
|
||||||
*/
|
*/
|
||||||
always @*
|
always @*
|
||||||
case( state )
|
case( state )
|
||||||
@@ -529,8 +529,8 @@ always @*
|
|||||||
case( state )
|
case( state )
|
||||||
DECODE: write_register = load_reg & ~plp;
|
DECODE: write_register = load_reg & ~plp;
|
||||||
|
|
||||||
PULL1,
|
PULL1,
|
||||||
RTS2,
|
RTS2,
|
||||||
RTI3,
|
RTI3,
|
||||||
BRK3,
|
BRK3,
|
||||||
JSR0,
|
JSR0,
|
||||||
@@ -590,7 +590,7 @@ assign AN1 = AN;
|
|||||||
assign AZ1 = AZ;
|
assign AZ1 = AZ;
|
||||||
|
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* write to a register. Usually this is the (BCD corrected) output of the
|
* 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
|
* ALU, but in case of the JSR0 we use the S register to temporarily store
|
||||||
@@ -603,10 +603,10 @@ always @(posedge clk)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* register select logic. This determines which of the A, X, Y or
|
* register select logic. This determines which of the A, X, Y or
|
||||||
* S registers will be accessed.
|
* S registers will be accessed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
always @*
|
always @*
|
||||||
case( state )
|
case( state )
|
||||||
INDY1,
|
INDY1,
|
||||||
INDX0,
|
INDX0,
|
||||||
@@ -615,7 +615,7 @@ always @*
|
|||||||
ABSX0 : regsel = index_y ? SEL_Y : SEL_X;
|
ABSX0 : regsel = index_y ? SEL_Y : SEL_X;
|
||||||
|
|
||||||
|
|
||||||
DECODE : regsel = dst_reg;
|
DECODE : regsel = dst_reg;
|
||||||
|
|
||||||
BRK0,
|
BRK0,
|
||||||
BRK3,
|
BRK3,
|
||||||
@@ -628,8 +628,8 @@ always @*
|
|||||||
RTI3,
|
RTI3,
|
||||||
RTS0,
|
RTS0,
|
||||||
RTS2 : regsel = SEL_S;
|
RTS2 : regsel = SEL_S;
|
||||||
|
|
||||||
default: regsel = src_reg;
|
default: regsel = src_reg;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -659,10 +659,10 @@ always @*
|
|||||||
case( state )
|
case( state )
|
||||||
READ: alu_op = op;
|
READ: alu_op = op;
|
||||||
|
|
||||||
BRA1: alu_op = backwards ? OP_SUB : OP_ADD;
|
BRA1: alu_op = backwards ? OP_SUB : OP_ADD;
|
||||||
|
|
||||||
FETCH,
|
FETCH,
|
||||||
REG : alu_op = op;
|
REG : alu_op = op;
|
||||||
|
|
||||||
DECODE,
|
DECODE,
|
||||||
ABS1: alu_op = 1'bx;
|
ABS1: alu_op = 1'bx;
|
||||||
@@ -688,15 +688,15 @@ always @*
|
|||||||
alu_shift_right = 0;
|
alu_shift_right = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sign extend branch offset.
|
* Sign extend branch offset.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if( RDY )
|
if( RDY )
|
||||||
backwards <= DIMUX[7];
|
backwards <= DIMUX[7];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ALU A Input MUX
|
* ALU A Input MUX
|
||||||
*/
|
*/
|
||||||
|
|
||||||
always @*
|
always @*
|
||||||
@@ -727,7 +727,7 @@ always @*
|
|||||||
BRA0,
|
BRA0,
|
||||||
READ: AI = DIMUX;
|
READ: AI = DIMUX;
|
||||||
|
|
||||||
BRA1: AI = ABH; // don't use PCH in case we're
|
BRA1: AI = ABH; // don't use PCH in case we're
|
||||||
|
|
||||||
FETCH: AI = load_only ? 0 : regfile;
|
FETCH: AI = load_only ? 0 : regfile;
|
||||||
|
|
||||||
@@ -757,7 +757,7 @@ always @*
|
|||||||
BRK0,
|
BRK0,
|
||||||
BRK1,
|
BRK1,
|
||||||
BRK2,
|
BRK2,
|
||||||
PUSH0,
|
PUSH0,
|
||||||
PUSH1,
|
PUSH1,
|
||||||
PULL0,
|
PULL0,
|
||||||
RTS0: BI = 8'h00;
|
RTS0: BI = 8'h00;
|
||||||
@@ -790,8 +790,8 @@ always @*
|
|||||||
REG: CI = rotate ? C :
|
REG: CI = rotate ? C :
|
||||||
shift ? 0 : inc;
|
shift ? 0 : inc;
|
||||||
|
|
||||||
FETCH: CI = rotate ? C :
|
FETCH: CI = rotate ? C :
|
||||||
compare ? 1 :
|
compare ? 1 :
|
||||||
(shift | load_only) ? 0 : C;
|
(shift | load_only) ? 0 : C;
|
||||||
|
|
||||||
PULL0,
|
PULL0,
|
||||||
@@ -801,7 +801,7 @@ always @*
|
|||||||
RTS0,
|
RTS0,
|
||||||
RTS1,
|
RTS1,
|
||||||
INDY0,
|
INDY0,
|
||||||
INDX1: CI = 1;
|
INDX1: CI = 1;
|
||||||
|
|
||||||
default: CI = 0;
|
default: CI = 0;
|
||||||
endcase
|
endcase
|
||||||
@@ -815,7 +815,7 @@ always @*
|
|||||||
* Update C flag when doing ADC/SBC, shift/rotate, compare
|
* Update C flag when doing ADC/SBC, shift/rotate, compare
|
||||||
*/
|
*/
|
||||||
always @(posedge clk )
|
always @(posedge clk )
|
||||||
if( shift && state == WRITE )
|
if( shift && state == WRITE )
|
||||||
C <= CO;
|
C <= CO;
|
||||||
else if( state == RTI2 )
|
else if( state == RTI2 )
|
||||||
C <= DIMUX[0];
|
C <= DIMUX[0];
|
||||||
@@ -832,15 +832,15 @@ always @(posedge clk )
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Special Z flag got TRB/TSB
|
* Special Z flag got TRB/TSB
|
||||||
*/
|
*/
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
AZ2 <= ~|(AI & regfile);
|
AZ2 <= ~|(AI & regfile);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update Z, N flags when writing A, X, Y, Memory, or when doing compare
|
* Update Z, N flags when writing A, X, Y, Memory, or when doing compare
|
||||||
*/
|
*/
|
||||||
|
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if( state == WRITE)
|
if( state == WRITE)
|
||||||
Z <= txb_ins ? AZ2 : AZ1;
|
Z <= txb_ins ? AZ2 : AZ1;
|
||||||
else if( state == RTI2 )
|
else if( state == RTI2 )
|
||||||
@@ -883,7 +883,7 @@ always @(posedge clk)
|
|||||||
/*
|
/*
|
||||||
* Update D flag
|
* Update D flag
|
||||||
*/
|
*/
|
||||||
always @(posedge clk )
|
always @(posedge clk )
|
||||||
if( state == RTI2 )
|
if( state == RTI2 )
|
||||||
D <= DIMUX[3];
|
D <= DIMUX[3];
|
||||||
else if( state == DECODE ) begin
|
else if( state == DECODE ) begin
|
||||||
@@ -896,7 +896,7 @@ always @(posedge clk )
|
|||||||
* Update V flag
|
* Update V flag
|
||||||
*/
|
*/
|
||||||
always @(posedge clk )
|
always @(posedge clk )
|
||||||
if( state == RTI2 )
|
if( state == RTI2 )
|
||||||
V <= DIMUX[6];
|
V <= DIMUX[6];
|
||||||
else if( state == DECODE ) begin
|
else if( state == DECODE ) begin
|
||||||
if( adc_sbc ) V <= AV;
|
if( adc_sbc ) V <= AV;
|
||||||
@@ -939,8 +939,8 @@ assign IR = (IRQ & ~I) | NMI_edge ? 8'h00 :
|
|||||||
IRHOLD_valid ? IRHOLD : DIMUX;
|
IRHOLD_valid ? IRHOLD : DIMUX;
|
||||||
|
|
||||||
//assign DIMUX = ~RDY1 ? DIHOLD : DI;
|
//assign DIMUX = ~RDY1 ? DIHOLD : DI;
|
||||||
|
|
||||||
assign DIMUX = DI;
|
assign DIMUX = DI;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Microcode state machine
|
* Microcode state machine
|
||||||
@@ -949,7 +949,7 @@ always @(posedge clk or posedge reset)
|
|||||||
if( reset )
|
if( reset )
|
||||||
state <= BRK0;
|
state <= BRK0;
|
||||||
else if( RDY ) case( state )
|
else if( RDY ) case( state )
|
||||||
DECODE :
|
DECODE :
|
||||||
casex ( IR )
|
casex ( IR )
|
||||||
// TODO Review for simplifications as in verilog the first matching case has priority
|
// TODO Review for simplifications as in verilog the first matching case has priority
|
||||||
8'b0000_0000: state <= BRK0;
|
8'b0000_0000: state <= BRK0;
|
||||||
@@ -957,23 +957,23 @@ always @(posedge clk or posedge reset)
|
|||||||
8'b0010_1100: state <= ABS0; // BIT abs
|
8'b0010_1100: state <= ABS0; // BIT abs
|
||||||
8'b1001_1100: state <= ABS0; // STZ abs
|
8'b1001_1100: state <= ABS0; // STZ abs
|
||||||
8'b000x_1100: state <= ABS0; // TSB/TRB
|
8'b000x_1100: state <= ABS0; // TSB/TRB
|
||||||
8'b0100_0000: state <= RTI0; //
|
8'b0100_0000: state <= RTI0; //
|
||||||
8'b0100_1100: state <= JMP0;
|
8'b0100_1100: state <= JMP0;
|
||||||
8'b0110_0000: state <= RTS0;
|
8'b0110_0000: state <= RTS0;
|
||||||
8'b0110_1100: state <= JMPI0;
|
8'b0110_1100: state <= JMPI0;
|
||||||
8'b0111_1100: state <= JMPIX0;
|
8'b0111_1100: state <= JMPIX0;
|
||||||
`ifdef IMPLEMENT_NOPS
|
`ifdef IMPLEMENT_NOPS
|
||||||
8'bxxxx_xx11: state <= REG; // (NOP1: 3/7/B/F column)
|
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'bxxx0_0010: state <= FETCH; // (NOP2: 2 column, 4 column handled correctly below)
|
||||||
8'bx1x1_1100: state <= ABS0; // (NOP3: C column)
|
8'bx1x1_1100: state <= ABS0; // (NOP3: C column)
|
||||||
`endif
|
`endif
|
||||||
8'b0x00_1000: state <= PUSH0;
|
8'b0x00_1000: state <= PUSH0;
|
||||||
8'b0x10_1000: state <= PULL0;
|
8'b0x10_1000: state <= PULL0;
|
||||||
8'b0xx1_1000: state <= REG; // CLC, SEC, CLI, SEI
|
8'b0xx1_1000: state <= REG; // CLC, SEC, CLI, SEI
|
||||||
8'b11x0_00x0: state <= FETCH; // IMM
|
8'b11x0_00x0: state <= FETCH; // IMM
|
||||||
8'b1x10_00x0: state <= FETCH; // IMM
|
8'b1x10_00x0: state <= FETCH; // IMM
|
||||||
8'b1xx0_1100: state <= ABS0; // X/Y abs
|
8'b1xx0_1100: state <= ABS0; // X/Y abs
|
||||||
8'b1xxx_1000: state <= REG; // DEY, TYA, ...
|
8'b1xxx_1000: state <= REG; // DEY, TYA, ...
|
||||||
8'bxxx0_0001: state <= INDX0;
|
8'bxxx0_0001: state <= INDX0;
|
||||||
8'bxxx1_0010: state <= IND0; // (ZP) odd 2 column
|
8'bxxx1_0010: state <= IND0; // (ZP) odd 2 column
|
||||||
8'b000x_0100: state <= ZP0; // TSB/TRB
|
8'b000x_0100: state <= ZP0; // TSB/TRB
|
||||||
@@ -1028,18 +1028,18 @@ always @(posedge clk or posedge reset)
|
|||||||
FETCH : state <= DECODE;
|
FETCH : state <= DECODE;
|
||||||
|
|
||||||
REG : state <= DECODE;
|
REG : state <= DECODE;
|
||||||
|
|
||||||
PUSH0 : state <= PUSH1;
|
PUSH0 : state <= PUSH1;
|
||||||
PUSH1 : state <= DECODE;
|
PUSH1 : state <= DECODE;
|
||||||
|
|
||||||
PULL0 : state <= PULL1;
|
PULL0 : state <= PULL1;
|
||||||
PULL1 : state <= PULL2;
|
PULL1 : state <= PULL2;
|
||||||
PULL2 : state <= DECODE;
|
PULL2 : state <= DECODE;
|
||||||
|
|
||||||
JSR0 : state <= JSR1;
|
JSR0 : state <= JSR1;
|
||||||
JSR1 : state <= JSR2;
|
JSR1 : state <= JSR2;
|
||||||
JSR2 : state <= JSR3;
|
JSR2 : state <= JSR3;
|
||||||
JSR3 : state <= FETCH;
|
JSR3 : state <= FETCH;
|
||||||
|
|
||||||
RTI0 : state <= RTI1;
|
RTI0 : state <= RTI1;
|
||||||
RTI1 : state <= RTI2;
|
RTI1 : state <= RTI2;
|
||||||
@@ -1057,7 +1057,7 @@ always @(posedge clk or posedge reset)
|
|||||||
BRA2 : state <= DECODE;
|
BRA2 : state <= DECODE;
|
||||||
|
|
||||||
JMP0 : state <= JMP1;
|
JMP0 : state <= JMP1;
|
||||||
JMP1 : state <= DECODE;
|
JMP1 : state <= DECODE;
|
||||||
|
|
||||||
JMPI0 : state <= JMPI1;
|
JMPI0 : state <= JMPI1;
|
||||||
JMPI1 : state <= JMP0;
|
JMPI1 : state <= JMP0;
|
||||||
@@ -1087,7 +1087,7 @@ always @(posedge clk)
|
|||||||
8'b0xxx_1010, // ASLA, INCA, ROLA, DECA, LSRA, PHY, RORA, PLY
|
8'b0xxx_1010, // ASLA, INCA, ROLA, DECA, LSRA, PHY, RORA, PLY
|
||||||
8'b0xxx_xx01, // ORA, AND, EOR, ADC
|
8'b0xxx_xx01, // ORA, AND, EOR, ADC
|
||||||
8'b100x_10x0, // DEY, TYA, TXA, TXS
|
8'b100x_10x0, // DEY, TYA, TXA, TXS
|
||||||
8'b1010_xxx0, // LDA/LDX/LDY
|
8'b1010_xxx0, // LDA/LDX/LDY
|
||||||
8'b1011_1010, // TSX
|
8'b1011_1010, // TSX
|
||||||
8'b1011_x1x0, // LDX/LDY
|
8'b1011_x1x0, // LDX/LDY
|
||||||
8'b1100_1010, // DEX
|
8'b1100_1010, // DEX
|
||||||
@@ -1127,15 +1127,15 @@ always @(posedge clk)
|
|||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if( state == DECODE && RDY )
|
if( state == DECODE && RDY )
|
||||||
casex( IR )
|
casex( IR )
|
||||||
8'b1011_1010: // TSX
|
8'b1011_1010: // TSX
|
||||||
src_reg <= SEL_S;
|
src_reg <= SEL_S;
|
||||||
|
|
||||||
8'b100x_x110, // STX
|
8'b100x_x110, // STX
|
||||||
8'b100x_1x10, // TXA, TXS
|
8'b100x_1x10, // TXA, TXS
|
||||||
8'b1110_xx00, // INX, CPX
|
8'b1110_xx00, // INX, CPX
|
||||||
8'b1101_1010, // PHX
|
8'b1101_1010, // PHX
|
||||||
8'b1100_1010: // DEX
|
8'b1100_1010: // DEX
|
||||||
src_reg <= SEL_X;
|
src_reg <= SEL_X;
|
||||||
|
|
||||||
8'b100x_x100, // STY
|
8'b100x_x100, // STY
|
||||||
8'b1001_1000, // TYA
|
8'b1001_1000, // TYA
|
||||||
@@ -1147,7 +1147,7 @@ always @(posedge clk)
|
|||||||
default: src_reg <= SEL_A;
|
default: src_reg <= SEL_A;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if( state == DECODE && RDY )
|
if( state == DECODE && RDY )
|
||||||
casex( IR )
|
casex( IR )
|
||||||
8'bxxx1_0001, // INDY
|
8'bxxx1_0001, // INDY
|
||||||
@@ -1178,7 +1178,7 @@ always @(posedge clk )
|
|||||||
casex( IR ) // DMB: Checked for 65C02 NOP collisions
|
casex( IR ) // DMB: Checked for 65C02 NOP collisions
|
||||||
8'b0xxx_x110, // ASL, ROL, LSR, ROR
|
8'b0xxx_x110, // ASL, ROL, LSR, ROR
|
||||||
8'b000x_x100, // TSB/TRB
|
8'b000x_x100, // TSB/TRB
|
||||||
8'b11xx_x110: // DEC/INC
|
8'b11xx_x110: // DEC/INC
|
||||||
write_back <= 1;
|
write_back <= 1;
|
||||||
|
|
||||||
default: write_back <= 0;
|
default: write_back <= 0;
|
||||||
@@ -1197,7 +1197,7 @@ always @(posedge clk )
|
|||||||
if( state == DECODE && RDY )
|
if( state == DECODE && RDY )
|
||||||
casex( IR )
|
casex( IR )
|
||||||
8'b0001_1010, // INCA
|
8'b0001_1010, // INCA
|
||||||
8'b111x_x110, // INC
|
8'b111x_x110, // INC
|
||||||
8'b11x0_1000: // INX, INY
|
8'b11x0_1000: // INX, INY
|
||||||
inc <= 1;
|
inc <= 1;
|
||||||
|
|
||||||
@@ -1240,7 +1240,7 @@ always @(posedge clk )
|
|||||||
8'b1101_0010, // CMP (zp)
|
8'b1101_0010, // CMP (zp)
|
||||||
8'b11x0_0x00, // CPX, CPY (imm/zp)
|
8'b11x0_0x00, // CPX, CPY (imm/zp)
|
||||||
8'b11x0_1100, // CPX, CPY (abs)
|
8'b11x0_1100, // CPX, CPY (abs)
|
||||||
8'b110x_xx01: // CMP
|
8'b110x_xx01: // CMP
|
||||||
compare <= 1;
|
compare <= 1;
|
||||||
|
|
||||||
default: compare <= 0;
|
default: compare <= 0;
|
||||||
@@ -1253,17 +1253,17 @@ always @(posedge clk )
|
|||||||
8'b01xx_1x10: // ROR, LSR
|
8'b01xx_1x10: // ROR, LSR
|
||||||
shift_right <= 1;
|
shift_right <= 1;
|
||||||
|
|
||||||
default: shift_right <= 0;
|
default: shift_right <= 0;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
always @(posedge clk )
|
always @(posedge clk )
|
||||||
if( state == DECODE && RDY )
|
if( state == DECODE && RDY )
|
||||||
casex( IR )
|
casex( IR )
|
||||||
8'b0x10_1010, // ROL A, ROR A
|
8'b0x10_1010, // ROL A, ROR A
|
||||||
8'b0x1x_x110: // ROR, ROL
|
8'b0x1x_x110: // ROR, ROL
|
||||||
rotate <= 1;
|
rotate <= 1;
|
||||||
|
|
||||||
default: rotate <= 0;
|
default: rotate <= 0;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
always @(posedge clk )
|
always @(posedge clk )
|
||||||
@@ -1290,8 +1290,8 @@ always @(posedge clk )
|
|||||||
8'b11x1_0010, // CMP, SBC (zp)
|
8'b11x1_0010, // CMP, SBC (zp)
|
||||||
8'b0011_1010, // DEC A
|
8'b0011_1010, // DEC A
|
||||||
8'b1000_1000, // DEY
|
8'b1000_1000, // DEY
|
||||||
8'b1100_1010, // DEX
|
8'b1100_1010, // DEX
|
||||||
8'b110x_x110, // DEC
|
8'b110x_x110, // DEC
|
||||||
8'b11xx_xx01, // CMP, SBC
|
8'b11xx_xx01, // CMP, SBC
|
||||||
8'b11x0_0x00, // CPX, CPY (imm, zpg)
|
8'b11x0_0x00, // CPX, CPY (imm, zpg)
|
||||||
8'b11x0_1100: op <= OP_SUB;
|
8'b11x0_1100: op <= OP_SUB;
|
||||||
@@ -1301,8 +1301,8 @@ always @(posedge clk )
|
|||||||
8'b010x_xx01, // EOR
|
8'b010x_xx01, // EOR
|
||||||
8'b00xx_xx01: // ORA, AND
|
8'b00xx_xx01: // ORA, AND
|
||||||
op <= { 2'b11, IR[6:5] };
|
op <= { 2'b11, IR[6:5] };
|
||||||
|
|
||||||
default: op <= OP_ADD;
|
default: op <= OP_ADD;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
always @(posedge clk )
|
always @(posedge clk )
|
||||||
|
|||||||
Reference in New Issue
Block a user