`define IDLE 2'b00
`define SETUP 2'b01
`define ENABLE 2'b10
module APB_Bridge(
input wire PRESETn,
input wire PCLK,
// AHB
input wire HEN,
input wire HRWN,
input wire [1:0] HBYTEN,
input wire [31:0] HADDR,
input wire [31:0] HWDATA,
output reg [31:0] HRDATA,
output reg HREADY,
output reg HACK,
output reg HKGrant,
output reg HdERROR,
// APB_Slave
output reg PSEL0,
output reg PSEL1,
output reg PSEL2,
output reg PSEL3,
output reg PENABLE,
output reg PWRITE,
output reg [31:0] PADDR,
output reg [31:0] PWDATA,
input wire [31:0] PRDATA,
output reg [3:0] PMASTER
);
// Read DATA
always @(*) HRDATA = PRDATA;
// Slave select
assign PSEL0i = (HADDR[31:8] == 24'h0000_00);
assign PSEL1i = (HADDR[31:8] == 24'h0000_01);
assign PSEL2i = (HADDR[31:8] == 24'h0000_02);
assign PSEL3i = (HADDR[31:8] == 24'h0000_03);
always @(*) PMASTER = HADDR[11:8];
// Bridge Main FSM
reg [1:0] APB_FSM;
always @(posedge PCLK or negedge PRESETn)
begin
if(!PRESETn)
begin
// master
HREADY <= 1'b1;
HACK <= 1'b0;
HdERROR <= 1'b0;
HKGrant <= 1'b0;
// slave
APB_FSM <= `IDLE;
PSEL0 <= 1'b0;
PSEL1 <= 1'b0;
PSEL2 <= 1'b0;
PSEL3 <= 1'b0;
PENABLE <= 1'b0;
PWRITE <= 1'b0;
PADDR <= 32'h0000;
PWDATA <= 32'h0000;
end
else
begin
case(APB_FSM)
`IDLE:
begin
if(HEN)
begin
APB_FSM <= `SETUP;
// master
HREADY <= 1'b0;
HACK <= 1'b0;
// slave
PSEL0 <= PSEL0i;
PSEL1 <= PSEL1i;
PSEL2 <= PSEL2i;
PSEL3 <= PSEL3i;
PWRITE <= ~HRWN; //////////////////////
PADDR <= HADDR;
PWDATA <= HWDATA;
end
end
`SETUP:
begin
APB_FSM <= `ENABLE;
// master
HREADY <= 1'b0;
HACK <= 1'b1;
HKGrant <= 1'b1;
// slave
PENABLE <= 1'b1;
end
`ENABLE:
begin
APB_FSM <= `IDLE;
// master
HREADY <= 1'b1;
HACK <= 1'b0;
HKGrant <= 1'b0;
HdERROR <= 1'b0;
// slave
PSEL0 <= 1'b0;
PSEL1 <= 1'b0;
PSEL2 <= 1'b0;
PSEL3 <= 1'b0;
PENABLE <= 1'b0;
end
default: APB_FSM <= `IDLE;
endcase
end
end
endmodule