Add indexed indirect
This commit is contained in:
@@ -339,3 +339,67 @@ async def test_indirect(dut):
|
|||||||
]
|
]
|
||||||
|
|
||||||
await check_instruction_sequence(dut, expected_cpu_outputs)
|
await check_instruction_sequence(dut, expected_cpu_outputs)
|
||||||
|
|
||||||
|
@cocotb.test
|
||||||
|
async def test_indexed_indirect(dut):
|
||||||
|
cocotb.start_soon(Clock(dut.clk, CLK_PERIOD, unit="ns").start())
|
||||||
|
cocotb.start_soon(handle_memory(dut))
|
||||||
|
|
||||||
|
write_dword(0xfffffff4, 0x200)
|
||||||
|
|
||||||
|
# ldy #1
|
||||||
|
# lda ($04),y
|
||||||
|
# iny
|
||||||
|
# inc
|
||||||
|
# sta ($04),y
|
||||||
|
write_bytes(0x200, [0xa0, 0x02])
|
||||||
|
write_bytes(0x202, [0xb1, 0x04])
|
||||||
|
write_bytes(0x204, [0xc8])
|
||||||
|
write_bytes(0x205, [0x1a])
|
||||||
|
write_bytes(0x206, [0x91, 0x04])
|
||||||
|
write_byte(0x208, 0xcb)
|
||||||
|
|
||||||
|
write_dword(0x04, 0xabcdbeef)
|
||||||
|
write_dword(0xabcdbeef+2, 0xaa)
|
||||||
|
|
||||||
|
dut.RDY.value = Immediate(1)
|
||||||
|
|
||||||
|
dut.reset.value = Immediate(1)
|
||||||
|
for _ in range(10):
|
||||||
|
await RisingEdge(dut.clk)
|
||||||
|
dut.reset.value = 0
|
||||||
|
|
||||||
|
expected_cpu_outputs = [
|
||||||
|
None, # ignore reset sequence
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
(0x00000200, False, None), # ldy #0
|
||||||
|
(0x00000201, False, None), # Immediate
|
||||||
|
(0x00000202, False, None), # lda ($04),y
|
||||||
|
(0x00000203, False, None), # ZP index
|
||||||
|
(0x00000004, False, None), # zp addr 0
|
||||||
|
(0x00000005, False, None), # zp addr 1
|
||||||
|
(0x00000006, False, None), # zp addr 2
|
||||||
|
(0x00000007, False, None), # zp addr 3
|
||||||
|
(0xabcdbef1, False, None), # fetch data
|
||||||
|
(0x00000204, False, None), # iny
|
||||||
|
(0x00000205, False, None), # iny
|
||||||
|
(0x00000205, False, None), # inc
|
||||||
|
(0x00000206, False, None), # inc
|
||||||
|
(0x00000206, False, None), # sta ($04),y
|
||||||
|
(0x00000207, False, None), # ZP index
|
||||||
|
(0x00000004, False, None), # zp addr 0
|
||||||
|
(0x00000005, False, None), # zp addr 1
|
||||||
|
(0x00000006, False, None), # zp addr 2
|
||||||
|
(0x00000007, False, None), # zp addr 3
|
||||||
|
(0xabcdbef2, False, None), # store takes extra cycle
|
||||||
|
(0xabcdbef2, True, 0xAB), # write data
|
||||||
|
]
|
||||||
|
|
||||||
|
await check_instruction_sequence(dut, expected_cpu_outputs)
|
||||||
@@ -67,6 +67,7 @@ output reg SYNC; // AB is first cycle of the intruction
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
reg [31:0] PC; // Program Counter
|
reg [31:0] PC; // Program Counter
|
||||||
|
reg abr_inc; // should increase address bus register
|
||||||
reg [31:0] ABR; // Address Bus Register
|
reg [31:0] ABR; // Address Bus Register
|
||||||
wire [7:0] ADD; // Adder Hold Register (registered in ALU)
|
wire [7:0] ADD; // Adder Hold Register (registered in ALU)
|
||||||
reg [7:0] alu_sr_0; // ALU output shift register 0
|
reg [7:0] alu_sr_0; // ALU output shift register 0
|
||||||
@@ -226,10 +227,10 @@ parameter
|
|||||||
INDX1 = 7'd15, // (ZP,X) - fetch LSB at ZP+X, calculate ZP+X+1
|
INDX1 = 7'd15, // (ZP,X) - fetch LSB at ZP+X, calculate ZP+X+1
|
||||||
INDX2 = 7'd16, // (ZP,X) - fetch MSB at ZP+X+1
|
INDX2 = 7'd16, // (ZP,X) - fetch MSB at ZP+X+1
|
||||||
INDX3 = 7'd17, // (ZP,X) - fetch data
|
INDX3 = 7'd17, // (ZP,X) - fetch data
|
||||||
INDY0 = 7'd18, // (ZP),Y - fetch ZP address, and send ZP to ALU (+1)
|
INDY0 = 7'd18, // (ZP),Y - fetch ZP address
|
||||||
INDY1 = 7'd19, // (ZP),Y - fetch at ZP+1, and send LSB to ALU (+Y)
|
INDY1 = 7'd19, // (ZP),Y - fetch at ZP+1, and send byte 0 to ALU (+Y)
|
||||||
INDY2 = 7'd20, // (ZP),Y - fetch data, and send MSB to ALU (+Carry)
|
INDY2 = 7'd20, // (ZP),Y - fetch at ZP+2, and send byte 1 to ALU (+Carry)
|
||||||
INDY3 = 7'd21, // (ZP),Y) - fetch data (if page boundary crossed)
|
INDY5 = 7'd21, // (ZP),Y) - fetch data (if page boundary crossed)
|
||||||
JMP0 = 7'd22, // JMP - fetch PCL and hold
|
JMP0 = 7'd22, // JMP - fetch PCL and hold
|
||||||
JMP1 = 7'd23, // JMP - fetch PCH
|
JMP1 = 7'd23, // JMP - fetch PCH
|
||||||
JMPI0 = 7'd24, // JMP IND - fetch LSB and send to ALU for delay (+0)
|
JMPI0 = 7'd24, // JMP IND - fetch LSB and send to ALU for delay (+0)
|
||||||
@@ -274,7 +275,9 @@ parameter
|
|||||||
JMPIX3 = 7'd63, // TODO
|
JMPIX3 = 7'd63, // TODO
|
||||||
JMPIX4 = 7'd64, // TODO
|
JMPIX4 = 7'd64, // TODO
|
||||||
JMPI2 = 7'd65, // TODO
|
JMPI2 = 7'd65, // TODO
|
||||||
JMPI3 = 7'd66; // TODO
|
JMPI3 = 7'd66, // TODO
|
||||||
|
INDY3 = 7'd67, // (ZP),Y - fetch at ZP+3, and send byte 2 to ALU (+Carry)
|
||||||
|
INDY4 = 7'd68; // (ZP),Y - fetch data, and send byte 3 to ALU (+Carry)
|
||||||
|
|
||||||
`ifdef SIM
|
`ifdef SIM
|
||||||
|
|
||||||
@@ -308,6 +311,8 @@ always @*
|
|||||||
INDY1: statename = "INDY1";
|
INDY1: statename = "INDY1";
|
||||||
INDY2: statename = "INDY2";
|
INDY2: statename = "INDY2";
|
||||||
INDY3: statename = "INDY3";
|
INDY3: statename = "INDY3";
|
||||||
|
INDY4: statename = "INDY4";
|
||||||
|
INDY5: statename = "INDY5";
|
||||||
READ: statename = "READ";
|
READ: statename = "READ";
|
||||||
WRITE: statename = "WRITE";
|
WRITE: statename = "WRITE";
|
||||||
FETCH: statename = "FETCH";
|
FETCH: statename = "FETCH";
|
||||||
@@ -454,14 +459,12 @@ always @*
|
|||||||
JMPIX3,
|
JMPIX3,
|
||||||
ABSX3,
|
ABSX3,
|
||||||
INDX3,
|
INDX3,
|
||||||
INDY2,
|
|
||||||
JMP3,
|
JMP3,
|
||||||
JMPI3,
|
JMPI3,
|
||||||
RTI4,
|
RTI4,
|
||||||
ABS3: AB = { DIMUX, ADD, alu_sr_0, alu_sr_1};
|
ABS3: AB = { DIMUX, ADD, alu_sr_0, alu_sr_1};
|
||||||
|
|
||||||
BRA2,
|
BRA2,
|
||||||
INDY3,
|
|
||||||
JMPIX4,
|
JMPIX4,
|
||||||
ABSX4: AB = { ADD, ABR[23:0] }; // TODO
|
ABSX4: AB = { ADD, ABR[23:0] }; // TODO
|
||||||
|
|
||||||
@@ -485,7 +488,6 @@ always @*
|
|||||||
BRK3,
|
BRK3,
|
||||||
BRK4: AB = { 16'h0, STACKPAGE, ADD };
|
BRK4: AB = { 16'h0, STACKPAGE, ADD };
|
||||||
|
|
||||||
INDY1,
|
|
||||||
INDX1,
|
INDX1,
|
||||||
ZPX1,
|
ZPX1,
|
||||||
INDX2: AB = { ZEROPAGE, ADD };
|
INDX2: AB = { ZEROPAGE, ADD };
|
||||||
@@ -495,8 +497,14 @@ always @*
|
|||||||
|
|
||||||
REG,
|
REG,
|
||||||
READ,
|
READ,
|
||||||
|
INDY1,
|
||||||
|
INDY2,
|
||||||
|
INDY3,
|
||||||
WRITE: AB = ABR;
|
WRITE: AB = ABR;
|
||||||
|
|
||||||
|
INDY4: AB = {DIMUX, ADD, alu_sr_0, alu_sr_1};
|
||||||
|
INDY5: AB = {ADD, ABR[23:0]};
|
||||||
|
|
||||||
default: AB = PC;
|
default: AB = PC;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
@@ -509,9 +517,22 @@ 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
|
||||||
ABR <= AB;
|
if (abr_inc) begin
|
||||||
|
ABR <= AB + 1;
|
||||||
|
end else begin
|
||||||
|
ABR <= AB;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
always @* begin
|
||||||
|
case( state )
|
||||||
|
INDY0,
|
||||||
|
INDY1,
|
||||||
|
INDY2: abr_inc = 1;
|
||||||
|
default: abr_inc = 0;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data Out MUX
|
* Data Out MUX
|
||||||
*/
|
*/
|
||||||
@@ -558,7 +579,7 @@ always @*
|
|||||||
WRITE: WE = 1;
|
WRITE: WE = 1;
|
||||||
|
|
||||||
INDX3, // only if doing a STA, STX or STY
|
INDX3, // only if doing a STA, STX or STY
|
||||||
INDY3,
|
INDY5,
|
||||||
ABSX4,
|
ABSX4,
|
||||||
ABS3,
|
ABS3,
|
||||||
ZPX1,
|
ZPX1,
|
||||||
@@ -1088,8 +1109,10 @@ always @(posedge clk or posedge reset)
|
|||||||
|
|
||||||
INDY0 : state <= INDY1;
|
INDY0 : state <= INDY1;
|
||||||
INDY1 : state <= INDY2;
|
INDY1 : state <= INDY2;
|
||||||
INDY2 : state <= (CO | store) ? INDY3 : FETCH;
|
INDY2 : state <= INDY3;
|
||||||
INDY3 : state <= FETCH;
|
INDY3 : state <= INDY4;
|
||||||
|
INDY4 : state <= (CO | store) ? INDY5 : FETCH;
|
||||||
|
INDY5 : state <= FETCH;
|
||||||
|
|
||||||
READ : state <= WRITE;
|
READ : state <= WRITE;
|
||||||
WRITE : state <= FETCH;
|
WRITE : state <= FETCH;
|
||||||
|
|||||||
Reference in New Issue
Block a user