116 lines
3.6 KiB
Systemverilog
116 lines
3.6 KiB
Systemverilog
module verilog6502_apb_adapter(
|
|
input i_clk,
|
|
input i_rst,
|
|
|
|
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,
|
|
|
|
taxi_apb_if.mst m_apb
|
|
);
|
|
|
|
enum logic {IDLE, ENABLE} state, state_next;
|
|
|
|
logic [15:0] latched_addr, latched_addr_next;
|
|
logic [15: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 = {16'b0, i_addr} & 32'hfffc; // 32 bit address
|
|
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 = {16'b0, second_addr} & 32'hfffc; // 32 bit address
|
|
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 = {16'b0, latched_addr} & 32'hfffc; // 32 bit address
|
|
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 |