Move everything around

This commit is contained in:
2026-05-09 16:00:25 -07:00
parent 089df744aa
commit 9e174a4f02
28 changed files with 13 additions and 400 deletions

View File

@@ -0,0 +1 @@
peakrdl regblock -o . --cpuif taxi-apb verilog6502_io_regs.rdl

View File

@@ -0,0 +1,71 @@
addrmap verilog6502_io_regs {
name = "";
desc = "";
reg {
name = "Core Control";
desc = "";
field {
name = "reset";
desc = "";
hw = r;
sw = rw;
} reset[0:0] = 0x1;
field {
name = "rdy";
desc = "";
hw = r;
sw = rw;
} rdy[1:1] = 0x0;
} core_ctrl @ 0x0;
reg {
name = "Core Status";
desc = "";
field {
name = "rdy_o";
desc = "";
hw = r;
sw = r;
} rdy_o[0:0] = 0x0;
} core_status @ 0x4;
reg {
name = "nmi";
field {
name = "nmi";
desc = "";
hw = r;
sw = rw;
} nmi[31:0] = 0x200;
} nmi @ 0xff4;
reg {
name = "reset";
desc = "";
field {
name = "reset";
desc = "";
hw = r;
sw = rw;
} reset[31:0] = 0x200;
} rst @ 0xff8;
reg {
name = "brk";
field {
name = "brq";
desc = "";
hw = r;
sw = rw;
} brk[31:0] = 0x200;
} brk @ 0xffc;
};

View File

