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/packet_proc | |
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/packet_proc')
-rw-r--r-- | fpga/usrp3/lib/packet_proc/.gitignore | 3 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/Makefile.srcs | 19 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/arm_deframer.v | 119 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/arp_responder/arp_responder.vhd | 204 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/arp_responder/test/arp_responder_test.vhd | 185 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/axis_to_cvita.v | 32 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/chdr_chunker.v | 135 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/chdr_dechunker.v | 101 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/cvita_dest_lookup.v | 53 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/cvita_to_axis.v | 32 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/ip_hdr_checksum.v | 29 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/ip_hdr_checksum_tb.v | 43 |
12 files changed, 955 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/packet_proc/.gitignore b/fpga/usrp3/lib/packet_proc/.gitignore new file mode 100644 index 000000000..ca543057c --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/.gitignore @@ -0,0 +1,3 @@ +vita.txt +xo.txt +zpu.txt diff --git a/fpga/usrp3/lib/packet_proc/Makefile.srcs b/fpga/usrp3/lib/packet_proc/Makefile.srcs new file mode 100644 index 000000000..07a357965 --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/Makefile.srcs @@ -0,0 +1,19 @@ +# +# Copyright 2013 Ettus Research LLC +# Copyright 2016 Ettus Research, a National Instruments Company +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# + +################################################## +# Packet Processing Sources +################################################## +PACKET_PROC_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/packet_proc/, \ +chdr_chunker.v \ +chdr_dechunker.v \ +cvita_dest_lookup.v \ +ip_hdr_checksum.v \ +arm_deframer.v \ +arp_responder/arp_responder.vhd \ +)) + diff --git a/fpga/usrp3/lib/packet_proc/arm_deframer.v b/fpga/usrp3/lib/packet_proc/arm_deframer.v new file mode 100644 index 000000000..c4f77edf7 --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/arm_deframer.v @@ -0,0 +1,119 @@ +///////////////////////////////////////////////////////////////////// +// +// Copyright 2017 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: arm_deframer +// Description: +// Adds 6 bytes of Zeros at the beginning of every packet. It aligns the +// 64-bit words of the ethernet packet to be used later for classifying the +// packets. The module is based on xge64_to_axi64 and has lesser +// functionality. +// Note that the block only works for padding 6 bytes. +// +///////////////////////////////////////////////////////////////////// + +module arm_deframer ( + // Clocks and Reset + input wire clk, + input wire reset, + input wire clear, + // Slave AXI Interface + input wire [63:0] s_axis_tdata, + input wire [3:0] s_axis_tuser, //used as tkeep here + input wire s_axis_tlast, + input wire s_axis_tvalid, + output reg s_axis_tready, + // Master AXI Interface + output reg [63:0] m_axis_tdata, + output reg [3:0] m_axis_tuser, //used as tkeep here + output reg m_axis_tlast, + output reg m_axis_tvalid, + input wire m_axis_tready +); + // State Machine States + localparam START = 2'b00; + localparam BODY = 2'b01; + localparam EXTRA = 2'b10; + localparam PAD_BYTES = 3'b110; //6 bytes + wire new_line; + wire valid_beat; + reg [1:0] state = 2'b00, next_state=2'b00; + reg [47:0] holding_reg; + reg [2:0] holding_user; + // New line will be created by padding 6 bytes if the valid bytes on the + // last line are greater than 2 bytes(3 to 7 bytes) or all 8 bytes are valid. + assign new_line = (s_axis_tuser[2:0] > 3'b010) || (s_axis_tuser[2:0] == 3'b000); + assign valid_beat = s_axis_tvalid & m_axis_tready; + always @(posedge clk) begin + if (reset | clear) begin + state <= START; + end else begin + state <=next_state; + end + end + // holding last 48 bits from input tdata on every valid_beat. + always @(posedge clk)begin + if (s_axis_tvalid & s_axis_tready) begin + // Register the last 6 bytes of data for one cycle + holding_reg <= s_axis_tdata[63:16]; + // Register the tuser in case there is a new line + // tuser should be valid for one extra cycle in that case + holding_user <= s_axis_tuser[2:0]; + end + end + // Outputs + always @(*) begin + m_axis_tdata = 64'b0; + m_axis_tvalid = 1'b0; + m_axis_tlast = 1'b0; + m_axis_tuser = 4'b0; + s_axis_tready = 1'b1; + case (state) + START : begin + // Pad with 6 bytes of Zeros at the beginning of the packet + // Shift the first 2 bytes to the end + m_axis_tdata = {s_axis_tdata[15:0], 48'b0}; + m_axis_tvalid = s_axis_tvalid; + m_axis_tlast = s_axis_tlast; + m_axis_tuser = 4'b0; + s_axis_tready = m_axis_tready; + if(valid_beat) next_state = BODY; + else next_state = START; + end + BODY : begin + // Shift the remaining packet by 6 bytes. + // Here we're using register version of data and tvalid. + m_axis_tdata = {s_axis_tdata[15:0], holding_reg}; + m_axis_tvalid = s_axis_tvalid; + m_axis_tlast = new_line? 1'b0: s_axis_tvalid & s_axis_tlast; + // Modify the tuser according to the new packet i.e. add 6 to it. + m_axis_tuser = (new_line & s_axis_tlast) ? 4'b0: {1'b0, s_axis_tuser[2:0] + PAD_BYTES}; + s_axis_tready = m_axis_tready; + if (valid_beat & s_axis_tlast) next_state = new_line ? EXTRA : START; + else next_state = BODY; + end + EXTRA : begin + m_axis_tdata = {16'b0, holding_reg}; + m_axis_tvalid = 1'b1; + m_axis_tlast = 1'b1; + // Modify the tuser according to the new shifted packet i.e. add 6 to it. + m_axis_tuser = {1'b0, holding_user + PAD_BYTES}; + // We need to hold off any comming upstream data i.e not ready until + // downstream done consuming this data + s_axis_tready = 1'b0; + if (m_axis_tready) next_state = START; + else next_state = EXTRA; + end + default : begin + m_axis_tdata = 64'b0; + m_axis_tvalid = 1'b0; + m_axis_tlast = 1'b0; + m_axis_tuser = 4'b0; + s_axis_tready = 1'b1; + next_state = START; + end + endcase + end +endmodule // arm_deframer diff --git a/fpga/usrp3/lib/packet_proc/arp_responder/arp_responder.vhd b/fpga/usrp3/lib/packet_proc/arp_responder/arp_responder.vhd new file mode 100644 index 000000000..8481132c6 --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/arp_responder/arp_responder.vhd @@ -0,0 +1,204 @@ +-- +-- Copyright 2019 Ettus Research, A National Instruments brand +-- +-- SPDX-License-Identifier: LGPL-3.0 +-- +-- Module: arp_responder +-- Description: Processing IP to send replies for ARP frames (for IPv4) +-- arp_responder checks the incoming ARP frame against the input port ip_addr, +-- and if the frame is a request for this module's ip_addr, the module will +-- format an ARP reply and send it on the outgoing AXI-S interface. +-- +-- mac_addr and ip_addr must be kept stable for this module to function. They +-- are not registered within the IP. +-- +-- s_axis_tuser indicates there is an error in the packet, and it should be discarded + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity arp_responder is +port ( + aclk : in std_logic; + aresetn : in std_logic; + mac_addr : in std_logic_vector(47 downto 0); + ip_addr : in std_logic_vector(31 downto 0); + s_axis_tdata : in std_logic_vector(63 downto 0); + s_axis_tvalid : in std_logic; + s_axis_tready : out std_logic; + s_axis_tkeep : in std_logic_vector(7 downto 0); + s_axis_tlast : in std_logic; + s_axis_tuser : in std_logic; + m_axis_tdata : out std_logic_vector(63 downto 0); + m_axis_tvalid : out std_logic; + m_axis_tready : in std_logic; + m_axis_tkeep : out std_logic_vector(7 downto 0); + m_axis_tlast : out std_logic; + m_axis_tuser : out std_logic +); +end arp_responder; + +architecture arch of arp_responder is + type pkt_state_t is (PKT_IDLE, PKT_RECV, PKT_SEND, PKT_DROP); + signal pkt_state : pkt_state_t; + signal pkt_recv_count : unsigned(3 downto 0); + signal pkt_send_count : unsigned(3 downto 0); + + --All of these are LSB-0 for bits, but first byte transmitted is byte 0 + -- In ChipScope, bytes will appear swapped versus typical diagrams + signal src_mac_be : std_logic_vector(47 downto 0); + signal sender_hw_addr_be : std_logic_vector(47 downto 0); + signal sender_protocol_addr_be : std_logic_vector(31 downto 0); + signal target_protocol_addr_be : std_logic_vector(31 downto 0); + signal ip_addr_be : std_logic_vector(31 downto 0); +begin + m_axis_tuser <= '0'; + m_axis_tvalid <= '1' when (pkt_state = PKT_SEND) else '0'; + ip_addr_be <= ip_addr(7 downto 0) & ip_addr(15 downto 8) & + ip_addr(23 downto 16) & ip_addr(31 downto 24); + + s_axis_tready <= '1' when (pkt_state = PKT_IDLE) or (pkt_state = PKT_RECV) or (pkt_state = PKT_DROP) + else '0'; + + tx_reply : process (src_mac_be, mac_addr, ip_addr, sender_hw_addr_be, + sender_protocol_addr_be, pkt_send_count) + begin + m_axis_tdata <= (others => 'X'); + m_axis_tkeep <= (others => '1'); + m_axis_tlast <= '0'; + case (to_integer(pkt_send_count)) is + when 0 => + m_axis_tdata(47 downto 0) <= src_mac_be; + m_axis_tdata(63 downto 48) <= mac_addr(39 downto 32) & mac_addr(47 downto 40); + m_axis_tkeep <= X"FF"; + m_axis_tlast <= '0'; + when 1 => + m_axis_tdata(31 downto 0) <= mac_addr(7 downto 0) & mac_addr(15 downto 8) & + mac_addr(23 downto 16) & mac_addr(31 downto 24); + m_axis_tdata(47 downto 32) <= X"0608"; + m_axis_tdata(63 downto 48) <= X"0100"; + m_axis_tkeep <= X"FF"; + m_axis_tlast <= '0'; + when 2 => + m_axis_tdata(15 downto 0) <= X"0008"; --PTYPE + m_axis_tdata(23 downto 16) <= X"06"; --HLEN + m_axis_tdata(31 downto 24) <= X"04"; --PLEN + m_axis_tdata(47 downto 32) <= X"0200"; --OPER + m_axis_tdata(63 downto 48) <= mac_addr(39 downto 32) & mac_addr(47 downto 40); --SHA + m_axis_tkeep <= X"FF"; + m_axis_tlast <= '0'; + when 3 => + m_axis_tdata(31 downto 0) <= mac_addr(7 downto 0) & mac_addr(15 downto 8) & + mac_addr(23 downto 16) & mac_addr(31 downto 24); --SHA + m_axis_tdata(63 downto 32) <= ip_addr(7 downto 0) & ip_addr(15 downto 8) & + ip_addr(23 downto 16) & ip_addr(31 downto 24); --SPA + m_axis_tkeep <= X"FF"; + m_axis_tlast <= '0'; + when 4 => + m_axis_tdata(47 downto 0) <= sender_hw_addr_be; --THA + m_axis_tdata(63 downto 48) <= sender_protocol_addr_be(15 downto 0); --TPA + m_axis_tkeep <= X"FF"; + m_axis_tlast <= '0'; + when 5 => + m_axis_tdata(15 downto 0) <= sender_protocol_addr_be(31 downto 16); --TPA + m_axis_tdata(63 downto 16) <= (others => '0'); + m_axis_tkeep <= X"03"; + m_axis_tlast <= '1'; + when others => + null; + end case; + end process; + + process (aclk) + variable pkt_nonmatch : boolean := false; + begin + if rising_edge(aclk) then + case (pkt_state) is + when PKT_IDLE => + if (s_axis_tvalid = '1') and (s_axis_tlast = '0') and (s_axis_tuser = '0') then + pkt_state <= PKT_RECV; + pkt_recv_count <= to_unsigned(1, pkt_recv_count'length); + src_mac_be(15 downto 0) <= s_axis_tdata(63 downto 48); + end if; + when PKT_RECV => + pkt_nonmatch := false; + + pkt_send_count <= to_unsigned(0, pkt_send_count'length); + + if (s_axis_tvalid = '1') and (s_axis_tuser = '1') then + pkt_nonmatch := true; + elsif (s_axis_tvalid = '1') and (s_axis_tuser = '0') then + if (to_integer(pkt_recv_count) < 7) then + pkt_recv_count <= pkt_recv_count + 1; + end if; + + case (to_integer(pkt_recv_count)) is + when 1 => + src_mac_be(47 downto 16) <= s_axis_tdata(31 downto 0); + if (s_axis_tdata(47 downto 32) /= X"0608") or --eth_type + (s_axis_tdata(63 downto 48) /= X"0100") or --HTYPE + (s_axis_tlast = '1') then + pkt_nonmatch := true; + end if; + when 2 => + sender_hw_addr_be(15 downto 0) <= s_axis_tdata(63 downto 48); + if (s_axis_tdata(15 downto 0) /= X"0008") or --PTYPE + (s_axis_tdata(23 downto 16) /= X"06") or --HLEN + (s_axis_tdata(31 downto 24) /= X"04") or --PLEN + (s_axis_tdata(47 downto 32) /= X"0100") or --OPER + (s_axis_tlast = '1') then + pkt_nonmatch := true; + end if; + when 3 => + sender_hw_addr_be(47 downto 16) <= s_axis_tdata(31 downto 0); + sender_protocol_addr_be <= s_axis_tdata(63 downto 32); + if (s_axis_tlast = '1') then + pkt_nonmatch := true; + end if; + when 4 => + --THA = s_axis_tdata(47 downto 0) + target_protocol_addr_be(15 downto 0) <= s_axis_tdata(63 downto 48); + if (s_axis_tdata(63 downto 48) /= ip_addr_be(15 downto 0)) or + (s_axis_tlast = '1') then + pkt_nonmatch := true; + end if; + when 5 => + target_protocol_addr_be(31 downto 16) <= s_axis_tdata(15 downto 0); + if (s_axis_tdata(15 downto 0) /= ip_addr_be(31 downto 16)) then + pkt_nonmatch := true; + end if; + when others => + null; + end case; + end if; + if (pkt_nonmatch) then + if (s_axis_tlast = '1') then + pkt_state <= PKT_IDLE; + else + pkt_state <= PKT_DROP; + end if; + elsif (s_axis_tlast = '1') then + pkt_state <= PKT_SEND; + end if; + when PKT_SEND => + if (m_axis_tready = '1') then + pkt_send_count <= pkt_send_count + 1; + + if (pkt_send_count = 5) then + pkt_state <= PKT_IDLE; + end if; + end if; + when PKT_DROP => + if (s_axis_tvalid = '1') and (s_axis_tlast = '1') then + pkt_state <= PKT_IDLE; + end if; + end case; + + if aresetn = '0' then + pkt_state <= PKT_IDLE; + end if; + end if; + end process; +end arch; + diff --git a/fpga/usrp3/lib/packet_proc/arp_responder/test/arp_responder_test.vhd b/fpga/usrp3/lib/packet_proc/arp_responder/test/arp_responder_test.vhd new file mode 100644 index 000000000..ef2e62980 --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/arp_responder/test/arp_responder_test.vhd @@ -0,0 +1,185 @@ +-- +-- Copyright 2019 Ettus Research, A National Instruments brand +-- +-- SPDX-License-Identifier: LGPL-3.0 +-- +-- Module: arp_responder_test +-- Description: Simulation module to check the arp_responder IP +-- Sends a request to the arp_responder and checks for the expected reply + +library ieee; +use ieee.std_logic_1164.all; + +library work; +use work.arp_responder; + +entity arp_responder_test is +end arp_responder_test; + +architecture sim of arp_responder_test is + signal test_fail : boolean := false; + signal aclk : std_logic := '0'; + signal aresetn : std_logic; + signal mac_addr : std_logic_vector(47 downto 0) := X"017136E7BE02"; + signal ip_addr : std_logic_vector(31 downto 0) := X"04030201"; + signal s_axis_tdata : std_logic_vector(63 downto 0); + signal s_axis_tvalid : std_logic; + signal s_axis_tready : std_logic; + signal s_axis_tkeep : std_logic_vector(7 downto 0); + signal s_axis_tlast : std_logic; + signal s_axis_tuser : std_logic; + signal m_axis_tdata : std_logic_vector(63 downto 0); + signal m_axis_tvalid : std_logic; + signal m_axis_tready : std_logic; + signal m_axis_tkeep : std_logic_vector(7 downto 0); + signal m_axis_tlast : std_logic; + signal m_axis_tuser : std_logic; + + constant HALFCYCLE : time := 4 ns; + constant CYCLE : time := 2*HALFCYCLE; + constant ARP_REQUEST_VECTOR : std_logic_vector(64*8-1 downto 0) := + X"0000000000000000" & --Padding + X"0000000000000000" & --Padding + X"000000000000" & --Packet filler + X"04030201" & -- + X"000000000000" & + X"020B010A" & + X"00D00D010101" & + X"0100" & + X"04" & + X"06" & + X"0008" & + X"0100" & + X"0608" & + X"00D00D010101" & + X"FFFFFFFFFFFF"; + constant ARP_REPLY_VECTOR : std_logic_vector(64*8-1 downto 0) := + X"0000000000000000" & --Padding + X"0000000000000000" & --Padding + X"000000000000" & --Packet filler + X"020B010A" & + X"00D00D010101" & + X"04030201" & -- + X"017136E7BE02" & + X"0200" & + X"04" & + X"06" & + X"0008" & + X"0100" & + X"0608" & + X"017136E7BE02" & + X"00D00D010101"; + --Dest --6 + --Src --6 + --Ethertype --2 + --HTYPE = 0x0001 --2 + --PTYPE = 0x0800 --2 + --HLEN = 0x06 --1 + --PLEN = 0x04 --1 + --OPER = 0x0001 --2 + --SHA = --6 + --SPA = --4 + --THA = --6 + --TPA = --4 + --Need to check... + -- ARP request to us + -- ARP request not to us + -- Malformed packet +begin + + process + begin + wait for HALFCYCLE; + aclk <= not aclk; + end process; + + process + begin + wait for CYCLE; + aresetn <= '0'; + wait for 3*CYCLE; + aresetn <= '1'; + s_axis_tvalid <= '0'; + s_axis_tkeep <= X"00"; + s_axis_tlast <= '0'; + s_axis_tuser <= '0'; + m_axis_tready <= '0'; + wait for CYCLE; + for i in 0 to 7 loop + s_axis_tdata <= ARP_REQUEST_VECTOR(64*i+63 downto 64*i); + s_axis_tkeep <= X"FF"; + s_axis_tvalid <= '1'; + if (i = 7) then + s_axis_tlast <= '1'; + else + s_axis_tlast <= '0'; + end if; + if (i >= 3) then + s_axis_tuser <= '1'; + else + s_axis_tuser <= '0'; + end if; + wait for CYCLE; + s_axis_tvalid <= '0'; + wait for 7*CYCLE; + --wait until s_axis_tready = '1'; + end loop; + wait for CYCLE; + s_axis_tvalid <= '0'; + s_axis_tuser <= '0'; + wait for CYCLE; + for i in 0 to 7 loop + s_axis_tdata <= ARP_REQUEST_VECTOR(64*i+63 downto 64*i); + s_axis_tkeep <= X"FF"; + s_axis_tvalid <= '1'; + if (i = 7) then + s_axis_tlast <= '1'; + else + s_axis_tlast <= '0'; + end if; + wait for CYCLE; + s_axis_tvalid <= '0'; + wait for 7*CYCLE; + --wait until s_axis_tready = '1'; + end loop; + wait for CYCLE; + s_axis_tvalid <= '0'; + wait for CYCLE; + for i in 0 to 7 loop + m_axis_tready <= '1'; + if (m_axis_tdata /= ARP_REPLY_VECTOR(64*i+63 downto 64*i)) then + test_fail <= true; + report "Reply vector mismatch"; + end if; + wait for CYCLE; + m_axis_tready <= '0'; + wait for 7*CYCLE; + end loop; + wait for CYCLE; + if (test_fail) then + report "Test FAILED" severity failure; + else + report "PASS: End of test" severity failure; + end if; + end process; + +dut : entity arp_responder +port map ( + aclk => aclk, + aresetn => aresetn, + mac_addr => mac_addr, + ip_addr => ip_addr, + s_axis_tdata => s_axis_tdata, + s_axis_tvalid => s_axis_tvalid, + s_axis_tready => s_axis_tready, + s_axis_tkeep => s_axis_tkeep, + s_axis_tlast => s_axis_tlast, + s_axis_tuser => s_axis_tuser, + m_axis_tdata => m_axis_tdata, + m_axis_tvalid => m_axis_tvalid, + m_axis_tready => m_axis_tready, + m_axis_tkeep => m_axis_tkeep, + m_axis_tlast => m_axis_tlast, + m_axis_tuser => m_axis_tuser +); +end sim; diff --git a/fpga/usrp3/lib/packet_proc/axis_to_cvita.v b/fpga/usrp3/lib/packet_proc/axis_to_cvita.v new file mode 100644 index 000000000..e2f0eed66 --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/axis_to_cvita.v @@ -0,0 +1,32 @@ +// +// Copyright 2017 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +`default_nettype none + +module axis_to_cvita +( + input wire clk, + + input wire [63:0] s_axis_tdata, + input wire s_axis_tlast, + input wire s_axis_tvalid, + output wire s_axis_tready, + + output wire [63:0] o_tdata, + output wire o_tlast, + output wire o_tvalid, + input wire o_tready +); + + assign s_axis_tready = o_tready; + + assign o_tdata = {s_axis_tdata[31:0], s_axis_tdata[63:32]}; + assign o_tlast = s_axis_tlast; + assign o_tvalid = s_axis_tvalid; + +endmodule // axis_to_cvita + +`default_nettype wire + diff --git a/fpga/usrp3/lib/packet_proc/chdr_chunker.v b/fpga/usrp3/lib/packet_proc/chdr_chunker.v new file mode 100644 index 000000000..434919466 --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/chdr_chunker.v @@ -0,0 +1,135 @@ +// +// Copyright 2013 Ettus Research LLC +// Copyright 2018 Ettus Research, a National Instruments Company +// Copyright 2019 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +// Quantize chdr packets to a configurable quantum value. o_tlast and +// i_tready will be held off until the entire quantized packet is xferred. +// If quantum is changed, it is the responsibility of the client to clear +// this module. error is asserted if a packet is larger than the quantum +// error can be reset by asserting reset or clear. + +`default_nettype none +module chdr_chunker # ( + parameter PAD_VALUE = 64'hFFFFFFFF_FFFFFFFF, + HOLD_ERROR = 1'b1 // If high, hold error until reset, else pulse +) ( + input wire clk, + input wire reset, + input wire clear, + input wire [15:0] frame_size, + + input wire [63:0] i_tdata, + input wire i_tlast, + input wire i_tvalid, + output reg i_tready, + + output wire [63:0] o_tdata, + output wire o_tlast, + output reg o_tvalid, + input wire o_tready, + + output wire error +); + + localparam ST_HEADER = 2'd0; + localparam ST_DATA = 2'd1; + localparam ST_PADDING = 2'd2; + localparam ST_ERROR = 2'd3; + + reg [1:0] state; + reg [15:0] frame_rem; + + // axi_len = ceil(length / 8) + wire [15:0] chdr_len_ceil = i_tdata[31:16] + 16'd7; + wire [15:0] axi_len = {3'b000, chdr_len_ceil[15:3]}; + + always @(posedge clk) begin + if (reset | clear) begin + state <= ST_HEADER; + frame_rem <= 16'd0; + end else if ((state == ST_ERROR) & i_tlast & i_tvalid & !HOLD_ERROR) begin + state <= ST_HEADER; + frame_rem <= 16'd0; + end else if (o_tready) begin + case (state) + ST_HEADER: begin + if (i_tvalid) begin + if ((axi_len > frame_size) | (axi_len == 16'd0)) + state <= ST_ERROR; + else if (i_tlast) + state <= ST_PADDING; + else + state <= ST_DATA; + + frame_rem <= frame_size - 16'd1; + end + end + + ST_DATA: begin + if (i_tvalid) begin + if (i_tlast) begin + state <= o_tlast ? ST_HEADER : ST_PADDING; + frame_rem <= o_tlast ? 16'd0 : (frame_rem - 16'd1); + end else begin + state <= ST_DATA; + frame_rem <= frame_rem - 16'd1; + end + end + end + + ST_PADDING: begin + if (o_tlast) begin + state <= ST_HEADER; + frame_rem <= 16'd0; + end else begin + state <= ST_PADDING; + frame_rem <= frame_rem - 16'd1; + end + end + + endcase + end + end + + always @(*) begin + case (state) + ST_HEADER: begin + i_tready = o_tready; + o_tvalid = (axi_len <= frame_size) & (axi_len > 16'd0) & i_tvalid; + end + + ST_DATA: begin + i_tready = o_tready; + o_tvalid = i_tvalid; + end + + ST_PADDING: begin + i_tready = 1'b0; + o_tvalid = 1'b1; + end + + ST_ERROR: begin + i_tready = 1'b1; + o_tvalid = 1'b0; + end + + default: begin + i_tready = 1'b0; + o_tvalid = 1'b0; + end + endcase + end + + assign o_tlast = (frame_rem != 16'd0) ? (frame_rem == 16'd1) : (axi_len == 16'd1); + assign o_tdata = (state == ST_PADDING) ? PAD_VALUE : i_tdata; + + assign error = (state == ST_ERROR); + +endmodule // chdr_chunker + +`default_nettype wire + diff --git a/fpga/usrp3/lib/packet_proc/chdr_dechunker.v b/fpga/usrp3/lib/packet_proc/chdr_dechunker.v new file mode 100644 index 000000000..3cae23fc6 --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/chdr_dechunker.v @@ -0,0 +1,101 @@ +// +// Copyright 2013 Ettus Research LLC +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + + +module chdr_dechunker # ( + parameter PAD_VALUE = 64'hFFFFFFFF_FFFFFFFF +) ( + input clk, + input reset, + input clear, + input [15:0] frame_size, + + input [63:0] i_tdata, + input i_tvalid, + output i_tready, + + output [63:0] o_tdata, + output o_tlast, + output o_tvalid, + input o_tready, + + output error +); + + localparam ST_HEADER = 2'd0; + localparam ST_DATA = 2'd1; + localparam ST_PADDING = 2'd2; + localparam ST_ERROR = 2'd3; + + reg [1:0] state; + reg [15:0] frame_rem, pkt_rem; + wire i_tlast; + + // axi_len = ceil(length / 8) + wire [15:0] cvita_len_ceil = i_tdata[31:16] + 7; + wire [15:0] axi_len = {3'b000, cvita_len_ceil[15:3]}; + + always @(posedge clk) begin + if (reset | clear) begin + state <= ST_HEADER; + frame_rem <= 16'd0; + pkt_rem <= 16'd0; + end else if (i_tvalid & i_tready) begin + case (state) + ST_HEADER: begin + if (axi_len > frame_size) + state <= ST_ERROR; + else if (~o_tlast) + state <= ST_DATA; + else + state <= ST_PADDING; + + frame_rem <= frame_size - 16'd1; + pkt_rem <= axi_len - 16'd1; + end + + ST_DATA: begin + if (o_tlast) begin + state <= i_tlast ? ST_HEADER : ST_PADDING; + pkt_rem <= 16'd0; + end else begin + state <= ST_DATA; + pkt_rem <= pkt_rem - 16'd1; + end + frame_rem <= frame_rem - 16'd1; + end + + ST_PADDING: begin + if (i_tlast) begin + state <= ST_HEADER; + frame_rem <= 16'd0; + end else begin + state <= ST_PADDING; + frame_rem <= frame_rem - 16'd1; + end + end + + ST_ERROR: begin + // We never leave the error state. However, we can't reach it + // with PCIe if we configure our transport according to the + // NI-RIO configuration. + state <= ST_ERROR; + end + endcase + end + end + + assign i_tready = o_tready | (state == ST_PADDING); + assign i_tlast = (frame_rem == 16'd1); //Temp signal + + assign o_tvalid = i_tvalid & (state != ST_PADDING); + assign o_tlast = (pkt_rem != 0) ? (pkt_rem == 16'd1) : (axi_len == 16'd1); + assign o_tdata = i_tdata; + + assign error = (state == ST_ERROR); + +endmodule // chdr_dechunker diff --git a/fpga/usrp3/lib/packet_proc/cvita_dest_lookup.v b/fpga/usrp3/lib/packet_proc/cvita_dest_lookup.v new file mode 100644 index 000000000..c19fd8b1a --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/cvita_dest_lookup.v @@ -0,0 +1,53 @@ +// +// Copyright 2014 Ettus Research LLC +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Map the endpoint dest part of the SID in the CVITA header to a destination +// This destination (o_tdest) signal will be valid with o_tdata +// This only works with VALID CVITA frames + +module cvita_dest_lookup +#( + parameter DEST_WIDTH = 4 +) +( + input clk, input rst, + input set_stb, input [7:0] set_addr, input [DEST_WIDTH-1:0] set_data, + input [63:0] i_tdata, input i_tlast, input i_tvalid, output i_tready, + output [63:0] o_tdata, output o_tlast, output o_tvalid, input o_tready, + output [DEST_WIDTH-1:0] o_tdest +); + + reg [7:0] endpoint; + ram_2port #(.DWIDTH(DEST_WIDTH), .AWIDTH(8)) dest_lut + ( + .clka(clk), .ena(1'b1), .wea(set_stb), .addra(set_addr), .dia(set_data), .doa(), + .clkb(clk), .enb(1'b1), .web(1'b0), .addrb(endpoint), .dib(8'hff), .dob(o_tdest) + ); + + reg forward; + reg [1:0] count; + always @(posedge clk) begin + if (rst) begin + forward <= 1'b0; + count <= 2'b0; + end + else if (forward == 1'b0 && i_tvalid) begin + if (count == 2'b11) forward <= 1'b1; + endpoint <= i_tdata[7:0]; + count <= count + 1'b1; + end + else if (forward == 1'b1 && i_tvalid && i_tready && i_tlast) begin + forward <= 1'b0; + count <= 2'b0; + end + end + + assign o_tdata = i_tdata; + assign o_tlast = i_tlast; + assign o_tvalid = i_tvalid && forward; + assign i_tready = o_tready && forward; + +endmodule // cvita_dest_lookup diff --git a/fpga/usrp3/lib/packet_proc/cvita_to_axis.v b/fpga/usrp3/lib/packet_proc/cvita_to_axis.v new file mode 100644 index 000000000..9a346a059 --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/cvita_to_axis.v @@ -0,0 +1,32 @@ +// +// Copyright 2017 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +`default_nettype none + +module cvita_to_axis +( + input wire clk, + + input wire [63:0] i_tdata, + input wire i_tlast, + input wire i_tvalid, + output wire i_tready, + + output wire [63:0] m_axis_tdata, + output wire m_axis_tlast, + output wire m_axis_tvalid, + input wire m_axis_tready +); + + assign i_tready = m_axis_tready; + + assign m_axis_tdata = {i_tdata[31:0], i_tdata[63:32]}; + assign m_axis_tlast = i_tlast; + assign m_axis_tvalid = i_tvalid; + +endmodule // cvita_to_axis + +`default_nettype wire + diff --git a/fpga/usrp3/lib/packet_proc/ip_hdr_checksum.v b/fpga/usrp3/lib/packet_proc/ip_hdr_checksum.v new file mode 100644 index 000000000..7e2e0f88e --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/ip_hdr_checksum.v @@ -0,0 +1,29 @@ +// +// Copyright 2014 Ettus Research LLC +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Compute IP header checksum. 2 cycles of latency. +module ip_hdr_checksum + (input clk, input [159:0] in, output reg [15:0] out); + + wire [18:0] padded [0:9]; + reg [18:0] sum_a, sum_b; + + genvar i; + generate + for(i=0 ; i<10 ; i=i+1) + assign padded[i] = {3'b000,in[i*16+15:i*16]}; + endgenerate + + always @(posedge clk) sum_a = padded[0] + padded[1] + padded[2] + padded[3] + padded[4]; + always @(posedge clk) sum_b = padded[5] + padded[6] + padded[7] + padded[8] + padded[9]; + + wire [18:0] sum = sum_a + sum_b; + + always @(posedge clk) + out <= ~(sum[15:0] + {13'd0,sum[18:16]}); + + +endmodule // ip_hdr_checksum diff --git a/fpga/usrp3/lib/packet_proc/ip_hdr_checksum_tb.v b/fpga/usrp3/lib/packet_proc/ip_hdr_checksum_tb.v new file mode 100644 index 000000000..de52a0049 --- /dev/null +++ b/fpga/usrp3/lib/packet_proc/ip_hdr_checksum_tb.v @@ -0,0 +1,43 @@ +// +// Copyright 2013 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +module ip_hdr_checksum_tb(); + + initial $dumpfile("ip_hdr_checksum_tb.vcd"); + initial $dumpvars(0,ip_hdr_checksum_tb); + + reg clk; + + wire [159:0] in = { + 16'h4500, + 16'h0030, + 16'h4422, + 16'h4000, + 16'h8006, + 16'h0000, + 16'h8c7c, + 16'h19ac, + 16'hae24, + 16'h1e2b + }; + + wire [15:0] out; + ip_hdr_checksum ip_hdr_checksum + (.clk(clk), + .in(in), + .out(out)); + + initial + begin + clk <= 0; + #100 clk <= 1; + #100 clk <= 0; + #100 clk <= 1; + #100 $display("Computed 0x%x, should be 0x442e", out); + #100 $finish; + end + +endmodule // ip_hdr_checksum_tb |