124 lines
3.1 KiB
Systemverilog
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 |