Files
fpga6502/src/verilog6502_addr_decoder.sv
2026-04-18 16:18:57 -07:00

124 lines
3.1 KiB
Systemverilog

module verilog6502_addr_decoder(
input i_clk,
input i_rst,
input logic [15: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 [15: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 [15: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 < 16'hE000) begin
o_mem_addr = i_cpu_addr;
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 < 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;
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;
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