blob: 154f62978aa173735d529f36f68802b8ec6d2e7b [file] [log] [blame]
module apb_fll_if
#(
parameter APB_ADDR_WIDTH = 12
)
(
HCLK,
HRESETn,
PADDR,
PWDATA,
PWRITE,
PSEL,
PENABLE,
PRDATA,
PREADY,
PSLVERR,
fll1_req,
fll1_wrn,
fll1_add,
fll1_data,
fll1_ack,
fll1_r_data,
fll1_lock,
fll2_req,
fll2_wrn,
fll2_add,
fll2_data,
fll2_ack,
fll2_r_data,
fll2_lock
);
//parameter APB_ADDR_WIDTH = 12;
input wire HCLK;
input wire HRESETn;
input wire [APB_ADDR_WIDTH - 1:0] PADDR;
input wire [31:0] PWDATA;
input wire PWRITE;
input wire PSEL;
input wire PENABLE;
output wire [31:0] PRDATA;
output wire PREADY;
output wire PSLVERR;
output reg fll1_req;
output wire fll1_wrn;
output wire [1:0] fll1_add;
output wire [31:0] fll1_data;
input wire fll1_ack;
input wire [31:0] fll1_r_data;
input wire fll1_lock;
output reg fll2_req;
output wire fll2_wrn;
output wire [1:0] fll2_add;
output wire [31:0] fll2_data;
input wire fll2_ack;
input wire [31:0] fll2_r_data;
input wire fll2_lock;
reg fll1_rd_access;
reg fll1_wr_access;
reg fll2_rd_access;
reg fll2_wr_access;
reg read_ready;
reg write_ready;
reg [31:0] read_data;
reg rvalid;
reg fll1_ack_sync0;
reg fll1_ack_sync;
reg fll2_ack_sync0;
reg fll2_ack_sync;
reg fll1_lock_sync0;
reg fll1_lock_sync;
reg fll2_lock_sync0;
reg fll2_lock_sync;
reg fll1_valid;
reg fll2_valid;
reg [2:0] state;
reg [2:0] state_next;
always @(posedge HCLK or negedge HRESETn)
if (!HRESETn) begin
fll1_ack_sync0 <= 1'b0;
fll1_ack_sync <= 1'b0;
fll2_ack_sync0 <= 1'b0;
fll2_ack_sync <= 1'b0;
fll1_lock_sync0 <= 1'b0;
fll1_lock_sync <= 1'b0;
fll2_lock_sync0 <= 1'b0;
fll2_lock_sync <= 1'b0;
state <= 3'd0;
end
else begin
fll1_ack_sync0 <= fll1_ack;
fll1_ack_sync <= fll1_ack_sync0;
fll2_ack_sync0 <= fll2_ack;
fll2_ack_sync <= fll2_ack_sync0;
fll1_lock_sync0 <= fll1_lock;
fll1_lock_sync <= fll1_lock_sync0;
fll2_lock_sync0 <= fll2_lock;
fll2_lock_sync <= fll2_lock_sync0;
state <= state_next;
end
always @(*) begin
state_next = 3'd0;
rvalid = 1'b0;
fll1_req = 1'b0;
fll2_req = 1'b0;
fll1_valid = 1'b0;
fll2_valid = 1'b0;
case (state)
3'd0:
if (fll2_rd_access || fll2_wr_access) begin
fll2_valid = 1'b1;
state_next = 3'd3;
end
else if (fll1_rd_access || fll1_wr_access) begin
fll1_valid = 1'b1;
state_next = 3'd1;
end
3'd1:
if (fll1_ack_sync) begin
fll1_req = 1'b0;
fll1_valid = 1'b0;
state_next = 3'd2;
rvalid = 1'b1;
end
else begin
fll1_req = 1'b1;
fll1_valid = 1'b1;
state_next = 3'd1;
end
3'd2:
if (!fll1_ack_sync)
state_next = 3'd0;
else
state_next = 3'd2;
3'd3:
if (fll2_ack_sync) begin
fll2_req = 1'b0;
fll2_valid = 1'b0;
state_next = 3'd4;
rvalid = 1'b1;
end
else begin
fll2_req = 1'b1;
fll2_valid = 1'b1;
state_next = 3'd3;
end
3'd4:
if (!fll2_ack_sync)
state_next = 3'd0;
else
state_next = 3'd4;
endcase
end
always @(*) begin
fll1_wr_access = 1'b0;
fll2_wr_access = 1'b0;
write_ready = 1'b0;
if ((PSEL && PENABLE) && PWRITE)
case (PADDR[5:2])
4'b0000, 4'b0001, 4'b0010, 4'b0011: begin
fll1_wr_access = 1'b1;
write_ready = rvalid;
end
4'b0100, 4'b0101, 4'b0110, 4'b0111: begin
fll2_wr_access = 1'b1;
write_ready = rvalid;
end
default: write_ready = 1'b1;
endcase
end
always @(*) begin
fll1_rd_access = 1'b0;
fll2_rd_access = 1'b0;
read_ready = 1'b0;
read_data = 1'sb0;
if ((PSEL && PENABLE) && ~PWRITE)
case (PADDR[5:2])
4'b0000, 4'b0001, 4'b0010, 4'b0011: begin
fll1_rd_access = 1'b1;
read_data = fll1_r_data;
read_ready = rvalid;
end
4'b0100, 4'b0101, 4'b0110, 4'b0111: begin
fll2_rd_access = 1'b1;
read_data = fll2_r_data;
read_ready = rvalid;
end
4'b1000: begin
read_data[1:0] = {fll2_lock_sync, fll1_lock_sync};
read_ready = 1'b1;
end
default: read_ready = 1'b1;
endcase
end
assign fll1_wrn = (fll1_valid ? ~PWRITE : 1'b0);
assign fll1_add = (fll1_valid ? PADDR[3:2] : {2 {1'sb0}});
assign fll1_data = (fll1_valid ? PWDATA : {32 {1'sb0}});
assign fll2_wrn = (fll2_valid ? ~PWRITE : 1'b0);
assign fll2_add = (fll2_valid ? PADDR[3:2] : {2 {1'sb0}});
assign fll2_data = (fll2_valid ? PWDATA : {32 {1'sb0}});
assign PREADY = (PWRITE ? write_ready : read_ready);
assign PRDATA = read_data;
assign PSLVERR = 1'b0;
endmodule