@@ -0,0 +1,346 @@
// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
// https://github.com/SystemRDL/PeakRDL-regblock
module verilog6502_io_regs (
input wire clk,
input wire rst,
taxi_apb_if.slv s_apb,
output verilog6502_io_regs_pkg::verilog6502_io_regs__out_t hwif_out
);
//--------------------------------------------------------------------------
// CPU Bus interface logic
//--------------------------------------------------------------------------
logic cpuif_req;
logic cpuif_req_is_wr;
logic [11:0] cpuif_addr;
logic [31:0] cpuif_wr_data;
logic [31:0] cpuif_wr_biten;
logic cpuif_req_stall_wr;
logic cpuif_req_stall_rd;
logic cpuif_rd_ack;
logic cpuif_rd_err;
logic [31:0] cpuif_rd_data;
logic cpuif_wr_ack;
logic cpuif_wr_err;
`ifndef SYNTHESIS
initial begin
assert_bad_addr_width: assert($bits(s_apb.paddr) >= verilog6502_io_regs_pkg::VERILOG6502_IO_REGS_MIN_ADDR_WIDTH)
else $error("Interface address width of %0d is too small. Shall be at least %0d bits", $bits(s_apb.paddr), verilog6502_io_regs_pkg::VERILOG6502_IO_REGS_MIN_ADDR_WIDTH);
assert_bad_data_width: assert($bits(s_apb.pwdata) == verilog6502_io_regs_pkg::VERILOG6502_IO_REGS_DATA_WIDTH)
else $error("Interface data width of %0d is incorrect. Shall be %0d bits", $bits(s_apb.pwdata), verilog6502_io_regs_pkg::VERILOG6502_IO_REGS_DATA_WIDTH);
end
`endif
// Request
logic is_active;
always_ff @(posedge clk) begin
if(rst) begin
is_active <= '0;
cpuif_req <= '0;
cpuif_req_is_wr <= '0;
cpuif_addr <= '0;
cpuif_wr_data <= '0;
cpuif_wr_biten <= '0;
end else begin
if(~is_active) begin
if(s_apb.psel) begin
is_active <= '1;
cpuif_req <= '1;
cpuif_req_is_wr <= s_apb.pwrite;
cpuif_addr <= {s_apb.paddr[11:2], 2'b0};
cpuif_wr_data <= s_apb.pwdata;
for(int i=0; i<4; i++) begin
cpuif_wr_biten[i*8 +: 8] <= {8{s_apb.pstrb[i]}};
end
end
end else begin
cpuif_req <= '0;
if(cpuif_rd_ack || cpuif_wr_ack) begin
is_active <= '0;
end
end
end
end
// Response
assign s_apb.pready = cpuif_rd_ack | cpuif_wr_ack;
assign s_apb.prdata = cpuif_rd_data;
assign s_apb.pslverr = cpuif_rd_err | cpuif_wr_err;
logic cpuif_req_masked;
// Read & write latencies are balanced. Stalls not required
assign cpuif_req_stall_rd = '0;
assign cpuif_req_stall_wr = '0;
assign cpuif_req_masked = cpuif_req
& !(!cpuif_req_is_wr & cpuif_req_stall_rd)
& !(cpuif_req_is_wr & cpuif_req_stall_wr);
//--------------------------------------------------------------------------
// Address Decode
//--------------------------------------------------------------------------
typedef struct {
logic core_ctrl;
logic core_status;
logic nmi;
logic rst;
logic brk;
} decoded_reg_strb_t;
decoded_reg_strb_t decoded_reg_strb;
logic decoded_err;
logic [11:0] decoded_addr;
logic decoded_req;
logic decoded_req_is_wr;
logic [31:0] decoded_wr_data;
logic [31:0] decoded_wr_biten;
always_comb begin
automatic logic is_valid_addr;
automatic logic is_valid_rw;
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.core_status = cpuif_req_masked & (cpuif_addr == 12'h4) & !cpuif_req_is_wr;
decoded_reg_strb.nmi = cpuif_req_masked & (cpuif_addr == 12'hff4);
decoded_reg_strb.rst = cpuif_req_masked & (cpuif_addr == 12'hff8);
decoded_reg_strb.brk = cpuif_req_masked & (cpuif_addr == 12'hffc);
decoded_err = '0;
end
// Pass down signals to next stage
assign decoded_addr = cpuif_addr;
assign decoded_req = cpuif_req_masked;
assign decoded_req_is_wr = cpuif_req_is_wr;
assign decoded_wr_data = cpuif_wr_data;
assign decoded_wr_biten = cpuif_wr_biten;
//--------------------------------------------------------------------------
// Field logic
//--------------------------------------------------------------------------
typedef struct {
struct {
struct {
logic next;
logic load_next;
} reset;
struct {
logic next;
logic load_next;
} rdy;
} core_ctrl;
struct {
struct {
logic [31:0] next;
logic load_next;
} nmi;
} nmi;
struct {
struct {
logic [31:0] next;
logic load_next;
} reset;
} rst;
struct {
struct {
logic [31:0] next;
logic load_next;
} brk;
} brk;
} field_combo_t;
field_combo_t field_combo;
typedef struct {
struct {
struct {
logic value;
} reset;
struct {
logic value;
} rdy;
} core_ctrl;
struct {
struct {
logic [31:0] value;
} nmi;
} nmi;
struct {
struct {
logic [31:0] value;
} reset;
} rst;
struct {
struct {
logic [31:0] value;
} brk;
} brk;
} field_storage_t;
field_storage_t field_storage;
// Field: verilog6502_io_regs.core_ctrl.reset
always_comb begin
automatic logic [0:0] next_c;
automatic logic load_next_c;
next_c = field_storage.core_ctrl.reset.value;
load_next_c = '0;
if(decoded_reg_strb.core_ctrl && decoded_req_is_wr) begin // SW write
next_c = (field_storage.core_ctrl.reset.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]);
load_next_c = '1;
end
field_combo.core_ctrl.reset.next = next_c;
field_combo.core_ctrl.reset.load_next = load_next_c;
end
always_ff @(posedge clk) begin
if(rst) begin
field_storage.core_ctrl.reset.value <= 1'h1;
end else begin
if(field_combo.core_ctrl.reset.load_next) begin
field_storage.core_ctrl.reset.value <= field_combo.core_ctrl.reset.next;
end
end
end
assign hwif_out.core_ctrl.reset.value = field_storage.core_ctrl.reset.value;
// Field: verilog6502_io_regs.core_ctrl.rdy
always_comb begin
automatic logic [0:0] next_c;
automatic logic load_next_c;
next_c = field_storage.core_ctrl.rdy.value;
load_next_c = '0;
if(decoded_reg_strb.core_ctrl && decoded_req_is_wr) begin // SW write
next_c = (field_storage.core_ctrl.rdy.value & ~decoded_wr_biten[1:1]) | (decoded_wr_data[1:1] & decoded_wr_biten[1:1]);
load_next_c = '1;
end
field_combo.core_ctrl.rdy.next = next_c;
field_combo.core_ctrl.rdy.load_next = load_next_c;
end
always_ff @(posedge clk) begin
if(rst) begin
field_storage.core_ctrl.rdy.value <= 1'h0;
end else begin
if(field_combo.core_ctrl.rdy.load_next) begin
field_storage.core_ctrl.rdy.value <= field_combo.core_ctrl.rdy.next;
end
end
end
assign hwif_out.core_ctrl.rdy.value = field_storage.core_ctrl.rdy.value;
assign hwif_out.core_status.rdy_o.value = 1'h0;
// Field: verilog6502_io_regs.nmi.nmi
always_comb begin
automatic logic [31: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:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]);
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 <= 32'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.rst.reset
always_comb begin
automatic logic [31:0] next_c;
automatic logic load_next_c;
next_c = field_storage.rst.reset.value;
load_next_c = '0;
if(decoded_reg_strb.rst && decoded_req_is_wr) begin // SW write
next_c = (field_storage.rst.reset.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]);
load_next_c = '1;
end
field_combo.rst.reset.next = next_c;
field_combo.rst.reset.load_next = load_next_c;
end
always_ff @(posedge clk) begin
if(rst) begin
field_storage.rst.reset.value <= 32'h200;
end else begin
if(field_combo.rst.reset.load_next) begin
field_storage.rst.reset.value <= field_combo.rst.reset.next;
end
end
end
assign hwif_out.rst.reset.value = field_storage.rst.reset.value;
// Field: verilog6502_io_regs.brk.brk
always_comb begin
automatic logic [31:0] next_c;
automatic logic load_next_c;
next_c = field_storage.brk.brk.value;
load_next_c = '0;
if(decoded_reg_strb.brk && decoded_req_is_wr) begin // SW write
next_c = (field_storage.brk.brk.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]);
load_next_c = '1;
end
field_combo.brk.brk.next = next_c;
field_combo.brk.brk.load_next = load_next_c;
end
always_ff @(posedge clk) begin
if(rst) begin
field_storage.brk.brk.value <= 32'h200;
end else begin
if(field_combo.brk.brk.load_next) begin
field_storage.brk.brk.value <= field_combo.brk.brk.next;
end
end
end
assign hwif_out.brk.brk.value = field_storage.brk.brk.value;
//--------------------------------------------------------------------------
// Write response
//--------------------------------------------------------------------------
assign cpuif_wr_ack = decoded_req & decoded_req_is_wr;
// Writes are always granted with no error response
assign cpuif_wr_err = '0;
//--------------------------------------------------------------------------
// Readback
//--------------------------------------------------------------------------
logic [11:0] rd_mux_addr;
assign rd_mux_addr = decoded_addr;
logic readback_err;
logic readback_done;
logic [31:0] readback_data;
always_comb begin
automatic logic [31:0] readback_data_var;
readback_data_var = '0;
if(rd_mux_addr == 12'h0) begin
readback_data_var[0] = field_storage.core_ctrl.reset.value;
readback_data_var[1] = field_storage.core_ctrl.rdy.value;
end
if(rd_mux_addr == 12'h4) begin
readback_data_var[0] = 1'h0;
end
if(rd_mux_addr == 12'hff4) begin
readback_data_var[31:0] = field_storage.nmi.nmi.value;
end
if(rd_mux_addr == 12'hff8) begin
readback_data_var[31:0] = field_storage.rst.reset.value;
end
if(rd_mux_addr == 12'hffc) begin
readback_data_var[31:0] = field_storage.brk.brk.value;
end
readback_data = readback_data_var;
readback_done = decoded_req & ~decoded_req_is_wr;
readback_err = '0;
end
assign cpuif_rd_ack = readback_done;
assign cpuif_rd_data = readback_data;
assign cpuif_rd_err = readback_err;
endmodule

View File

@@ -0,0 +1,62 @@
// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
// https://github.com/SystemRDL/PeakRDL-regblock
package verilog6502_io_regs_pkg;
localparam VERILOG6502_IO_REGS_DATA_WIDTH = 32;
localparam VERILOG6502_IO_REGS_MIN_ADDR_WIDTH = 12;
localparam VERILOG6502_IO_REGS_SIZE = 'h1000;
typedef struct {
logic value;
} verilog6502_io_regs__core_ctrl__reset__out_t;
typedef struct {
logic value;
} verilog6502_io_regs__core_ctrl__rdy__out_t;
typedef struct {
verilog6502_io_regs__core_ctrl__reset__out_t reset;
verilog6502_io_regs__core_ctrl__rdy__out_t rdy;
} verilog6502_io_regs__core_ctrl__out_t;
typedef struct {
logic value;
} verilog6502_io_regs__core_status__rdy_o__out_t;
typedef struct {
verilog6502_io_regs__core_status__rdy_o__out_t rdy_o;
} verilog6502_io_regs__core_status__out_t;
typedef struct {
logic [31: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 [31:0] value;
} verilog6502_io_regs__rst__reset__out_t;
typedef struct {
verilog6502_io_regs__rst__reset__out_t reset;
} verilog6502_io_regs__rst__out_t;
typedef struct {
logic [31:0] value;
} verilog6502_io_regs__brk__brk__out_t;
typedef struct {
verilog6502_io_regs__brk__brk__out_t brk;
} verilog6502_io_regs__brk__out_t;
typedef struct {
verilog6502_io_regs__core_ctrl__out_t core_ctrl;
verilog6502_io_regs__core_status__out_t core_status;
verilog6502_io_regs__nmi__out_t nmi;
verilog6502_io_regs__rst__out_t rst;
verilog6502_io_regs__brk__out_t brk;
} verilog6502_io_regs__out_t;
endpackage

View File

@@ -0,0 +1,124 @@
module verilog6502_addr_decoder(
input i_clk,
input i_rst,
input logic [31:0] i_cpu_addr,
input logic [7:0] i_cpu_data,
output logic [7:0] o_cpu_data,
input logic i_cpu_we,
input logic i_cpu_rdy,
output logic o_cpu_rdy,
output logic [15:0] o_mem_addr,
output logic [7:0] o_mem_data,
input logic [7:0] i_mem_data,
output logic o_mem_rd,
output logic o_mem_we,
input logic i_mem_rdy,
output logic [31:0] o_external_addr,
output logic [7:0] o_external_data,
input logic [7:0] i_external_data,
output logic o_external_rd,
output logic o_external_we,
input logic i_external_rdy,
output logic [11:0] o_io_addr,
output logic [7:0] o_io_data,
input logic [7:0] i_io_data,
output logic o_io_rd,
output logic o_io_we,
input logic i_io_rdy
);
enum logic [1:0] {NONE, MEM, EXT, IO} prev_addr, prev_addr_next;
always_ff @(posedge i_clk) begin
if (i_rst) begin
prev_addr <= NONE;
end else begin
prev_addr <= prev_addr_next;
end
end
always_comb begin
prev_addr_next = prev_addr;
o_mem_addr = '0;
o_mem_data = '0;
o_mem_rd = '0;
o_mem_we = '0;
o_external_addr = '0;
o_external_data = '0;
o_external_rd = '0;
o_external_we = '0;
o_io_addr = '0;
o_io_data = '0;
o_io_rd = '0;
o_io_we = '0;
case (prev_addr)
NONE: begin
o_cpu_rdy = '1;
o_cpu_data = '0;
end
MEM: begin
o_cpu_rdy = i_mem_rdy;
o_cpu_data = i_mem_data;
end
EXT: begin
o_cpu_rdy = i_external_rdy;
o_cpu_data = i_external_data;
end
IO: begin
o_cpu_rdy = i_io_rdy;
o_cpu_data = i_io_data;
end
default: begin
o_cpu_rdy = '1;
o_cpu_data = '0;
end
endcase
if (o_cpu_rdy) begin
if (i_cpu_addr < 32'hFFFF) begin
o_mem_addr = i_cpu_addr[15:0];
o_mem_data = i_cpu_data;
o_mem_we = i_cpu_we & o_cpu_rdy;
o_mem_rd = ~i_cpu_we & o_cpu_rdy;
prev_addr_next = MEM;
end else if (i_cpu_addr < 32'hFFFFEFFF) begin
o_external_addr = i_cpu_addr;
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;
end else begin
o_io_addr = 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;
end
end
if (i_rst | ~i_cpu_rdy) begin
prev_addr_next = NONE;
o_mem_rd = 0;
o_mem_we = 0;
o_external_rd = 0;
o_external_we = 0;
o_io_rd = 0;
o_io_we = 0;
end
end
endmodule

View File

@@ -0,0 +1,120 @@
module verilog6502_apb_adapter #(
parameter ADDR_WIDTH = 32
)(
input i_clk,
input i_rst,
input logic [ADDR_WIDTH-1:0] i_addr,
input logic [7:0] i_data,
output logic [7:0] o_data,
input logic i_rd,
input logic i_we,
output logic o_rdy,
taxi_apb_if.mst m_apb
);
localparam APB_ADDR_WIDTH = m_apb.ADDR_W;
enum logic {IDLE, ENABLE} state, state_next;
logic [ADDR_WIDTH-1:0] latched_addr, latched_addr_next;
logic [ADDR_WIDTH-1:0] second_addr, second_addr_next;
logic second_we, second_rd, second_we_next, second_rd_next;
logic [7:0] latched_data, latched_data_next;
logic [7:0] second_data, second_data_next;
logic latched_pwrite, latched_pwrite_next;
always_ff @(posedge i_clk) begin
if (i_rst) begin
state <= IDLE;
latched_addr <= '0;
second_addr <= '0;
second_we <= '0;
second_rd <= '0;
latched_data <= '0;
latched_pwrite <= '0;
second_data <= '0;
end else begin
state <= state_next;
latched_addr <= latched_addr_next;
second_addr <= second_addr_next;
second_we <= second_we_next;
second_rd <= second_rd_next;
latched_data <= latched_data_next;
latched_pwrite <= latched_pwrite_next;
second_data <= second_data_next;
end
end
always_comb begin
case (state)
IDLE: begin
if (i_rd | i_we) begin
m_apb.pprot = '0;
m_apb.paddr = APB_ADDR_WIDTH'({i_addr[ADDR_WIDTH-1:2], 2'b0});
m_apb.psel = '1;
m_apb.pwrite = i_we;
m_apb.pstrb = 4'h1 << i_addr[1:0]; // shift based on lower 2 bits
m_apb.pwdata = {24'b0, i_data} << i_addr[1:0];
o_rdy = '0;
m_apb.penable = '0;
state_next = ENABLE;
latched_addr_next = i_addr;
latched_data_next = i_data;
latched_pwrite_next = i_we;
end else if (second_rd | second_we) begin
m_apb.pprot = '0;
m_apb.paddr = APB_ADDR_WIDTH'({second_addr[ADDR_WIDTH-1:2], 2'b0});
m_apb.psel = '1;
m_apb.pwrite = second_we;
m_apb.pstrb = 4'h1 << second_addr[1:0]; // shift based on lower 2 bits
m_apb.pwdata = {24'b0, second_data} << second_addr[1:0];
o_rdy = '0;
m_apb.penable = '0;
state_next = ENABLE;
latched_addr_next = second_addr;
latched_data_next = second_data;
latched_pwrite_next = second_we;
end else begin
m_apb.pprot = '0;
m_apb.paddr = '0;
m_apb.psel = '0;
m_apb.pwrite = '0;
m_apb.pstrb = '0;
m_apb.pwdata = '0;
o_rdy = '0;
end
end
ENABLE: begin
m_apb.penable = '1;
second_we_next = i_we;
second_rd_next = i_rd;
second_addr_next = i_addr;
second_data_next = i_data;
m_apb.pprot = '0;
m_apb.paddr = APB_ADDR_WIDTH'({latched_addr[ADDR_WIDTH-1:2], 2'b0});
m_apb.psel = '1;
m_apb.pwrite = latched_pwrite;
m_apb.pstrb = 4'h1 << latched_addr[1:0]; // shift based on lower 2 bits
m_apb.pwdata = {24'b0, latched_data} << latched_addr[1:0];
if (m_apb.pready) begin
state_next = IDLE;
o_data = m_apb.prdata[8 * latched_addr[1:0] +: 8];
o_rdy = '1;
end
end
endcase
end
endmodule

View File

@@ -0,0 +1,59 @@
module verilog6502_external_memory (
input i_clk,
input i_rst,
input logic [31:0] i_addr,
input logic [7:0] i_data,
output logic [7:0] o_data,
input logic i_rd,
input logic i_we,
output logic o_rdy,
taxi_axil_if.wr_mst m_axil_wr,
taxi_axil_if.rd_mst m_axil_rd
);
taxi_apb_if internal_apb();
taxi_apb_if addr_shift_apb();
verilog6502_apb_adapter u_internal_apb_adapter (
.i_clk (i_clk),
.i_rst (i_rst),
.i_addr (i_addr),
.i_data (i_data),
.o_data (o_data),
.i_rd (i_rd),
.i_we (i_we),
.o_rdy (o_rdy),
.m_apb (internal_apb)
);
assign addr_shift_apb.paddr = internal_apb.paddr;
assign addr_shift_apb.pprot = internal_apb.pprot;
assign addr_shift_apb.psel = internal_apb.psel;
assign addr_shift_apb.penable = internal_apb.penable;
assign addr_shift_apb.pwrite = internal_apb.pwrite;
assign addr_shift_apb.pwdata = internal_apb.pwdata;
assign addr_shift_apb.pstrb = internal_apb.pstrb;
assign internal_apb.pready = addr_shift_apb.pready;
assign internal_apb.prdata = addr_shift_apb.prdata;
assign internal_apb.pslverr = addr_shift_apb.pslverr;
assign addr_shift_apb.pauser = '0;
assign addr_shift_apb.pwuser = '0;
assign internal_apb.pruser = '0;
assign internal_apb.pbuser = '0;
taxi_apb_axil_adapter u_apb_axil_adapter (
.clk (i_clk),
.rst (i_rst),
.s_apb (addr_shift_apb),
.m_axil_wr (m_axil_wr),
.m_axil_rd (m_axil_rd)
);
endmodule

View File

@@ -0,0 +1,226 @@
module verilog6502_internal_memory(
input i_clk,
input i_rst,
taxi_axi_if.rd_slv s_axi_rd,
taxi_axi_if.wr_slv s_axi_wr,
input logic [15:0] i_addr,
input logic [7:0] i_data,
output logic [7:0] o_data,
input logic i_rd,
input logic i_we,
output logic o_rdy
);
localparam ID_W = 8;
localparam ADDR_W = 32;
localparam AUSER_W = 1;
localparam RUSER_W = 1;
localparam WUSER_W = 1;
localparam DATA_W = 32;
localparam STRB_W = 4;
logic [ID_W-1:0] ram_cmd_id;
logic [ADDR_W-1:0] ram_cmd_addr;
logic [DATA_W-1:0] ram_cmd_wr_data;
logic [STRB_W-1:0] ram_cmd_wr_strb;
logic ram_cmd_wr_en;
logic ram_cmd_rd_en;
logic ram_cmd_last;
logic ram_cmd_ready;
logic [DATA_W-1:0] ram_rd_resp_data;
logic ram_rd_resp_last;
logic ram_rd_resp_valid;
logic ram_rd_resp_ready;
taxi_axi_ram_if_rdwr #(
.DATA_W(DATA_W),
.ADDR_W(ADDR_W),
.STRB_W(STRB_W),
.ID_W(ID_W),
.AUSER_W(AUSER_W),
.WUSER_W(WUSER_W),
.RUSER_W(RUSER_W)
) axi_ram_if_rdwr (
.clk (i_clk),
.rst (i_rst),
.s_axi_wr (s_axi_wr),
.s_axi_rd (s_axi_rd),
.ram_cmd_id (ram_cmd_id),
.ram_cmd_addr (ram_cmd_addr),
.ram_cmd_lock (),
.ram_cmd_cache (),
.ram_cmd_prot (),
.ram_cmd_qos (),
.ram_cmd_region (),
.ram_cmd_auser (),
.ram_cmd_wr_data (ram_cmd_wr_data),
.ram_cmd_wr_strb (ram_cmd_wr_strb),
.ram_cmd_wr_user (),
.ram_cmd_wr_en (ram_cmd_wr_en),
.ram_cmd_rd_en (ram_cmd_rd_en),
.ram_cmd_last (ram_cmd_last),
.ram_cmd_ready (ram_cmd_ready),
.ram_rd_resp_id (),
.ram_rd_resp_data (ram_rd_resp_data),
.ram_rd_resp_last (ram_rd_resp_last),
.ram_rd_resp_user (),
.ram_rd_resp_valid (ram_rd_resp_valid),
.ram_rd_resp_ready (ram_rd_resp_ready)
);
logic [7:0] mem [4][16*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;
logic ram_we;
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;
if (ram_we) begin
for (int i = 0; i < 4; i++) begin
if (ram_wstrb[i]) begin
mem[i][ram_addr[15:2]] <= ram_wdata[8*i +: 8];
end
end
end
if (ram_re) begin
for (int i = 0; i < 4; i++) begin
ram_rdata[8*i +: 8] <= mem[i][ram_addr[15:2]];
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
always_comb begin
sel_next = sel;
ram_cmd_ready = '0;
ram_addr = '0;
ram_we = '0;
ram_wdata = '0;
ram_we = '0;
ram_re = '0;
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 | 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
ram_cmd_ready = '1;
if (ram_cmd_wr_en) begin
ram_addr = ram_cmd_addr[15:0];
ram_wdata = ram_cmd_wr_data;
ram_wstrb = ram_cmd_wr_strb;
ram_we = '1;
end else if (ram_cmd_rd_en) begin
ram_addr = ram_cmd_addr[15:0];
ram_re = '1;
end else begin
sel_next = CPU;
end
ram_rd_resp_valid = ram_rdata_valid;
ram_rd_resp_data = ram_rdata;
end
endcase
end
endmodule

View File

@@ -0,0 +1,205 @@
// Wrapper around verilog-6502
// memory map:
// 0x00000000-0x000000FF Zero Page (Hard coded)
// 0x00000100-0x000001FF Stack (Hard coded)
// 0x00000200-0x0000FFFF Internal Memory
// 0x00010000-0xFFFFEFFF External AXI
// 0xFFFFF000-0xFFFFFFFF Processor IO
module verilog6502_wrapper(
input clk,
input rst,
taxi_apb_if.slv s_apb,
taxi_axil_if.wr_mst m_axil_wr,
taxi_axil_if.rd_mst m_axil_rd,
taxi_axi_if.rd_slv s_axi_rd,
taxi_axi_if.wr_slv s_axi_wr,
output logic o_irq_ext,
input logic i_irq_ext,
input logic i_nmi_ext
);
taxi_apb_if internal_apb();
taxi_apb_if s_apb_mux[2]();
taxi_apb_if m_apb_mux[1]();
taxi_apb_if m_apb();
taxi_apb_tie u_external_apb_tie(
.s_apb(s_apb),
.m_apb(s_apb_mux[0])
);
taxi_apb_tie u_internal_apb_tie(
.s_apb(internal_apb),
.m_apb(s_apb_mux[1])
);
taxi_apb_tie u_master_apb_tie(
.s_apb(m_apb_mux[0]),
.m_apb(m_apb)
);
taxi_apb_interconnect #(
.S_CNT(2),
.M_CNT(1),
.ADDR_W(32)
) u_apb_interconnect (
.clk (clk),
.rst (rst),
.s_apb (s_apb_mux),
.m_apb (m_apb_mux)
);
logic cpu_clk;
logic cpu_reset;
logic [31:0] cpu_addr;
logic [7:0] cpu_data_in;
logic [7:0] cpu_data_out;
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_irq = i_irq_ext;
assign cpu_nmi = i_nmi_ext;
logic [15:0] mem_addr;
logic [7:0] mem_data_in;
logic [7:0] mem_data_out;
logic mem_rd;
logic mem_we;
logic mem_rdy;
logic [31:0] ext_addr;
logic [7:0] ext_data_in;
logic [7:0] ext_data_out;
logic ext_rd;
logic ext_we;
logic ext_rdy;
logic [11:0] io_addr;
logic [7:0] io_data_in;
logic [7:0] io_data_out;
logic io_rd;
logic io_we;
logic io_rdy;
verilog6502_io_regs_pkg::verilog6502_io_regs__out_t hwif_out;
cpu_65c02 u_cpu_6502(
.clk (cpu_clk),
.reset (cpu_reset),
.AB (cpu_addr),
.DI (cpu_data_in),
.DO (cpu_data_out),
.WE (cpu_we),
.IRQ (cpu_irq),
.NMI (cpu_nmi),
.RDY (cpu_rdy),
.RDY_O (cpu_rdy_o),
.SYNC (cpu_sync)
);
verilog6502_addr_decoder u_addr_decoder(
.i_clk (cpu_clk),
.i_rst (cpu_reset),
.i_cpu_addr (cpu_addr),
.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),
.o_mem_data (mem_data_in),
.i_mem_data (mem_data_out),
.o_mem_rd (mem_rd),
.o_mem_we (mem_we),
.i_mem_rdy (mem_rdy),
.o_external_addr (ext_addr),
.o_external_data (ext_data_in),
.i_external_data (ext_data_out),
.o_external_rd (ext_rd),
.o_external_we (ext_we),
.i_external_rdy (ext_rdy),
.o_io_addr (io_addr),
.o_io_data (io_data_in),
.i_io_data (io_data_out),
.o_io_rd (io_rd),
.o_io_we (io_we),
.i_io_rdy (io_rdy)
);
verilog6502_internal_memory u_internal_memory(
.i_clk (cpu_clk),
.i_rst (rst),
.s_axi_rd (s_axi_rd),
.s_axi_wr (s_axi_wr),
.i_addr (mem_addr),
.i_data (mem_data_in),
.o_data (mem_data_out),
.i_rd (mem_rd),
.i_we (mem_we),
.o_rdy (mem_rdy)
);
verilog6502_external_memory u_external_memory (
.i_clk (clk),
.i_rst (rst),
.i_addr (ext_addr),
.i_data (ext_data_in),
.o_data (ext_data_out),
.i_rd (ext_rd),
.i_we (ext_we),
.o_rdy (ext_rdy),
.m_axil_rd (m_axil_rd),
.m_axil_wr (m_axil_wr)
);
verilog6502_apb_adapter #(
.ADDR_WIDTH(12)
) u_io_apb_adapter(
.i_clk (cpu_clk),
.i_rst (rst),
.i_addr (io_addr),
.i_data (io_data_in),
.o_data (io_data_out),
.i_rd (io_rd),
.i_we (io_we),
.o_rdy (io_rdy),
.m_apb (internal_apb)
);
verilog6502_io_regs u_io_regs (
.clk (cpu_clk),
.rst (rst),
.s_apb (m_apb),
.hwif_out (hwif_out)
);
endmodule