318 lines
9.0 KiB
Verilog
318 lines
9.0 KiB
Verilog
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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-2024, 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_SWAP_ENDIANNESS = 1'b0,
|
|
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,
|
|
output wire S_AXI_AWREADY,
|
|
input wire [C_AXI_ID_WIDTH-1:0] S_AXI_AWID,
|
|
input wire [C_AXI_ADDR_WIDTH-1:0] S_AXI_AWADDR,
|
|
input wire [7:0] S_AXI_AWLEN,
|
|
input wire [2:0] S_AXI_AWSIZE,
|
|
input wire [1:0] S_AXI_AWBURST,
|
|
input wire [0:0] S_AXI_AWLOCK,
|
|
input wire [3:0] S_AXI_AWCACHE,
|
|
input wire [2:0] S_AXI_AWPROT,
|
|
input wire [3:0] S_AXI_AWQOS,
|
|
// }}}
|
|
// AXI write data channel signals
|
|
// {{{
|
|
input wire S_AXI_WVALID,
|
|
output wire S_AXI_WREADY,
|
|
input wire [C_AXI_DATA_WIDTH-1:0] S_AXI_WDATA,
|
|
input wire [C_AXI_DATA_WIDTH/8-1:0] S_AXI_WSTRB,
|
|
input wire S_AXI_WLAST,
|
|
// }}}
|
|
// AXI write response channel signals
|
|
// {{{
|
|
output wire S_AXI_BVALID,
|
|
input wire S_AXI_BREADY,
|
|
output wire [C_AXI_ID_WIDTH-1:0] S_AXI_BID,
|
|
output wire [1:0] S_AXI_BRESP,
|
|
// }}}
|
|
// AXI read address channel signals
|
|
// {{{
|
|
input wire S_AXI_ARVALID,
|
|
output wire S_AXI_ARREADY,
|
|
input wire [C_AXI_ID_WIDTH-1:0] S_AXI_ARID,
|
|
input wire [C_AXI_ADDR_WIDTH-1:0] S_AXI_ARADDR,
|
|
input wire [7:0] S_AXI_ARLEN,
|
|
input wire [2:0] S_AXI_ARSIZE,
|
|
input wire [1:0] S_AXI_ARBURST,
|
|
input wire [0:0] S_AXI_ARLOCK,
|
|
input wire [3:0] S_AXI_ARCACHE,
|
|
input wire [2:0] S_AXI_ARPROT,
|
|
input wire [3:0] S_AXI_ARQOS,
|
|
// }}}
|
|
// AXI read data channel signals
|
|
// {{{
|
|
output wire S_AXI_RVALID, // Rd rslt valid
|
|
input wire S_AXI_RREADY, // Rd rslt 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, r_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),
|
|
.OPT_SWAP_ENDIANNESS(OPT_SWAP_ENDIANNESS),
|
|
.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 : NO_WRITE_CHANNEL
|
|
// {{{
|
|
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),
|
|
.OPT_SWAP_ENDIANNESS(OPT_SWAP_ENDIANNESS),
|
|
.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),
|
|
.o_wb_sel( r_wb_sel),
|
|
.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 : NO_READ_CHANNEL
|
|
// {{{
|
|
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 = r_wb_sel;
|
|
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, r_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
|