diff options
author | Martin Braun <martin.braun@ettus.com> | 2020-01-23 16:10:22 -0800 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2020-01-28 09:35:36 -0800 |
commit | bafa9d95453387814ef25e6b6256ba8db2df612f (patch) | |
tree | 39ba24b5b67072d354775272e687796bb511848d /fpga/usrp3/lib/rfnoc/crossbar/chdr_xb_ingress_buff.v | |
parent | 3075b981503002df3115d5f1d0b97d2619ba30f2 (diff) | |
download | uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.gz uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.bz2 uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.zip |
Merge FPGA repository back into UHD repository
The FPGA codebase was removed from the UHD repository in 2014 to reduce
the size of the repository. However, over the last half-decade, the
split between the repositories has proven more burdensome than it has
been helpful. By merging the FPGA code back, it will be possible to
create atomic commits that touch both FPGA and UHD codebases. Continuous
integration testing is also simplified by merging the repositories,
because it was previously difficult to automatically derive the correct
UHD branch when testing a feature branch on the FPGA repository.
This commit also updates the license files and paths therein.
We are therefore merging the repositories again. Future development for
FPGA code will happen in the same repository as the UHD host code and
MPM code.
== Original Codebase and Rebasing ==
The original FPGA repository will be hosted for the foreseeable future
at its original local location: https://github.com/EttusResearch/fpga/
It can be used for bisecting, reference, and a more detailed history.
The final commit from said repository to be merged here is
05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as
v4.0.0.0-pre-uhd-merge.
If you have changes in the FPGA repository that you want to rebase onto
the UHD repository, simply run the following commands:
- Create a directory to store patches (this should be an empty
directory):
mkdir ~/patches
- Now make sure that your FPGA codebase is based on the same state as
the code that was merged:
cd src/fpga # Or wherever your FPGA code is stored
git rebase v4.0.0.0-pre-uhd-merge
Note: The rebase command may look slightly different depending on what
exactly you're trying to rebase.
- Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge:
git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches
Note: Make sure that only patches are stored in your output directory.
It should otherwise be empty. Make sure that you picked the correct
range of commits, and only commits you wanted to rebase were exported
as patch files.
- Go to the UHD repository and apply the patches:
cd src/uhd # Or wherever your UHD repository is stored
git am --directory fpga ~/patches/*
rm -rf ~/patches # This is for cleanup
== Contributors ==
The following people have contributed mainly to these files (this list
is not complete):
Co-authored-by: Alex Williams <alex.williams@ni.com>
Co-authored-by: Andrej Rode <andrej.rode@ettus.com>
Co-authored-by: Ashish Chaudhari <ashish@ettus.com>
Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com>
Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Derek Kozel <derek.kozel@ettus.com>
Co-authored-by: EJ Kreinar <ej@he360.com>
Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com>
Co-authored-by: Ian Buckley <ian.buckley@gmail.com>
Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Jon Kiser <jon.kiser@ni.com>
Co-authored-by: Josh Blum <josh@joshknows.com>
Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com>
Co-authored-by: Martin Braun <martin.braun@ettus.com>
Co-authored-by: Matt Ettus <matt@ettus.com>
Co-authored-by: Michael West <michael.west@ettus.com>
Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com>
Co-authored-by: Nick Foster <nick@ettus.com>
Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Paul David <paul.david@ettus.com>
Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com>
Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com>
Co-authored-by: Sylvain Munaut <tnt@246tNt.com>
Co-authored-by: Trung Tran <trung.tran@ettus.com>
Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/crossbar/chdr_xb_ingress_buff.v')
-rw-r--r-- | fpga/usrp3/lib/rfnoc/crossbar/chdr_xb_ingress_buff.v | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/crossbar/chdr_xb_ingress_buff.v b/fpga/usrp3/lib/rfnoc/crossbar/chdr_xb_ingress_buff.v new file mode 100644 index 000000000..dcb11da8e --- /dev/null +++ b/fpga/usrp3/lib/rfnoc/crossbar/chdr_xb_ingress_buff.v @@ -0,0 +1,259 @@ +// +// Copyright 2018 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: chdr_ingress_buff +// +// Description: +// +// Ingress buffer module for the CHDR crossbar. This module stores and gates +// the incoming packet and simultaneously determines the destination (TDEST) +// by inspecting the incoming TID. If the TID is CHDR_MGMT_ROUTE_EPID then we +// perform a lookup on the TID to determine the correct output for TDEST. +// +// Parameters: +// +// WIDTH : Data width of the CHDR interfaces (TDATA) +// MTU : Maximum transmission unit, in WIDTH-sized words, is 2**MTU +// DEST_W : Width of the destination routing information (TDEST) +// NODE_ID : Numeric identifier for this port +// + +module chdr_xb_ingress_buff #( + parameter WIDTH = 64, + parameter MTU = 5, + parameter DEST_W = 4, + parameter [9:0] NODE_ID = 0 +) ( + input wire clk, + input wire reset, + // CHDR input port + input wire [WIDTH-1:0] s_axis_chdr_tdata, + input wire [DEST_W-1:0] s_axis_chdr_tdest, + input wire [1:0] s_axis_chdr_tid, + input wire s_axis_chdr_tlast, + input wire s_axis_chdr_tvalid, + output wire s_axis_chdr_tready, + // CHDR output port (with a tdest and tkeep) + output wire [WIDTH-1:0] m_axis_chdr_tdata, + output wire [DEST_W-1:0] m_axis_chdr_tdest, + output wire m_axis_chdr_tkeep, + output wire m_axis_chdr_tlast, + output wire m_axis_chdr_tvalid, + input wire m_axis_chdr_tready, + // Find port going to routing table + output wire [15:0] m_axis_find_tdata, + output wire m_axis_find_tvalid, + input wire m_axis_find_tready, + // Result port from routing table + input wire [DEST_W-1:0] s_axis_result_tdata, + input wire s_axis_result_tkeep, + input wire s_axis_result_tvalid, + output wire s_axis_result_tready +); + + // RFNoC Includes + `include "../core/rfnoc_chdr_utils.vh" + `include "../core/rfnoc_chdr_internal_utils.vh" + + + //--------------------------------------------------------------------------- + // Packet Buffer + //--------------------------------------------------------------------------- + + wire [WIDTH-1:0] gate_i_tdata , gate_o_tdata ; + wire gate_i_tlast , gate_o_tlast ; + wire gate_i_tvalid, gate_o_tvalid; + wire gate_i_tready, gate_o_tready; + + // The axi_packet_gate queues up an entire packet before letting it go out. + // This reduces congestion in the crossbar for slowly-built packets. + axi_packet_gate #( + .WIDTH (WIDTH), + .SIZE (MTU) + ) axi_packet_gate_i ( + .clk (clk), + .reset (reset), + .clear (1'b0), + .i_tdata (gate_i_tdata), + .i_tlast (gate_i_tlast), + .i_terror (1'b0), + .i_tvalid (gate_i_tvalid), + .i_tready (gate_i_tready), + .o_tdata (gate_o_tdata), + .o_tlast (gate_o_tlast), + .o_tvalid (gate_o_tvalid), + .o_tready (gate_o_tready) + ); + + + //--------------------------------------------------------------------------- + // Destination (TDEST) Muxing + //--------------------------------------------------------------------------- + + wire [15:0] find_tdata; + wire find_tvalid, find_tready; + + wire [DEST_W-1:0] dest_i_tdata; + wire dest_i_tkeep, dest_i_tvalid, dest_i_tready; + wire [DEST_W-1:0] dest_o_tdata; + wire dest_o_tkeep, dest_o_tvalid, dest_o_tready; + + // The find_fifo holds the lookup requests from the find_* AXI stream and + // sends them on to the m_axis_find_* stream port. It is required because the + // input logic (see below) doesn't obey the AXI handshake protocol but this + // FIFO can tolerate it. + axi_fifo #( + .WIDTH (16), + .SIZE (1) + ) find_fifo_i ( + .clk (clk), + .reset (reset), + .clear (1'b0), + .i_tdata (find_tdata), + .i_tvalid (find_tvalid), + .i_tready (find_tready), + .o_tdata (m_axis_find_tdata), + .o_tvalid (m_axis_find_tvalid), + .o_tready (m_axis_find_tready), + .space (), + .occupied () + ); + + // The destination (TDEST) can come from two sources: Directly from the + // packet info (in which case TDEST was immediately determined and comes in + // on dest_* AXI stream) or via a lookup (in which case the result comes in + // on s_axis_result_*). Only one of these data paths is used at a time, so we + // mux them together here create a single stream (dest_o_*) that contains the + // destination for the next packet. + axi_mux #( + .WIDTH (DEST_W+1), + .SIZE (2), + .PRIO (1), + .PRE_FIFO_SIZE (1), + .POST_FIFO_SIZE (1) + ) dest_mux_i ( + .clk (clk), + .reset (reset), + .clear (1'b0), + .i_tdata ({dest_i_tkeep, dest_i_tdata, + s_axis_result_tkeep, s_axis_result_tdata}), + .i_tlast (2'b11), + .i_tvalid ({dest_i_tvalid, s_axis_result_tvalid}), + .i_tready ({dest_i_tready, s_axis_result_tready}), + .o_tdata ({dest_o_tkeep, dest_o_tdata}), + .o_tlast (), + .o_tvalid (dest_o_tvalid), + .o_tready (dest_o_tready) + ); + + + //--------------------------------------------------------------------------- + // Input Logic + //--------------------------------------------------------------------------- + // + // When a packet comes in, we may have to do one of the following: + // 1) Lookup the TDEST using the EPID + // 2) Use the specified input TDEST + // 3) Use the NODE_ID as the TDEST (to return the packet) + // + //--------------------------------------------------------------------------- + + // The s_axis_chdr_hdr_valid signal indicates when TDATA and TID contain the + // header information for the current packet. + reg s_axis_chdr_hdr_valid = 1'b1; + + always @(posedge clk) begin + if (reset) begin + s_axis_chdr_hdr_valid <= 1'b1; + end else if (s_axis_chdr_tvalid & s_axis_chdr_tready) begin + s_axis_chdr_hdr_valid <= s_axis_chdr_tlast; + end + end + + // The dest_find_tready signal indicates if the find_fifo is ready or if the + // dest port of the dest_muax is ready, depending on which path will be used. + reg dest_find_tready; + + always @(*) begin + if (s_axis_chdr_hdr_valid) begin + case (s_axis_chdr_tid) + CHDR_MGMT_ROUTE_EPID: + dest_find_tready = find_tready; + CHDR_MGMT_ROUTE_TDEST: + dest_find_tready = dest_i_tready; + CHDR_MGMT_RETURN_TO_SRC: + dest_find_tready = dest_i_tready; + default: + dest_find_tready = dest_i_tready; // We should never get here + endcase + end else begin + dest_find_tready = 1'b1; + end + end + + // We can accept a transfer from the input CHDR stream only if the the packet + // gate and dest/find datapaths are ready. + assign s_axis_chdr_tready = s_axis_chdr_tvalid && + gate_i_tready && + dest_find_tready; + + // The chdr_header_stb signal indicates when we write data into the dest/find + // data path. This happens when we're accepting the header word of the packet + // into the packet gate. + wire chdr_header_stb = s_axis_chdr_tvalid && + s_axis_chdr_tready && + s_axis_chdr_hdr_valid; + + // ************************************************************************** + // WARNING: The logic below violates AXI-Stream by having a tready -> tvalid + // dependency To ensure no deadlocks, we must place FIFOs downstream + // of gate_i_*, find_* and dest_i_* + + // Here we decide if we need to do a lookup using the find_* path or if the + // destination is known and can be put directly on the dest_* path. + // + // Start a lookup request if the TID is CHDR_MGMT_ROUTE_EPID. + assign find_tdata = chdr_get_dst_epid(s_axis_chdr_tdata[63:0]); + assign find_tvalid = chdr_header_stb && + (s_axis_chdr_tid == CHDR_MGMT_ROUTE_EPID); + // Set TDEST directly if TID is CHDR_MGMT_ROUTE_TDEST or + // CHDR_MGMT_RETURN_TO_SRC. + assign dest_i_tdata = (s_axis_chdr_tid == CHDR_MGMT_ROUTE_TDEST) ? + s_axis_chdr_tdest : NODE_ID[DEST_W-1:0]; + assign dest_i_tkeep = 1'b1; + assign dest_i_tvalid = chdr_header_stb && + (s_axis_chdr_tid != CHDR_MGMT_ROUTE_EPID); + + // Input logic for axi_packet_gate + assign gate_i_tdata = s_axis_chdr_tdata; + assign gate_i_tlast = s_axis_chdr_tlast; + assign gate_i_tvalid = s_axis_chdr_tready && s_axis_chdr_tvalid; + + // + // ************************************************************************** + + + //--------------------------------------------------------------------------- + // Output Logic + //--------------------------------------------------------------------------- + // + // The destination for the packet (TDEST) must be valid before we allow the + // header of the packet to pass through. So the packet must be blocked until + // the output of the dest_o_* is valid. TDEST and TKEEP must remain valid + // until the end of the packet. + // + //--------------------------------------------------------------------------- + + assign m_axis_chdr_tdata = gate_o_tdata; + assign m_axis_chdr_tlast = gate_o_tlast; + assign m_axis_chdr_tdest = dest_o_tdata; + assign m_axis_chdr_tkeep = dest_o_tkeep; + assign m_axis_chdr_tvalid = gate_o_tvalid && dest_o_tvalid; + + assign gate_o_tready = m_axis_chdr_tvalid && m_axis_chdr_tready; + assign dest_o_tready = m_axis_chdr_tvalid && m_axis_chdr_tready && m_axis_chdr_tlast; + +endmodule + |