blob: cf518d5603c878e480e5f7e558137aa639686750 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Filename: axim2wbsp.v
//
// Project: WB2AXIPSP: bus bridges and other odds and ends
//
// Purpose: So ... this converter works in the other direction from
// wbm2axisp. This converter takes AXI commands, and organizes
// them into pipelined wishbone commands.
//
// This particular core treats AXI as two separate buses: one for writes,
// and the other for reads. This particular core combines the two channels
// into one. The designer should be aware that the two AXI buses turned
// Wishbone buses can be kept separate as separate inputs to a WB crosssbar
// for better performance in some circumstances.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016-2020, Gisselquist Technology, LLC
//
// This file is part of the WB2AXIP project.
//
// The WB2AXIP project contains free software and gateware, licensed under the
// Apache License, Version 2.0 (the "License"). You may not use this project,
// or this file, except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
////////////////////////////////////////////////////////////////////////////////
//
//
`default_nettype none
//
module axim2wbsp #(
parameter C_AXI_ID_WIDTH = 2, // The AXI id width used for R&W
// This is an int between 1-16
parameter C_AXI_DATA_WIDTH = 32,// Width of the AXI R&W data
parameter C_AXI_ADDR_WIDTH = 28, // AXI Address width
localparam AXI_LSBS = $clog2(C_AXI_DATA_WIDTH)-3,
localparam DW = C_AXI_DATA_WIDTH,
localparam AW = C_AXI_ADDR_WIDTH - AXI_LSBS,
parameter LGFIFO = 5,
parameter [0:0] OPT_READONLY = 1'b0,
parameter [0:0] OPT_WRITEONLY = 1'b0
) (
//
input wire S_AXI_ACLK, // System clock
input wire S_AXI_ARESETN,
// AXI write address channel signals
input wire S_AXI_AWVALID, // Write address valid
output wire S_AXI_AWREADY, // Slave is ready to rcv
input wire [C_AXI_ID_WIDTH-1:0] S_AXI_AWID, // Write ID
input wire [C_AXI_ADDR_WIDTH-1:0] S_AXI_AWADDR, // Write address
input wire [7:0] S_AXI_AWLEN, // Write Burst Length
input wire [2:0] S_AXI_AWSIZE, // Write Burst size
input wire [1:0] S_AXI_AWBURST, // Write Burst type
input wire [0:0] S_AXI_AWLOCK, // Write lock type
input wire [3:0] S_AXI_AWCACHE, // Write Cache type
input wire [2:0] S_AXI_AWPROT, // Write Protection type
input wire [3:0] S_AXI_AWQOS, // Write Quality of Svc
//
// AXI write data channel signals
input wire S_AXI_WVALID, // Write valid
output wire S_AXI_WREADY, // Write data ready
input wire [C_AXI_DATA_WIDTH-1:0] S_AXI_WDATA, // Write data
input wire [C_AXI_DATA_WIDTH/8-1:0] S_AXI_WSTRB, // Write strobes
input wire S_AXI_WLAST, // Last write transaction
//
// AXI write response channel signals
output wire S_AXI_BVALID, // Write reponse valid
input wire S_AXI_BREADY, // Response ready
output wire [C_AXI_ID_WIDTH-1:0] S_AXI_BID, // Response ID
output wire [1:0] S_AXI_BRESP, // Write response
//
// AXI read address channel signals
input wire S_AXI_ARVALID, // Read address valid
output wire S_AXI_ARREADY, // Read address ready
input wire [C_AXI_ID_WIDTH-1:0] S_AXI_ARID, // Read ID
input wire [C_AXI_ADDR_WIDTH-1:0] S_AXI_ARADDR, // Read address
input wire [7:0] S_AXI_ARLEN, // Read Burst Length
input wire [2:0] S_AXI_ARSIZE, // Read Burst size
input wire [1:0] S_AXI_ARBURST, // Read Burst type
input wire [0:0] S_AXI_ARLOCK, // Read lock type
input wire [3:0] S_AXI_ARCACHE, // Read Cache type
input wire [2:0] S_AXI_ARPROT, // Read Protection type
input wire [3:0] S_AXI_ARQOS, // Read Quality of Svc
//
// AXI read data channel signals
output wire S_AXI_RVALID, // Read reponse valid
input wire S_AXI_RREADY, // Read Response ready
output wire [C_AXI_ID_WIDTH-1:0] S_AXI_RID, // Response ID
output wire [C_AXI_DATA_WIDTH-1:0] S_AXI_RDATA, // Read data
output wire S_AXI_RLAST, // Read last
output wire [1:0] S_AXI_RRESP, // Read response
// We'll share the clock and the reset
output wire o_reset,
output wire o_wb_cyc,
output wire o_wb_stb,
output wire o_wb_we,
output wire [(AW-1):0] o_wb_addr,
output wire [(C_AXI_DATA_WIDTH-1):0] o_wb_data,
output wire [(C_AXI_DATA_WIDTH/8-1):0] o_wb_sel,
input wire i_wb_stall,
input wire i_wb_ack,
input wire [(C_AXI_DATA_WIDTH-1):0] i_wb_data,
input wire i_wb_err
);
//
//
//
wire [(AW-1):0] w_wb_addr, r_wb_addr;
wire [(C_AXI_DATA_WIDTH-1):0] w_wb_data;
wire [(C_AXI_DATA_WIDTH/8-1):0] w_wb_sel;
wire r_wb_err, r_wb_cyc, r_wb_stb, r_wb_stall, r_wb_ack;
wire w_wb_err, w_wb_cyc, w_wb_stb, w_wb_stall, w_wb_ack;
wire r_wb_we, w_wb_we;
assign r_wb_we = 1'b0;
assign w_wb_we = 1'b1;
generate if (!OPT_READONLY)
begin : AXI_WR
aximwr2wbsp #(
.C_AXI_ID_WIDTH(C_AXI_ID_WIDTH),
.C_AXI_DATA_WIDTH(C_AXI_DATA_WIDTH),
.C_AXI_ADDR_WIDTH(C_AXI_ADDR_WIDTH),
.LGFIFO(LGFIFO))
axi_write_decoder(
.S_AXI_ACLK(S_AXI_ACLK), .S_AXI_ARESETN(S_AXI_ARESETN),
//
.S_AXI_AWVALID(S_AXI_AWVALID),
.S_AXI_AWREADY(S_AXI_AWREADY),
.S_AXI_AWID( S_AXI_AWID),
.S_AXI_AWADDR( S_AXI_AWADDR),
.S_AXI_AWLEN( S_AXI_AWLEN),
.S_AXI_AWSIZE( S_AXI_AWSIZE),
.S_AXI_AWBURST(S_AXI_AWBURST),
.S_AXI_AWLOCK( S_AXI_AWLOCK),
.S_AXI_AWCACHE(S_AXI_AWCACHE),
.S_AXI_AWPROT( S_AXI_AWPROT),
.S_AXI_AWQOS( S_AXI_AWQOS),
//
.S_AXI_WVALID( S_AXI_WVALID),
.S_AXI_WREADY( S_AXI_WREADY),
.S_AXI_WDATA( S_AXI_WDATA),
.S_AXI_WSTRB( S_AXI_WSTRB),
.S_AXI_WLAST( S_AXI_WLAST),
//
.S_AXI_BVALID(S_AXI_BVALID),
.S_AXI_BREADY(S_AXI_BREADY),
.S_AXI_BID( S_AXI_BID),
.S_AXI_BRESP( S_AXI_BRESP),
//
.o_wb_cyc( w_wb_cyc),
.o_wb_stb( w_wb_stb),
.o_wb_addr( w_wb_addr),
.o_wb_data( w_wb_data),
.o_wb_sel( w_wb_sel),
.i_wb_ack( w_wb_ack),
.i_wb_stall(w_wb_stall),
.i_wb_err( w_wb_err)
);
end else begin
assign w_wb_cyc = 0;
assign w_wb_stb = 0;
assign w_wb_addr = 0;
assign w_wb_data = 0;
assign w_wb_sel = 0;
assign S_AXI_AWREADY = 0;
assign S_AXI_WREADY = 0;
assign S_AXI_BVALID = 0;
assign S_AXI_BRESP = 2'b11;
assign S_AXI_BID = 0;
end endgenerate
generate if (!OPT_WRITEONLY)
begin : AXI_RD
aximrd2wbsp #(
.C_AXI_ID_WIDTH(C_AXI_ID_WIDTH),
.C_AXI_DATA_WIDTH(C_AXI_DATA_WIDTH),
.C_AXI_ADDR_WIDTH(C_AXI_ADDR_WIDTH),
.LGFIFO(LGFIFO))
axi_read_decoder(
.S_AXI_ACLK(S_AXI_ACLK), .S_AXI_ARESETN(S_AXI_ARESETN),
//
.S_AXI_ARVALID(S_AXI_ARVALID),
.S_AXI_ARREADY(S_AXI_ARREADY),
.S_AXI_ARID( S_AXI_ARID),
.S_AXI_ARADDR( S_AXI_ARADDR),
.S_AXI_ARLEN( S_AXI_ARLEN),
.S_AXI_ARSIZE( S_AXI_ARSIZE),
.S_AXI_ARBURST(S_AXI_ARBURST),
.S_AXI_ARLOCK( S_AXI_ARLOCK),
.S_AXI_ARCACHE(S_AXI_ARCACHE),
.S_AXI_ARPROT( S_AXI_ARPROT),
.S_AXI_ARQOS( S_AXI_ARQOS),
//
.S_AXI_RVALID(S_AXI_RVALID),
.S_AXI_RREADY(S_AXI_RREADY),
.S_AXI_RID( S_AXI_RID),
.S_AXI_RDATA( S_AXI_RDATA),
.S_AXI_RLAST( S_AXI_RLAST),
.S_AXI_RRESP( S_AXI_RRESP),
//
.o_wb_cyc( r_wb_cyc),
.o_wb_stb( r_wb_stb),
.o_wb_addr( r_wb_addr),
.i_wb_ack( r_wb_ack),
.i_wb_stall(r_wb_stall),
.i_wb_data( i_wb_data),
.i_wb_err( r_wb_err)
);
end else begin
assign r_wb_cyc = 0;
assign r_wb_stb = 0;
assign r_wb_addr = 0;
//
assign S_AXI_ARREADY = 0;
assign S_AXI_RVALID = 0;
assign S_AXI_RID = 0;
assign S_AXI_RDATA = 0;
assign S_AXI_RLAST = 0;
assign S_AXI_RRESP = 0;
end endgenerate
generate if (OPT_READONLY)
begin : ARB_RD
assign o_wb_cyc = r_wb_cyc;
assign o_wb_stb = r_wb_stb;
assign o_wb_we = r_wb_we;
assign o_wb_addr = r_wb_addr;
assign o_wb_data = 0;
assign o_wb_sel = 0;
assign r_wb_ack = i_wb_ack;
assign r_wb_stall= i_wb_stall;
assign r_wb_ack = i_wb_ack;
assign r_wb_err = i_wb_err;
end else if (OPT_WRITEONLY)
begin : ARB_WR
assign o_wb_cyc = w_wb_cyc;
assign o_wb_stb = w_wb_stb;
assign o_wb_we = w_wb_we;
assign o_wb_addr = w_wb_addr;
assign o_wb_data = w_wb_data;
assign o_wb_sel = w_wb_sel;
assign w_wb_ack = i_wb_ack;
assign w_wb_stall= i_wb_stall;
assign w_wb_ack = i_wb_ack;
assign w_wb_err = i_wb_err;
end else begin : ARB_WB
wbarbiter #(.DW(DW), .AW(AW))
readorwrite(S_AXI_ACLK, o_reset,
r_wb_cyc, r_wb_stb, r_wb_we, r_wb_addr, w_wb_data, w_wb_sel,
r_wb_ack, r_wb_stall, r_wb_err,
w_wb_cyc, w_wb_stb, w_wb_we, w_wb_addr, w_wb_data, w_wb_sel,
w_wb_ack, w_wb_stall, w_wb_err,
o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data, o_wb_sel,
i_wb_ack, i_wb_stall, i_wb_err
);
end endgenerate
assign o_reset = (S_AXI_ARESETN == 1'b0);
`ifdef FORMAL
`endif
endmodule