diff options
Diffstat (limited to 'rtl/wb2axip/axilempty.v')
| -rw-r--r-- | rtl/wb2axip/axilempty.v | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/rtl/wb2axip/axilempty.v b/rtl/wb2axip/axilempty.v new file mode 100644 index 0000000..f429d69 --- /dev/null +++ b/rtl/wb2axip/axilempty.v @@ -0,0 +1,371 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: axilempty.v +// {{{ +// Project: WB2AXIPSP: bus bridges and other odds and ends +// +// Purpose: Modifies the simple AXI-lite interface to be an empty shell +// +// This is useful for a bus with masters but no slaves. When used, +// the interconnect can connect those masters to this slave to know +// that requests will still be properly handled--and get proper error +// returns. +// +// 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 axilempty #( + // {{{ + // + // Size of the AXI-lite bus. These are fixed, since 1) AXI-lite + // is fixed at a width of 32-bits by Xilinx def'n, and 2) since + // we only ever have 4 configuration words. + // Verilator lint_off UNUSED + parameter C_AXI_ADDR_WIDTH = 4, + // Verilator lint_on UNUSED + localparam C_AXI_DATA_WIDTH = 32, + parameter [0:0] OPT_SKIDBUFFER = 1'b0, + parameter [0:0] OPT_LOWPOWER = 0 + // }}} + ) ( + // {{{ + input wire S_AXI_ACLK, + input wire S_AXI_ARESETN, + // + input wire S_AXI_AWVALID, + output wire S_AXI_AWREADY, + // + input wire S_AXI_WVALID, + output wire S_AXI_WREADY, + // + output wire S_AXI_BVALID, + input wire S_AXI_BREADY, + output wire [1:0] S_AXI_BRESP, + // + input wire S_AXI_ARVALID, + output wire S_AXI_ARREADY, + // + output wire S_AXI_RVALID, + input wire S_AXI_RREADY, + output wire [C_AXI_DATA_WIDTH-1:0] S_AXI_RDATA, + output wire [1:0] S_AXI_RRESP + // }}} + ); + + //////////////////////////////////////////////////////////////////////// + // + // Register/wire signal declarations + // + //////////////////////////////////////////////////////////////////////// + // + // {{{ + wire i_reset = !S_AXI_ARESETN; + + wire axil_write_ready; + // + reg axil_bvalid; + // + wire axil_read_ready; + reg axil_read_valid; + + //////////////////////////////////////////////////////////////////////// + // + // AXI-lite signaling + // + //////////////////////////////////////////////////////////////////////// + // + // {{{ + + // + // Write signaling + // + // {{{ + + generate if (OPT_SKIDBUFFER) + begin : SKIDBUFFER_WRITE + + wire awskd_valid, wskd_valid, awskd_unused, wskd_unused; + + skidbuffer #(.OPT_OUTREG(0), + .OPT_LOWPOWER(OPT_LOWPOWER), .DW(1)) + axilawskid(// + .i_clk(S_AXI_ACLK), .i_reset(i_reset), + .i_valid(S_AXI_AWVALID), .o_ready(S_AXI_AWREADY), + .i_data(1'b0), + .o_valid(awskd_valid), .i_ready(axil_write_ready), + .o_data(awskd_unused)); + +`ifdef FORMAL + always @(*) + if (awskd_valid) + assert(awskd_unused == 0); +`endif + + skidbuffer #(.OPT_OUTREG(0), .OPT_LOWPOWER(OPT_LOWPOWER), + .DW(1)) + axilwskid(// + .i_clk(S_AXI_ACLK), .i_reset(i_reset), + .i_valid(S_AXI_WVALID), .o_ready(S_AXI_WREADY), + .i_data({ 1'b0 }), + .o_valid(wskd_valid), .i_ready(axil_write_ready), + .o_data(wskd_unused)); +`ifdef FORMAL + always @(*) + if (wskd_valid) + assert(wskd_unused == 0); +`endif + + assign axil_write_ready = awskd_valid && wskd_valid + && (!S_AXI_BVALID || S_AXI_BREADY); + + // Verilator lint_off UNUSED + wire unused; + assign unused = &{ 1'b0, awskd_unused, wskd_unused }; + // Verilator lint_on UNUSED + end else begin : SIMPLE_WRITES + + reg axil_awready; + + initial axil_awready = 1'b0; + always @(posedge S_AXI_ACLK) + if (!S_AXI_ARESETN) + axil_awready <= 1'b0; + else + axil_awready <= !axil_awready + && (S_AXI_AWVALID && S_AXI_WVALID) + && (!S_AXI_BVALID || S_AXI_BREADY); + + assign S_AXI_AWREADY = axil_awready; + assign S_AXI_WREADY = axil_awready; + + assign axil_write_ready = axil_awready; + + end endgenerate + + initial axil_bvalid = 0; + always @(posedge S_AXI_ACLK) + if (i_reset) + axil_bvalid <= 0; + else if (axil_write_ready) + axil_bvalid <= 1; + else if (S_AXI_BREADY) + axil_bvalid <= 0; + + assign S_AXI_BVALID = axil_bvalid; + assign S_AXI_BRESP = 2'b11; + // }}} + + // + // Read signaling + // + // {{{ + + generate if (OPT_SKIDBUFFER) + begin : SKIDBUFFER_READ + + wire arskd_valid, arskd_unused; + + skidbuffer #(.OPT_OUTREG(0), + .OPT_LOWPOWER(OPT_LOWPOWER), + .DW(1)) + axilarskid(// + .i_clk(S_AXI_ACLK), .i_reset(i_reset), + .i_valid(S_AXI_ARVALID), .o_ready(S_AXI_ARREADY), + .i_data( 1'b0 ), + .o_valid(arskd_valid), .i_ready(axil_read_ready), + .o_data(arskd_unused)); + + assign axil_read_ready = arskd_valid + && (!axil_read_valid || S_AXI_RREADY); + +`ifdef FORMAL + always @(*) + if (arskd_valid) + assert(arskd_unused == 0); +`endif + + // Verilator lint_off UNUSED + wire unused; + assign unused = &{ 1'b0, arskd_unused }; + // Verilator lint_on UNUSED + end else begin : SIMPLE_READS + + reg axil_arready; + + always @(*) + axil_arready = !S_AXI_RVALID; + + assign S_AXI_ARREADY = axil_arready; + assign axil_read_ready = (S_AXI_ARVALID && S_AXI_ARREADY); + + end endgenerate + + initial axil_read_valid = 1'b0; + always @(posedge S_AXI_ACLK) + if (i_reset) + axil_read_valid <= 1'b0; + else if (axil_read_ready) + axil_read_valid <= 1'b1; + else if (S_AXI_RREADY) + axil_read_valid <= 1'b0; + + assign S_AXI_RVALID = axil_read_valid; + assign S_AXI_RDATA = 0; + assign S_AXI_RRESP = 2'b11; + // }}} + + // }}} + //////////////////////////////////////////////////////////////////////// + // + // AXI-lite register logic + // + //////////////////////////////////////////////////////////////////////// + // + // {{{ + + + // }}} + + // Verilator lint_off UNUSED + wire unused; + assign unused = &{ 1'b0 }; + // Verilator lint_on UNUSED + // }}} +`ifdef FORMAL + //////////////////////////////////////////////////////////////////////// + // + // Formal properties used in verfiying this core + // + //////////////////////////////////////////////////////////////////////// + // + // {{{ + reg f_past_valid; + initial f_past_valid = 0; + always @(posedge S_AXI_ACLK) + f_past_valid <= 1; + + //////////////////////////////////////////////////////////////////////// + // + // The AXI-lite control interface + // + //////////////////////////////////////////////////////////////////////// + // + // {{{ + localparam F_AXIL_LGDEPTH = 4; + wire [F_AXIL_LGDEPTH-1:0] faxil_rd_outstanding, + faxil_wr_outstanding, + faxil_awr_outstanding; + + faxil_slave #( + // {{{ + .C_AXI_DATA_WIDTH(C_AXI_DATA_WIDTH), + .C_AXI_ADDR_WIDTH(C_AXI_ADDR_WIDTH), + .F_LGDEPTH(F_AXIL_LGDEPTH), + .F_AXI_MAXWAIT(2), + .F_AXI_MAXDELAY(2), + .F_AXI_MAXRSTALL(3), + .F_OPT_COVER_BURST(0) + // }}} + ) faxil( + // {{{ + .i_clk(S_AXI_ACLK), .i_axi_reset_n(S_AXI_ARESETN), + // + .i_axi_awvalid(S_AXI_AWVALID), + .i_axi_awready(S_AXI_AWREADY), + .i_axi_awaddr({(C_AXI_ADDR_WIDTH){1'b0}}), + .i_axi_awprot( 3'h0), + // + .i_axi_wvalid(S_AXI_WVALID), + .i_axi_wready(S_AXI_WREADY), + .i_axi_wdata( {(C_AXI_DATA_WIDTH){1'b0}}), + .i_axi_wstrb( {(C_AXI_DATA_WIDTH/8){1'b0}}), + // + .i_axi_bvalid(S_AXI_BVALID), + .i_axi_bready(S_AXI_BREADY), + .i_axi_bresp( S_AXI_BRESP), + // + .i_axi_arvalid(S_AXI_ARVALID), + .i_axi_arready(S_AXI_ARREADY), + .i_axi_araddr( {(C_AXI_ADDR_WIDTH){1'b0}}), + .i_axi_arprot( 3'h0), + // + .i_axi_rvalid(S_AXI_RVALID), + .i_axi_rready(S_AXI_RREADY), + .i_axi_rdata( S_AXI_RDATA), + .i_axi_rresp( S_AXI_RRESP), + // + .f_axi_rd_outstanding(faxil_rd_outstanding), + .f_axi_wr_outstanding(faxil_wr_outstanding), + .f_axi_awr_outstanding(faxil_awr_outstanding) + // }}} + ); + + always @(*) + if (OPT_SKIDBUFFER) + begin + assert(faxil_awr_outstanding== (S_AXI_BVALID ? 1:0) + +(S_AXI_AWREADY ? 0:1)); + assert(faxil_wr_outstanding == (S_AXI_BVALID ? 1:0) + +(S_AXI_WREADY ? 0:1)); + + assert(faxil_rd_outstanding == (S_AXI_RVALID ? 1:0) + +(S_AXI_ARREADY ? 0:1)); + end else begin + assert(faxil_wr_outstanding == (S_AXI_BVALID ? 1:0)); + assert(faxil_awr_outstanding == faxil_wr_outstanding); + + assert(faxil_rd_outstanding == (S_AXI_RVALID ? 1:0)); + end + + // + // Check that our low-power only logic works by verifying that anytime + // S_AXI_RVALID is inactive, then the outgoing data is also zero. + // + always @(*) + assert(S_AXI_RDATA == 0); + always @(*) + assert(S_AXI_RRESP == 2'b11); + always @(*) + assert(S_AXI_BRESP == 2'b11); + + // }}} + //////////////////////////////////////////////////////////////////////// + // + // Cover checks + // + //////////////////////////////////////////////////////////////////////// + // + // {{{ + + // While there are already cover properties in the formal property + // set above, you'll probably still want to cover something + // application specific here + + // }}} + // }}} +`endif +endmodule |
