From 019b84f41d6ea775194eeeb250fbd0eb185c3779 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Sun, 26 Apr 2026 19:28:39 -0700 Subject: [PATCH] Get reset sequence to work --- sim/verilog6502_32bit_test.py | 50 ++++++++++++++++++++++++++++++++++- src/cpu_65c02.v | 35 ++++++++++++++++++------ 2 files changed, 76 insertions(+), 9 deletions(-) diff --git a/sim/verilog6502_32bit_test.py b/sim/verilog6502_32bit_test.py index 08d111d..ff55f5d 100644 --- a/sim/verilog6502_32bit_test.py +++ b/sim/verilog6502_32bit_test.py @@ -4,11 +4,35 @@ from cocotb.handle import Immediate from cocotb.clock import Clock from cocotb.triggers import Timer, RisingEdge +from collections import defaultdict + CLK_PERIOD = 5 +memory = defaultdict(int) + +def write_dword(addr: int, data: int): + memory[addr + 0] = (data >> 0) & 0xff + memory[addr + 1] = (data >> 8) & 0xff + memory[addr + 2] = (data >> 16) & 0xff + memory[addr + 3] = (data >> 24) & 0xff + +async def handle_memory(dut): + while True: + await RisingEdge(dut.clk) + addr = int(dut.AB.value) + we = bool(dut.WE.value) + + dut.DI.value = memory[addr] + + if we: + memory[addr] = int(dut.DO.value) + @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, 0x12345678) dut.RDY.value = Immediate(1) @@ -17,4 +41,28 @@ async def test_absolute(dut): await RisingEdge(dut.clk) dut.reset.value = 0 - await Timer(1, "us") \ No newline at end of file + expected_cpu_outputs = [ + (0x00000100, True, (int(dut.PC.value) >> 24) & 0xff), # High addr + (0x000001ff, True, (int(dut.PC.value) >> 16) & 0xff), # Mid high addr + (0x000001fe, True, (int(dut.PC.value) >> 8) & 0xff), # Mid low addr + (0x000001fd, True, (int(dut.PC.value) >> 0) & 0xff), # Low addr + (0x000001fc, True, int(dut.P.value)), # Status + (0xfffffff4, False, int(dut.regfile.value)), # read vector byte 0 + (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 + ] + + for expected_output in expected_cpu_outputs: + await RisingEdge(dut.clk) + + 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 + assert dut_do == expected_do diff --git a/src/cpu_65c02.v b/src/cpu_65c02.v index c140cf9..c8da170 100644 --- a/src/cpu_65c02.v +++ b/src/cpu_65c02.v @@ -69,6 +69,8 @@ output reg SYNC; // AB is first cycle of the intruction reg [31:0] PC; // Program Counter reg [31:0] ABR; // Address Bus Register 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_1; // ALU output shift register 1 reg [7:0] DIHOLD; // Hold for Data In reg DIHOLD_valid; // @@ -262,7 +264,9 @@ parameter JMPIX2 = 6'd53, // JMP (,X)- Wait for ALU (only if needed) WAI = 6'd54, // WAI - Wait for interrupt, then go to decode BRK4 = 6'd55, // TODO - BRK5 = 6'd56; // TODO + BRK5 = 6'd56, // TODO + JMP2 = 6'd57, // TODO + JMP3 = 6'd58; // TODO `ifdef SIM @@ -324,6 +328,8 @@ always @* BRA2: statename = "BRA2"; JMP0: statename = "JMP0"; JMP1: statename = "JMP1"; + JMP2: statename = "JMP2"; + JMP3: statename = "JMP3"; JMPI0: statename = "JMPI0"; JMPI1: statename = "JMPI1"; JMPIX0: statename = "JMPIX0"; @@ -352,19 +358,19 @@ always @* PC_temp = PC; - JMP1, + JMP3, JMPI1, JMPIX1, JSR3, RTS3, - RTI4: PC_temp = { DIMUX, ADD }; + RTI4: PC_temp = { DIMUX, ADD, alu_sr_0, alu_sr_1}; BRA1: PC_temp = { ABR[15:8], ADD }; JMPIX2, BRA2: PC_temp = { ADD, PC[7:0] }; // TODO - BRK2: PC_temp = res ? 32'hFFFFFFF4 : + BRK4: PC_temp = res ? 32'hFFFFFFF4 : NMI_edge ? 32'hFFFFFFF8 : 32'hFFFFFFFC; default: PC_temp = PC; @@ -389,7 +395,9 @@ always @* BRA2, BRK5, JMPI1, + JMP0, JMP1, + JMP2, RTI4, RTS3: PC_inc = 1; @@ -421,10 +429,10 @@ always @* ABSX1, INDX3, INDY2, - JMP1, + JMP3, JMPI1, RTI4, - ABS1: AB = { DIMUX, ADD }; + ABS1: AB = { DIMUX, ADD, alu_sr_0, alu_sr_1}; BRA2, INDY3, @@ -667,6 +675,11 @@ ALU ALU( .clk(clk), .HC(HC), .RDY(RDY) ); +always @(posedge clk) begin + alu_sr_0 <= ADD; + alu_sr_1 <= alu_sr_0; +end + /* * Select current ALU operation */ @@ -687,6 +700,8 @@ always @* BRK0, BRK1, BRK2, + BRK3, + BRK4, JSR0, JSR1: alu_op = OP_SUB; @@ -723,6 +738,8 @@ always @* RTI2, BRK1, BRK2, + BRK3, + BRK4, INDX1: AI = ADD; REG, @@ -1074,7 +1091,9 @@ always @(posedge clk or posedge reset) BRA2 : state <= DECODE; JMP0 : state <= JMP1; - JMP1 : state <= DECODE; + JMP1 : state <= JMP2; + JMP2 : state <= JMP3; + JMP3 : state <= DECODE; JMPI0 : state <= JMPI1; JMPI1 : state <= JMP0; @@ -1106,7 +1125,7 @@ always @(posedge clk or posedge reset) PUSH1, PULL2, RTI4, - JMP1, + JMP3, BRA2 : SYNC <= 1'b1; default: SYNC <= 1'b0; endcase