From 756b96d9e281528442bf89f57d7fa3944519a936 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Sat, 18 Apr 2026 16:18:57 -0700 Subject: [PATCH] Kinda working --- sim/verilog6502_wrapper_tb.sv | 4 +- sim/verilog6502_wrapper_test.py | 10 +++-- src/regs/verilog6502_io_regs.rdl | 10 +++++ src/regs/verilog6502_io_regs.sv | 39 +++++++++++++++++ src/regs/verilog6502_io_regs_pkg.sv | 9 ++++ src/verilog6502_addr_decoder.sv | 12 ++---- src/verilog6502_internal_memory.sv | 65 ++++++++++++++++++++++++++++- src/verilog6502_wrapper.sv | 9 +++- sub/verilog-6502 | 2 +- 9 files changed, 143 insertions(+), 17 deletions(-) diff --git a/sim/verilog6502_wrapper_tb.sv b/sim/verilog6502_wrapper_tb.sv index 176a718..b833611 100644 --- a/sim/verilog6502_wrapper_tb.sv +++ b/sim/verilog6502_wrapper_tb.sv @@ -11,6 +11,7 @@ logic rst; logic o_irq_ext; logic i_irq_ext; +logic i_nmi_ext; verilog6502_wrapper u_dut( @@ -22,7 +23,8 @@ verilog6502_wrapper u_dut( .s_axi_rd(s_axi), .s_axi_wr(s_axi), .o_irq_ext(o_irq_ext), - .i_irq_ext(i_irq_ext) + .i_irq_ext(i_irq_ext), + .i_nmi_ext(i_nmi_ext) ); endmodule \ No newline at end of file diff --git a/sim/verilog6502_wrapper_test.py b/sim/verilog6502_wrapper_test.py index 28c4ca0..30c2be0 100644 --- a/sim/verilog6502_wrapper_test.py +++ b/sim/verilog6502_wrapper_test.py @@ -29,12 +29,16 @@ async def test_sanity(dut): for _ in range(10): await RisingEdge(dut.clk) - await s_axi.write(0x0, [0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + await s_axi.write(0x200, [0x58, 0xa9, 0x00, 0x1a, 0xcb, 0x4c, 0x02, 0x03]) - cocotb.start_soon(s_axi.read(0x0, 8)) + cocotb.start_soon(s_axi.read(0x200, 8)) await Timer(10, "us") await s_apb.write_dword(0x0, 0) - await Timer(10, "us") \ No newline at end of file + await Timer(1, "us") + + dut.i_nmi_ext.value = Immediate(1) + + await Timer(1, "us") \ No newline at end of file diff --git a/src/regs/verilog6502_io_regs.rdl b/src/regs/verilog6502_io_regs.rdl index a8301ec..853c8f6 100644 --- a/src/regs/verilog6502_io_regs.rdl +++ b/src/regs/verilog6502_io_regs.rdl @@ -15,6 +15,16 @@ addrmap verilog6502_io_regs { } core_ctrl @ 0x0; + reg { + name = "nmi"; + + field { + name = "nmi"; + desc = ""; + hw = r; + sw = rw; + } nmi[31:16] = 0x200; + } nmi @ 0xff8; reg { name = "reset_brq"; diff --git a/src/regs/verilog6502_io_regs.sv b/src/regs/verilog6502_io_regs.sv index 3f5e267..93c8a16 100644 --- a/src/regs/verilog6502_io_regs.sv +++ b/src/regs/verilog6502_io_regs.sv @@ -87,6 +87,7 @@ module verilog6502_io_regs ( //-------------------------------------------------------------------------- typedef struct { logic core_ctrl; + logic nmi; logic reset_brq; } decoded_reg_strb_t; decoded_reg_strb_t decoded_reg_strb; @@ -103,6 +104,7 @@ module verilog6502_io_regs ( is_valid_addr = '1; // No valid address check is_valid_rw = '1; // No valid RW check decoded_reg_strb.core_ctrl = cpuif_req_masked & (cpuif_addr == 12'h0); + decoded_reg_strb.nmi = cpuif_req_masked & (cpuif_addr == 12'hff8); decoded_reg_strb.reset_brq = cpuif_req_masked & (cpuif_addr == 12'hffc); decoded_err = '0; end @@ -124,6 +126,12 @@ module verilog6502_io_regs ( logic load_next; } reset; } core_ctrl; + struct { + struct { + logic [15:0] next; + logic load_next; + } nmi; + } nmi; struct { struct { logic [15:0] next; @@ -143,6 +151,11 @@ module verilog6502_io_regs ( logic value; } reset; } core_ctrl; + struct { + struct { + logic [15:0] value; + } nmi; + } nmi; struct { struct { logic [15:0] value; @@ -177,6 +190,29 @@ module verilog6502_io_regs ( end end assign hwif_out.core_ctrl.reset.value = field_storage.core_ctrl.reset.value; + // Field: verilog6502_io_regs.nmi.nmi + always_comb begin + automatic logic [15:0] next_c; + automatic logic load_next_c; + next_c = field_storage.nmi.nmi.value; + load_next_c = '0; + if(decoded_reg_strb.nmi && decoded_req_is_wr) begin // SW write + next_c = (field_storage.nmi.nmi.value & ~decoded_wr_biten[31:16]) | (decoded_wr_data[31:16] & decoded_wr_biten[31:16]); + load_next_c = '1; + end + field_combo.nmi.nmi.next = next_c; + field_combo.nmi.nmi.load_next = load_next_c; + end + always_ff @(posedge clk) begin + if(rst) begin + field_storage.nmi.nmi.value <= 16'h200; + end else begin + if(field_combo.nmi.nmi.load_next) begin + field_storage.nmi.nmi.value <= field_combo.nmi.nmi.next; + end + end + end + assign hwif_out.nmi.nmi.value = field_storage.nmi.nmi.value; // Field: verilog6502_io_regs.reset_brq.reset always_comb begin automatic logic [15:0] next_c; @@ -247,6 +283,9 @@ module verilog6502_io_regs ( if(rd_mux_addr == 12'h0) begin readback_data_var[0] = field_storage.core_ctrl.reset.value; end + if(rd_mux_addr == 12'hff8) begin + readback_data_var[31:16] = field_storage.nmi.nmi.value; + end if(rd_mux_addr == 12'hffc) begin readback_data_var[15:0] = field_storage.reset_brq.reset.value; readback_data_var[31:16] = field_storage.reset_brq.brk.value; diff --git a/src/regs/verilog6502_io_regs_pkg.sv b/src/regs/verilog6502_io_regs_pkg.sv index 3750542..99cacae 100644 --- a/src/regs/verilog6502_io_regs_pkg.sv +++ b/src/regs/verilog6502_io_regs_pkg.sv @@ -15,6 +15,14 @@ package verilog6502_io_regs_pkg; verilog6502_io_regs__core_ctrl__reset__out_t reset; } verilog6502_io_regs__core_ctrl__out_t; + typedef struct { + logic [15:0] value; + } verilog6502_io_regs__nmi__nmi__out_t; + + typedef struct { + verilog6502_io_regs__nmi__nmi__out_t nmi; + } verilog6502_io_regs__nmi__out_t; + typedef struct { logic [15:0] value; } verilog6502_io_regs__reset_brq__reset__out_t; @@ -30,6 +38,7 @@ package verilog6502_io_regs_pkg; typedef struct { verilog6502_io_regs__core_ctrl__out_t core_ctrl; + verilog6502_io_regs__nmi__out_t nmi; verilog6502_io_regs__reset_brq__out_t reset_brq; } verilog6502_io_regs__out_t; endpackage diff --git a/src/verilog6502_addr_decoder.sv b/src/verilog6502_addr_decoder.sv index 7ef3b38..84cbaa8 100644 --- a/src/verilog6502_addr_decoder.sv +++ b/src/verilog6502_addr_decoder.sv @@ -6,9 +6,8 @@ module verilog6502_addr_decoder( input logic [7:0] i_cpu_data, output logic [7:0] o_cpu_data, input logic i_cpu_we, - /* verilator lint_off UNOPTFLAT */ + input logic i_cpu_rdy, output logic o_cpu_rdy, - /* verilator lint_on UNOPTFLAT */ output logic [15:0] o_mem_addr, @@ -95,28 +94,23 @@ always_comb begin o_mem_we = i_cpu_we & o_cpu_rdy; o_mem_rd = ~i_cpu_we & o_cpu_rdy; prev_addr_next = MEM; - // o_cpu_rdy = i_mem_rdy; - // o_cpu_data = i_mem_data; end else if (i_cpu_addr < 16'hF000) begin o_external_addr = {4'b0, i_cpu_addr[11:0]}; o_external_data = i_cpu_data; o_external_we = i_cpu_we & o_cpu_rdy; o_external_rd = ~i_cpu_we & o_cpu_rdy; prev_addr_next = EXT; - // o_cpu_rdy = i_external_rdy; - // o_cpu_data = i_external_data; end else begin o_io_addr = {4'b0, i_cpu_addr[11:0]}; o_io_data = i_cpu_data; o_io_we = i_cpu_we & o_cpu_rdy; o_io_rd = ~i_cpu_we & o_cpu_rdy; prev_addr_next = IO; - // o_cpu_rdy = i_io_rdy; - // o_cpu_data = i_io_data; end end - if (i_rst) begin + if (i_rst | ~i_cpu_rdy) begin + prev_addr_next = NONE; o_mem_rd = 0; o_mem_we = 0; o_external_rd = 0; diff --git a/src/verilog6502_internal_memory.sv b/src/verilog6502_internal_memory.sv index 4ac6d92..12b0399 100644 --- a/src/verilog6502_internal_memory.sv +++ b/src/verilog6502_internal_memory.sv @@ -78,6 +78,8 @@ logic [7:0] mem [4][14*1024]; enum logic {CPU, EXT} sel, sel_next; +logic o_rdy_next; + logic [15:0] ram_addr; logic [31:0] ram_wdata; logic [3:0] ram_wstrb; @@ -87,12 +89,21 @@ logic ram_re; logic [31:0] ram_rdata; logic ram_rdata_valid; +logic [1:0] latched_byte_select; + +logic [15:0] pending_addr; +logic [7:0] pending_data; +logic pending_rd; +logic pending_we; + always_ff @(posedge i_clk) begin if (i_rst) begin sel <= CPU; + o_rdy <= '0; end else begin sel <= sel_next; + o_rdy <= o_rdy_next; ram_rdata_valid <= '0; ram_rd_resp_last <= '0; @@ -111,6 +122,26 @@ always_ff @(posedge i_clk) begin end ram_rdata_valid <= '1; ram_rd_resp_last <= ram_cmd_last; + + latched_byte_select <= ram_addr[1:0]; + end + + if (sel == EXT) begin + if (i_we) begin + pending_we <= '1; + pending_addr <= i_addr; + pending_data <= i_data; + end + + if (i_rd) begin + pending_rd <= '1; + pending_addr <= i_addr; + end + end else begin + pending_we <= '0; + pending_rd <= '0; + pending_addr <= '0; + pending_data <= '0; end end end @@ -129,12 +160,44 @@ always_comb begin ram_rd_resp_valid = '0; ram_rd_resp_data = '0; + o_rdy_next = '0; + o_data = '0; + case (sel) CPU: begin // if there was no CPU op, then give external bus a chance - if (~(i_rd | i_we)) begin + if (~(i_rd | i_we | pending_rd | pending_we)) begin sel_next = EXT; end + + if (i_we) begin + ram_addr = i_addr; + ram_wstrb = 4'b1 << i_addr[1:0]; + ram_wdata = {24'b0, i_data} << (i_addr[1:0] * 8); + ram_we = '1; + o_rdy_next = '1; + end + if (pending_we) begin + ram_addr = pending_addr; + ram_wstrb = 4'b1 << pending_addr[1:0]; + ram_wdata = {24'b0, pending_data} << (pending_addr[1:0] * 8); + ram_we = '1; + o_rdy_next = '1; + end + + if (i_rd) begin + ram_addr = i_addr; + ram_re = '1; + o_rdy_next = '1; + end + if (pending_rd) begin + ram_addr = pending_addr; + ram_re = '1; + o_rdy_next = '1; + end + + o_data = ram_rdata[8*latched_byte_select +: 8]; + end EXT: begin diff --git a/src/verilog6502_wrapper.sv b/src/verilog6502_wrapper.sv index e5ee5af..3c452f7 100644 --- a/src/verilog6502_wrapper.sv +++ b/src/verilog6502_wrapper.sv @@ -19,7 +19,8 @@ module verilog6502_wrapper( taxi_axi_if.wr_slv s_axi_wr, output logic o_irq_ext, - input logic i_irq_ext + input logic i_irq_ext, + input logic i_nmi_ext ); taxi_apb_if internal_apb(); @@ -66,12 +67,14 @@ logic cpu_we; logic cpu_irq; logic cpu_nmi; logic cpu_rdy; +logic cpu_rdy_o; logic cpu_sync; assign cpu_clk = clk; assign cpu_reset = hwif_out.core_ctrl.reset.value; -assign cpu_rdy = '1; +assign cpu_irq = i_irq_ext; +assign cpu_nmi = i_nmi_ext; logic [15:0] mem_addr; logic [7:0] mem_data_in; @@ -100,6 +103,7 @@ cpu_65c02 u_cpu_6502( .IRQ (cpu_irq), .NMI (cpu_nmi), .RDY (cpu_rdy), + .RDY_O (cpu_rdy_o), .SYNC (cpu_sync) ); @@ -111,6 +115,7 @@ verilog6502_addr_decoder u_addr_decoder( .i_cpu_data (cpu_data_out), .o_cpu_data (cpu_data_in), .i_cpu_we (cpu_we), + .i_cpu_rdy (cpu_rdy_o), .o_cpu_rdy (cpu_rdy), .o_mem_addr (mem_addr), diff --git a/sub/verilog-6502 b/sub/verilog-6502 index ef2cc5a..8f19e45 160000 --- a/sub/verilog-6502 +++ b/sub/verilog-6502 @@ -1 +1 @@ -Subproject commit ef2cc5ab453b0c35e8c9f459b52eb72be70b71d7 +Subproject commit 8f19e45b40f546e8b0fa58d43c1208d151652984