diff --git a/sim/verilog6502_32bit_test.py b/sim/verilog6502_32bit_test.py index ff55f5d..ace9288 100644 --- a/sim/verilog6502_32bit_test.py +++ b/sim/verilog6502_32bit_test.py @@ -16,6 +16,13 @@ def write_dword(addr: int, data: int): memory[addr + 2] = (data >> 16) & 0xff memory[addr + 3] = (data >> 24) & 0xff +def write_byte(addr: int, data: int): + memory[addr] = data & 0xff + +def write_bytes(addr: int, data: bytes| list[int]): + for i, val in enumerate(data): + memory[addr + i] = int(val) + async def handle_memory(dut): while True: await RisingEdge(dut.clk) @@ -28,7 +35,7 @@ async def handle_memory(dut): memory[addr] = int(dut.DO.value) @cocotb.test -async def test_absolute(dut): +async def test_reset(dut): cocotb.start_soon(Clock(dut.clk, CLK_PERIOD, unit="ns").start()) cocotb.start_soon(handle_memory(dut)) @@ -51,8 +58,8 @@ async def test_absolute(dut): (0xfffffff5, False, int(dut.regfile.value)), # read vector byte 1 (0xfffffff6, False, int(dut.regfile.value)), # read vector byte 2 (0xfffffff7, False, int(dut.regfile.value)), # read vector byte 3 - (0x12345678, False, int(dut.regfile.value)), # Load PC with vector (0x12345678, False, int(dut.regfile.value)), # Read first instruction + (0x12345679, False, int(dut.regfile.value)), # Read second byte ] for expected_output in expected_cpu_outputs: @@ -66,3 +73,64 @@ async def test_absolute(dut): assert dut_addr == expected_addr assert dut_we == expected_we assert dut_do == expected_do + +@cocotb.test +async def test_absolute(dut): + cocotb.start_soon(Clock(dut.clk, CLK_PERIOD, unit="ns").start()) + cocotb.start_soon(handle_memory(dut)) + + write_dword(0xfffffff4, 0x200) + + # lda #$abcd1234 + # wai + write_bytes(0x200, [0xad, 0x34, 0x12, 0xcd, 0xab]) + write_bytes(0x205, [0x8d, 0x53, 0x52, 0x51, 0x50]) + write_byte(0x20a, 0xcb) + write_byte(0xabcd1234, 0x55) + + 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), # Read first instruction + (0x00000201, False, None), # Read address byte 0 + (0x00000202, False, None), # Read address byte 1 + (0x00000203, False, None), # Read address byte 2 + (0x00000204, False, None), # Read address byte 3 + (0xabcd1234, False, None), # Read from absolute address + (0x00000205, False, None), # Read second instruction + (0x00000206, False, None), # Read address byte 0 + (0x00000207, False, None), # Read address byte 1 + (0x00000208, False, None), # Read address byte 2 + (0x00000209, False, None), # Read address byte 3 + (0x50515253, True, 0x55), # Write to absolute address + + ] + + for expected_output in expected_cpu_outputs: + await RisingEdge(dut.clk) + + if expected_output: + expected_addr, expected_we, expected_do = expected_output + dut_addr = int(dut.AB.value) + dut_we = bool(dut.WE.value) + dut_do = int(dut.DO.value) + + assert dut_addr == expected_addr + assert dut_we == expected_we + + if dut_we: + assert dut_do == expected_do diff --git a/src/cpu_65c02.v b/src/cpu_65c02.v index c8da170..21cfa3b 100644 --- a/src/cpu_65c02.v +++ b/src/cpu_65c02.v @@ -266,7 +266,9 @@ parameter BRK4 = 6'd55, // TODO BRK5 = 6'd56, // TODO JMP2 = 6'd57, // TODO - JMP3 = 6'd58; // TODO + JMP3 = 6'd58, // TODO + ABS2 = 6'd59, // TODO + ABS3 = 6'd60; // TODO `ifdef SIM @@ -284,6 +286,8 @@ always @* ZPX1: statename = "ZPX1"; ABS0: statename = "ABS0"; ABS1: statename = "ABS1"; + ABS2: statename = "ABS2"; + ABS3: statename = "ABS3"; ABSX0: statename = "ABSX0"; ABSX1: statename = "ABSX1"; ABSX2: statename = "ABSX2"; @@ -387,6 +391,8 @@ always @* PC_inc = 1; ABS0, + ABS1, + ABS2, JMPIX0, JMPIX2, ABSX0, @@ -398,6 +404,7 @@ always @* JMP0, JMP1, JMP2, + JMP3, RTI4, RTS3: PC_inc = 1; @@ -432,7 +439,7 @@ always @* JMP3, JMPI1, RTI4, - ABS1: AB = { DIMUX, ADD, alu_sr_0, alu_sr_1}; + ABS3: AB = { DIMUX, ADD, alu_sr_0, alu_sr_1}; BRA2, INDY3, @@ -534,7 +541,7 @@ always @* INDX3, // only if doing a STA, STX or STY INDY3, ABSX2, - ABS1, + ABS3, ZPX1, ZP0: WE = store; @@ -694,7 +701,7 @@ always @* REG : alu_op = op; DECODE, - ABS1: alu_op = 1'bx; + ABS3: alu_op = 1'bx; PUSH1, BRK0, @@ -765,7 +772,7 @@ always @* FETCH: AI = load_only ? 8'b0 : regfile; DECODE, - ABS1: AI = 8'hxx; // don't care + ABS3: AI = 8'hxx; // don't care default: AI = 0; endcase @@ -800,7 +807,7 @@ always @* BRA0: BI = PC[7:0]; // TODO DECODE, - ABS1: BI = 8'hxx; + ABS3: BI = 8'hxx; default: BI = DIMUX; endcase @@ -817,7 +824,7 @@ always @* ABSX1: CI = CO; DECODE, - ABS1: CI = 1'bx; + ABS3: CI = 1'bx; READ, REG: CI = rotate ? C : @@ -1035,7 +1042,9 @@ always @(posedge clk or posedge reset) ZPX1 : state <= write_back ? READ : FETCH; ABS0 : state <= ABS1; - ABS1 : state <= write_back ? READ : FETCH; + ABS1 : state <= ABS2; + ABS2 : state <= ABS3; + ABS3 : state <= write_back ? READ : FETCH; ABSX0 : state <= ABSX1; ABSX1 : state <= (CO | store | write_back) ? ABSX2 : FETCH;