blob: dd71d6a0911e3f11cdc62d294638f9a35355f416 [file] [log] [blame]
module AXI_2_APB_32
#(
parameter AXI4_ADDRESS_WIDTH = 32,
parameter AXI4_RDATA_WIDTH = 32,
parameter AXI4_WDATA_WIDTH = 32,
parameter AXI4_ID_WIDTH = 16,
parameter AXI4_USER_WIDTH = 10,
parameter AXI_NUMBYTES = AXI4_WDATA_WIDTH/8,
parameter BUFF_DEPTH_SLAVE = 4,
parameter APB_NUM_SLAVES = 8,
parameter APB_ADDR_WIDTH = 12 //APB slaves are 4KB by default
)
(
ACLK,
ARESETn,
test_en_i,
AWID_i,
AWADDR_i,
AWLEN_i,
AWSIZE_i,
AWBURST_i,
AWLOCK_i,
AWCACHE_i,
AWPROT_i,
AWREGION_i,
AWUSER_i,
AWQOS_i,
AWVALID_i,
AWREADY_o,
WDATA_i,
WSTRB_i,
WLAST_i,
WUSER_i,
WVALID_i,
WREADY_o,
BID_o,
BRESP_o,
BVALID_o,
BUSER_o,
BREADY_i,
ARID_i,
ARADDR_i,
ARLEN_i,
ARSIZE_i,
ARBURST_i,
ARLOCK_i,
ARCACHE_i,
ARPROT_i,
ARREGION_i,
ARUSER_i,
ARQOS_i,
ARVALID_i,
ARREADY_o,
RID_o,
RDATA_o,
RRESP_o,
RLAST_o,
RUSER_o,
RVALID_o,
RREADY_i,
PENABLE,
PWRITE,
PADDR,
PSEL,
PWDATA,
PRDATA,
PREADY,
PSLVERR
);
//parameter AXI4_ADDRESS_WIDTH = 32;
//parameter AXI4_RDATA_WIDTH = 32;
//parameter AXI4_WDATA_WIDTH = 32;
//parameter AXI4_ID_WIDTH = 16;
//parameter AXI4_USER_WIDTH = 10;
//parameter AXI_NUMBYTES = AXI4_WDATA_WIDTH / 8;
//parameter BUFF_DEPTH_SLAVE = 4;
//parameter APB_NUM_SLAVES = 8;
//parameter APB_ADDR_WIDTH = 12;
input wire ACLK;
input wire ARESETn;
input wire test_en_i;
input wire [AXI4_ID_WIDTH - 1:0] AWID_i;
input wire [AXI4_ADDRESS_WIDTH - 1:0] AWADDR_i;
input wire [7:0] AWLEN_i;
input wire [2:0] AWSIZE_i;
input wire [1:0] AWBURST_i;
input wire AWLOCK_i;
input wire [3:0] AWCACHE_i;
input wire [2:0] AWPROT_i;
input wire [3:0] AWREGION_i;
input wire [AXI4_USER_WIDTH - 1:0] AWUSER_i;
input wire [3:0] AWQOS_i;
input wire AWVALID_i;
output wire AWREADY_o;
input wire [AXI4_WDATA_WIDTH - 1:0] WDATA_i;
input wire [AXI_NUMBYTES - 1:0] WSTRB_i;
input wire WLAST_i;
input wire [AXI4_USER_WIDTH - 1:0] WUSER_i;
input wire WVALID_i;
output wire WREADY_o;
output wire [AXI4_ID_WIDTH - 1:0] BID_o;
output wire [1:0] BRESP_o;
output wire BVALID_o;
output wire [AXI4_USER_WIDTH - 1:0] BUSER_o;
input wire BREADY_i;
input wire [AXI4_ID_WIDTH - 1:0] ARID_i;
input wire [AXI4_ADDRESS_WIDTH - 1:0] ARADDR_i;
input wire [7:0] ARLEN_i;
input wire [2:0] ARSIZE_i;
input wire [1:0] ARBURST_i;
input wire ARLOCK_i;
input wire [3:0] ARCACHE_i;
input wire [2:0] ARPROT_i;
input wire [3:0] ARREGION_i;
input wire [AXI4_USER_WIDTH - 1:0] ARUSER_i;
input wire [3:0] ARQOS_i;
input wire ARVALID_i;
output wire ARREADY_o;
output wire [AXI4_ID_WIDTH - 1:0] RID_o;
output wire [AXI4_RDATA_WIDTH - 1:0] RDATA_o;
output wire [1:0] RRESP_o;
output wire RLAST_o;
output wire [AXI4_USER_WIDTH - 1:0] RUSER_o;
output wire RVALID_o;
input wire RREADY_i;
output wire PENABLE;
output wire PWRITE;
output wire [APB_ADDR_WIDTH - 1:0] PADDR;
output reg [APB_NUM_SLAVES - 1:0] PSEL;
output wire [31:0] PWDATA;
input wire [(APB_NUM_SLAVES * 32) - 1:0] PRDATA;
input wire [APB_NUM_SLAVES - 1:0] PREADY;
input wire [APB_NUM_SLAVES - 1:0] PSLVERR;
wire [AXI4_ID_WIDTH - 1:0] AWID;
wire [AXI4_ADDRESS_WIDTH - 1:0] AWADDR;
wire [7:0] AWLEN;
wire [2:0] AWSIZE;
wire [1:0] AWBURST;
wire AWLOCK;
wire [3:0] AWCACHE;
wire [2:0] AWPROT;
wire [3:0] AWREGION;
wire [AXI4_USER_WIDTH - 1:0] AWUSER;
wire [3:0] AWQOS;
wire AWVALID;
reg AWREADY;
wire [AXI4_WDATA_WIDTH - 1:0] WDATA;
wire [AXI_NUMBYTES - 1:0] WSTRB;
wire WLAST;
wire [AXI4_USER_WIDTH - 1:0] WUSER;
wire WVALID;
reg WREADY;
reg [AXI4_ID_WIDTH - 1:0] BID;
reg [1:0] BRESP;
reg BVALID;
reg [AXI4_USER_WIDTH - 1:0] BUSER;
wire BREADY;
wire [AXI4_ID_WIDTH - 1:0] ARID;
wire [AXI4_ADDRESS_WIDTH - 1:0] ARADDR;
wire [7:0] ARLEN;
wire [2:0] ARSIZE;
wire [1:0] ARBURST;
wire ARLOCK;
wire [3:0] ARCACHE;
wire [2:0] ARPROT;
wire [3:0] ARREGION;
wire [AXI4_USER_WIDTH - 1:0] ARUSER;
wire [3:0] ARQOS;
wire ARVALID;
reg ARREADY;
reg [AXI4_ID_WIDTH - 1:0] RID;
reg [AXI4_RDATA_WIDTH - 1:0] RDATA;
reg [1:0] RRESP;
reg RLAST;
reg [AXI4_USER_WIDTH - 1:0] RUSER;
reg RVALID;
wire RREADY;
reg [2:0] CS;
reg [2:0] NS;
reg [($clog2(APB_NUM_SLAVES) + APB_ADDR_WIDTH) - 1:0] address;
reg sample_RDATA;
reg [31:0] RDATA_Q;
reg read_req;
reg write_req;
wire [$clog2(APB_NUM_SLAVES) - 1:0] TARGET_SLAVE;
assign PENABLE = write_req | read_req;
assign PWRITE = write_req;
assign PADDR = address[APB_ADDR_WIDTH - 1:0];
assign PWDATA = WDATA;
assign TARGET_SLAVE = address[(APB_ADDR_WIDTH + $clog2(APB_NUM_SLAVES)) - 1:APB_ADDR_WIDTH];
always @(*) begin
PSEL = 1'sb0;
PSEL[TARGET_SLAVE] = 1'b1;
end
axi_aw_buffer #(
.ID_WIDTH(AXI4_ID_WIDTH),
.ADDR_WIDTH(AXI4_ADDRESS_WIDTH),
.USER_WIDTH(AXI4_USER_WIDTH),
.BUFFER_DEPTH(BUFF_DEPTH_SLAVE)
) Slave_aw_buffer(
.clk_i(ACLK),
.rst_ni(ARESETn),
.test_en_i(test_en_i),
.slave_valid_i(AWVALID_i),
.slave_addr_i(AWADDR_i),
.slave_prot_i(AWPROT_i),
.slave_region_i(AWREGION_i),
.slave_len_i(AWLEN_i),
.slave_size_i(AWSIZE_i),
.slave_burst_i(AWBURST_i),
.slave_lock_i(AWLOCK_i),
.slave_cache_i(AWCACHE_i),
.slave_qos_i(AWQOS_i),
.slave_id_i(AWID_i),
.slave_user_i(AWUSER_i),
.slave_ready_o(AWREADY_o),
.master_valid_o(AWVALID),
.master_addr_o(AWADDR),
.master_prot_o(AWPROT),
.master_region_o(AWREGION),
.master_len_o(AWLEN),
.master_size_o(AWSIZE),
.master_burst_o(AWBURST),
.master_lock_o(AWLOCK),
.master_cache_o(AWCACHE),
.master_qos_o(AWQOS),
.master_id_o(AWID),
.master_user_o(AWUSER),
.master_ready_i(AWREADY)
);
axi_ar_buffer #(
.ID_WIDTH(AXI4_ID_WIDTH),
.ADDR_WIDTH(AXI4_ADDRESS_WIDTH),
.USER_WIDTH(AXI4_USER_WIDTH),
.BUFFER_DEPTH(BUFF_DEPTH_SLAVE)
) Slave_ar_buffer(
.clk_i(ACLK),
.rst_ni(ARESETn),
.test_en_i(test_en_i),
.slave_valid_i(ARVALID_i),
.slave_addr_i(ARADDR_i),
.slave_prot_i(ARPROT_i),
.slave_region_i(ARREGION_i),
.slave_len_i(ARLEN_i),
.slave_size_i(ARSIZE_i),
.slave_burst_i(ARBURST_i),
.slave_lock_i(ARLOCK_i),
.slave_cache_i(ARCACHE_i),
.slave_qos_i(ARQOS_i),
.slave_id_i(ARID_i),
.slave_user_i(ARUSER_i),
.slave_ready_o(ARREADY_o),
.master_valid_o(ARVALID),
.master_addr_o(ARADDR),
.master_prot_o(ARPROT),
.master_region_o(ARREGION),
.master_len_o(ARLEN),
.master_size_o(ARSIZE),
.master_burst_o(ARBURST),
.master_lock_o(ARLOCK),
.master_cache_o(ARCACHE),
.master_qos_o(ARQOS),
.master_id_o(ARID),
.master_user_o(ARUSER),
.master_ready_i(ARREADY)
);
axi_w_buffer #(
.DATA_WIDTH(AXI4_WDATA_WIDTH),
.USER_WIDTH(AXI4_USER_WIDTH),
.BUFFER_DEPTH(BUFF_DEPTH_SLAVE)
) Slave_w_buffer(
.clk_i(ACLK),
.rst_ni(ARESETn),
.test_en_i(test_en_i),
.slave_valid_i(WVALID_i),
.slave_data_i(WDATA_i),
.slave_strb_i(WSTRB_i),
.slave_user_i(WUSER_i),
.slave_last_i(WLAST_i),
.slave_ready_o(WREADY_o),
.master_valid_o(WVALID),
.master_data_o(WDATA),
.master_strb_o(WSTRB),
.master_user_o(WUSER),
.master_last_o(WLAST),
.master_ready_i(WREADY)
);
axi_r_buffer #(
.ID_WIDTH(AXI4_ID_WIDTH),
.DATA_WIDTH(AXI4_RDATA_WIDTH),
.USER_WIDTH(AXI4_USER_WIDTH),
.BUFFER_DEPTH(BUFF_DEPTH_SLAVE)
) Slave_r_buffer(
.clk_i(ACLK),
.rst_ni(ARESETn),
.test_en_i(test_en_i),
.slave_valid_i(RVALID),
.slave_data_i(RDATA),
.slave_resp_i(RRESP),
.slave_user_i(RUSER),
.slave_id_i(RID),
.slave_last_i(RLAST),
.slave_ready_o(RREADY),
.master_valid_o(RVALID_o),
.master_data_o(RDATA_o),
.master_resp_o(RRESP_o),
.master_user_o(RUSER_o),
.master_id_o(RID_o),
.master_last_o(RLAST_o),
.master_ready_i(RREADY_i)
);
axi_b_buffer #(
.ID_WIDTH(AXI4_ID_WIDTH),
.USER_WIDTH(AXI4_USER_WIDTH),
.BUFFER_DEPTH(BUFF_DEPTH_SLAVE)
) Slave_b_buffer(
.clk_i(ACLK),
.rst_ni(ARESETn),
.test_en_i(test_en_i),
.slave_valid_i(BVALID),
.slave_resp_i(BRESP),
.slave_id_i(BID),
.slave_user_i(BUSER),
.slave_ready_o(BREADY),
.master_valid_o(BVALID_o),
.master_resp_o(BRESP_o),
.master_id_o(BID_o),
.master_user_o(BUSER_o),
.master_ready_i(BREADY_i)
);
always @(posedge ACLK or negedge ARESETn)
if (ARESETn == 1'b0) begin
CS <= 3'd0;
RDATA_Q <= 1'sb0;
end
else begin
CS <= NS;
if (sample_RDATA)
RDATA_Q <= PRDATA[TARGET_SLAVE * 32+:32];
end
always @(*) begin
read_req = 1'b0;
write_req = 1'b0;
address = 1'sbx;
sample_RDATA = 1'b0;
ARREADY = 1'b0;
AWREADY = 1'b0;
WREADY = 1'b0;
BVALID = 1'b0;
BRESP = 2'b00;
BID = AWID;
BUSER = AWUSER;
RVALID = 1'b0;
RLAST = 1'b0;
RID = ARID;
RUSER = ARUSER;
RRESP = 2'b00;
RDATA = RDATA_Q;
case (CS)
3'd3: begin
read_req = 1'b1;
address = ARADDR[($clog2(APB_NUM_SLAVES) + APB_ADDR_WIDTH) - 1:0];
sample_RDATA = PREADY[TARGET_SLAVE];
if (PREADY[TARGET_SLAVE] == 1'b1)
NS = 3'd1;
else
NS = 3'd3;
end
3'd2: begin
write_req = 1'b1;
address = AWADDR[($clog2(APB_NUM_SLAVES) + APB_ADDR_WIDTH) - 1:0];
if (PREADY[TARGET_SLAVE] == 1'b1)
NS = 3'd4;
else
NS = 3'd2;
end
3'd0:
if (ARVALID == 1'b1) begin
read_req = 1'b1;
address = ARADDR[($clog2(APB_NUM_SLAVES) + APB_ADDR_WIDTH) - 1:0];
sample_RDATA = PREADY[TARGET_SLAVE];
if (PREADY[TARGET_SLAVE] == 1'b1)
NS = 3'd1;
else
NS = 3'd3;
end
else if (AWVALID) begin
address = AWADDR[($clog2(APB_NUM_SLAVES) + APB_ADDR_WIDTH) - 1:0];
if (WVALID) begin
write_req = 1'b1;
if (PREADY[TARGET_SLAVE] == 1'b1)
NS = 3'd4;
else
NS = 3'd2;
end
else begin
write_req = 1'b0;
address = 1'sb0;
NS = 3'd0;
end
end
else begin
NS = 3'd0;
address = 1'sb0;
end
3'd4: begin
BVALID = 1'b1;
address = 1'sb0;
if (BREADY) begin
NS = 3'd0;
AWREADY = 1'b1;
WREADY = 1'b1;
end
else
NS = 3'd4;
end
3'd1: begin
RVALID = 1'b1;
RLAST = 1;
address = 1'sb0;
if (RREADY) begin
NS = 3'd0;
ARREADY = 1'b1;
end
else
NS = 3'd1;
end
default: NS = 3'd0;
endcase
end
endmodule