//////////////////////////////////////////////////////////////////////////////// // // Filename: axi32axi.v // {{{ // Project: WB2AXIPSP: bus bridges and other odds and ends // // Purpose: Bridge from an AXI3 slave to an AXI4 master // // The goal here is to support as high a bus speed as possible, maintain // burst support (if possible) and (more important) allow bus requests // coming from the ARM within either the Zynq or one of Intel's SOC chips // to speak with an AutoFPGA based design. // // Note that if you aren't using AutoFPGA, then you probably don't need // this core--the vendor tools should be able to handle this conversion // quietly and automatically for you. // // Notes: // AxCACHE is remapped as per the AXI4 specification, since the values // aren't truly equivalent. This forces a single clock delay in the Ax* // channels and (likely) the W* channel as well as a system level // consequence. // // AXI3 locking is not supported under AXI4. As per the AXI4 spec, // AxLOCK is converteted from AXI3 to AXI4 by just dropping the high // order bit. // // The WID input is ignored. Whether or not this input can be ignored // is based upon how the ARM is implemented internally. After a bit // of research into both Zynq's and Intel SOCs, this appears to be the // appropriate answer here. // // Creator: Dan Gisselquist, Ph.D. // Gisselquist Technology, LLC // //////////////////////////////////////////////////////////////////////////////// // }}} // Copyright (C) 2020-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 axi32axi #( // {{{ parameter C_AXI_ID_WIDTH = 1, parameter C_AXI_ADDR_WIDTH = 32, parameter C_AXI_DATA_WIDTH = 32, parameter OPT_REORDER_METHOD = 0, parameter [0:0] OPT_TRANSFORM_AXCACHE = 1, parameter [0:0] OPT_LOWPOWER = 0, parameter [0:0] OPT_LOW_LATENCY = 0, parameter WID_LGAWFIFO = 3, parameter WID_LGWFIFO = 3 // // }}} ) ( // {{{ input wire S_AXI_ACLK, input wire S_AXI_ARESETN, // // The AXI3 incoming/slave interface 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 [3:0] S_AXI_AWLEN, input wire [2:0] S_AXI_AWSIZE, input wire [1:0] S_AXI_AWBURST, input wire [1: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, // // input wire S_AXI_WVALID, output wire S_AXI_WREADY, input wire [C_AXI_ID_WIDTH-1:0] S_AXI_WID, 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, // // 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, // // 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 [3:0] S_AXI_ARLEN, input wire [2:0] S_AXI_ARSIZE, input wire [1:0] S_AXI_ARBURST, input wire [1: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, // output wire S_AXI_RVALID, input wire S_AXI_RREADY, output wire [C_AXI_ID_WIDTH-1:0] S_AXI_RID, output wire [C_AXI_DATA_WIDTH-1:0] S_AXI_RDATA, output wire S_AXI_RLAST, output wire [1:0] S_AXI_RRESP, // // // The AXI4 Master (outgoing) interface output wire M_AXI_AWVALID, input wire M_AXI_AWREADY, output wire [C_AXI_ID_WIDTH-1:0] M_AXI_AWID, output wire [C_AXI_ADDR_WIDTH-1:0] M_AXI_AWADDR, output wire [7:0] M_AXI_AWLEN, output wire [2:0] M_AXI_AWSIZE, output wire [1:0] M_AXI_AWBURST, output wire M_AXI_AWLOCK, output wire [3:0] M_AXI_AWCACHE, output wire [2:0] M_AXI_AWPROT, output wire [3:0] M_AXI_AWQOS, // // output wire M_AXI_WVALID, input wire M_AXI_WREADY, output wire [C_AXI_DATA_WIDTH-1:0] M_AXI_WDATA, output wire [C_AXI_DATA_WIDTH/8-1:0] M_AXI_WSTRB, output wire M_AXI_WLAST, // // input wire M_AXI_BVALID, output wire M_AXI_BREADY, input wire [C_AXI_ID_WIDTH-1:0] M_AXI_BID, input wire [1:0] M_AXI_BRESP, // // output wire M_AXI_ARVALID, input wire M_AXI_ARREADY, output wire [C_AXI_ID_WIDTH-1:0] M_AXI_ARID, output wire [C_AXI_ADDR_WIDTH-1:0] M_AXI_ARADDR, output wire [7:0] M_AXI_ARLEN, output wire [2:0] M_AXI_ARSIZE, output wire [1:0] M_AXI_ARBURST, output wire M_AXI_ARLOCK, output wire [3:0] M_AXI_ARCACHE, output wire [2:0] M_AXI_ARPROT, output wire [3:0] M_AXI_ARQOS, // input wire M_AXI_RVALID, output wire M_AXI_RREADY, input wire [C_AXI_ID_WIDTH-1:0] M_AXI_RID, input wire [C_AXI_DATA_WIDTH-1:0] M_AXI_RDATA, input wire M_AXI_RLAST, input wire [1:0] M_AXI_RRESP // }}} ); // verilator tracing_off // Register/net declarations // {{{ // localparam ADDRLSB= $clog2(C_AXI_DATA_WIDTH)-3; localparam IW=C_AXI_ID_WIDTH; reg [3:0] axi4_awcache, axi4_arcache; reg axi4_awlock, axi4_arlock; wire awskd_ready; wire wid_reorder_awready; wire [IW-1:0] reordered_wid; // }}} // Write cache remapping // {{{ always @(*) case(S_AXI_AWCACHE) 4'b1010: axi4_awcache = 4'b1110; 4'b1011: axi4_awcache = 4'b1111; default: axi4_awcache = S_AXI_AWCACHE; endcase // }}} // AWLOCK // {{{ always @(*) axi4_awlock = S_AXI_AWLOCK[0]; // }}} // AW Skid buffer // {{{ generate if (OPT_TRANSFORM_AXCACHE) begin : GEN_AWCACHE // {{{ skidbuffer #( .DW(C_AXI_ADDR_WIDTH + C_AXI_ID_WIDTH + 4 + 3 + 2 + 1+4+3+4), .OPT_OUTREG(1'b1) ) awskid ( .i_clk(S_AXI_ACLK), .i_reset(!S_AXI_ARESETN), .i_valid(S_AXI_AWVALID && wid_reorder_awready), .o_ready(awskd_ready), .i_data({ S_AXI_AWID, S_AXI_AWADDR, S_AXI_AWLEN, S_AXI_AWSIZE, S_AXI_AWBURST,axi4_awlock, axi4_awcache, S_AXI_AWPROT, S_AXI_AWQOS }), .o_valid(M_AXI_AWVALID), .i_ready(M_AXI_AWREADY), .o_data({ M_AXI_AWID, M_AXI_AWADDR, M_AXI_AWLEN[3:0], M_AXI_AWSIZE,M_AXI_AWBURST,M_AXI_AWLOCK, M_AXI_AWCACHE,M_AXI_AWPROT, M_AXI_AWQOS }) ); assign M_AXI_AWLEN[7:4] = 4'h0; assign S_AXI_AWREADY = awskd_ready && wid_reorder_awready; // }}} end else begin : IGN_AWCACHE // {{{ assign M_AXI_AWVALID = S_AXI_AWVALID && wid_reorder_awready; assign S_AXI_AWREADY = M_AXI_AWREADY; assign M_AXI_AWID = S_AXI_AWID; assign M_AXI_AWADDR = S_AXI_AWADDR; assign M_AXI_AWLEN = { 4'h0, S_AXI_AWLEN }; assign M_AXI_AWSIZE = S_AXI_AWSIZE; assign M_AXI_AWBURST = S_AXI_AWBURST; assign M_AXI_AWLOCK = axi4_awlock; assign M_AXI_AWCACHE = axi4_awcache; assign M_AXI_AWPROT = S_AXI_AWPROT; assign M_AXI_AWQOS = S_AXI_AWQOS; assign awskd_ready = 1; // }}} end endgenerate // }}} // Handle write channel de-interleaving // {{{ axi3reorder #( // {{{ .C_AXI_ID_WIDTH(C_AXI_ID_WIDTH), .C_AXI_DATA_WIDTH(C_AXI_DATA_WIDTH), .OPT_METHOD(OPT_REORDER_METHOD), .OPT_LOWPOWER(OPT_LOWPOWER), .OPT_LOW_LATENCY(OPT_LOW_LATENCY), .LGAWFIFO(WID_LGAWFIFO), .LGWFIFO(WID_LGWFIFO) // }}} ) widreorder ( // {{{ .S_AXI_ACLK(S_AXI_ACLK), .S_AXI_ARESETN(S_AXI_ARESETN), // Incoming Write address ID .S_AXI3_AWVALID(S_AXI_AWVALID && S_AXI_AWREADY), .S_AXI3_AWREADY(wid_reorder_awready), .S_AXI3_AWID(S_AXI_AWID), // Incoming Write data info .S_AXI3_WVALID(S_AXI_WVALID), .S_AXI3_WREADY(S_AXI_WREADY), .S_AXI3_WID(S_AXI_WID), .S_AXI3_WDATA(S_AXI_WDATA), .S_AXI3_WSTRB(S_AXI_WSTRB), .S_AXI3_WLAST(S_AXI_WLAST), // Outgoing write data channel .M_AXI_WVALID(M_AXI_WVALID), .M_AXI_WREADY(M_AXI_WREADY), .M_AXI_WID(reordered_wid), .M_AXI_WDATA(M_AXI_WDATA), .M_AXI_WSTRB(M_AXI_WSTRB), .M_AXI_WLAST(M_AXI_WLAST) // }}} ); // }}} // Forward the B* channel return // {{{ assign S_AXI_BVALID = M_AXI_BVALID; assign M_AXI_BREADY = S_AXI_BREADY; assign S_AXI_BID = M_AXI_BID; assign S_AXI_BRESP = M_AXI_BRESP; // }}} // Read cache remapping // {{{ always @(*) case(S_AXI_ARCACHE) 4'b0110: axi4_arcache = 4'b1110; 4'b0111: axi4_arcache = 4'b1111; default: axi4_arcache = S_AXI_ARCACHE; endcase // }}} // ARLOCK // {{{ always @(*) axi4_arlock = S_AXI_ARLOCK[0]; // }}} // AR Skid buffer // {{{ generate if (OPT_TRANSFORM_AXCACHE) begin : GEN_ARCACHE // {{{ skidbuffer #( .DW(C_AXI_ADDR_WIDTH + C_AXI_ID_WIDTH + 4 + 3 + 2 + 1+4+3+4), .OPT_OUTREG(1'b1) ) arskid ( .i_clk(S_AXI_ACLK), .i_reset(!S_AXI_ARESETN), .i_valid(S_AXI_ARVALID), .o_ready(S_AXI_ARREADY), .i_data({ S_AXI_ARID, S_AXI_ARADDR, S_AXI_ARLEN, S_AXI_ARSIZE, S_AXI_ARBURST, axi4_arlock, axi4_arcache, S_AXI_ARPROT, S_AXI_ARQOS }), .o_valid(M_AXI_ARVALID), .i_ready(M_AXI_ARREADY), .o_data({ M_AXI_ARID, M_AXI_ARADDR, M_AXI_ARLEN[3:0], M_AXI_ARSIZE, M_AXI_ARBURST, M_AXI_ARLOCK, M_AXI_ARCACHE, M_AXI_ARPROT, M_AXI_ARQOS }) ); assign M_AXI_ARLEN[7:4] = 4'h0; // }}} end else begin : IGN_ARCACHE // {{{ assign M_AXI_ARVALID = S_AXI_ARVALID; assign S_AXI_ARREADY = M_AXI_ARREADY; assign M_AXI_ARID = S_AXI_ARID; assign M_AXI_ARADDR = S_AXI_ARADDR; assign M_AXI_ARLEN = { 4'h0, S_AXI_ARLEN }; assign M_AXI_ARSIZE = S_AXI_ARSIZE; assign M_AXI_ARBURST = S_AXI_ARBURST; assign M_AXI_ARLOCK = axi4_arlock; assign M_AXI_ARCACHE = axi4_arcache; assign M_AXI_ARPROT = S_AXI_ARPROT; assign M_AXI_ARQOS = S_AXI_ARQOS; // }}} end endgenerate // }}} // Forward the R* channel return // {{{ assign S_AXI_RVALID = M_AXI_RVALID; assign M_AXI_RREADY = S_AXI_RREADY; assign S_AXI_RID = M_AXI_RID; assign S_AXI_RDATA = M_AXI_RDATA; assign S_AXI_RLAST = M_AXI_RLAST; assign S_AXI_RRESP = M_AXI_RRESP; // }}} // Verilator lint_off UNUSED wire unused; assign unused = &{ 1'b0, S_AXI_AWLOCK[1], S_AXI_ARLOCK[1], reordered_wid }; // Verilator lint_on UNUSED //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // // Formal property section // //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// `ifdef FORMAL // // This design has not been formally verified. // `endif endmodule