aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/packet_proc
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/packet_proc')
-rw-r--r--fpga/usrp3/lib/packet_proc/.gitignore3
-rw-r--r--fpga/usrp3/lib/packet_proc/Makefile.srcs19
-rw-r--r--fpga/usrp3/lib/packet_proc/arm_deframer.v119
-rw-r--r--fpga/usrp3/lib/packet_proc/arp_responder/arp_responder.vhd204
-rw-r--r--fpga/usrp3/lib/packet_proc/arp_responder/test/arp_responder_test.vhd185
-rw-r--r--fpga/usrp3/lib/packet_proc/axis_to_cvita.v32
-rw-r--r--fpga/usrp3/lib/packet_proc/chdr_chunker.v135
-rw-r--r--fpga/usrp3/lib/packet_proc/chdr_dechunker.v101
-rw-r--r--fpga/usrp3/lib/packet_proc/cvita_dest_lookup.v53
-rw-r--r--fpga/usrp3/lib/packet_proc/cvita_to_axis.v32
-rw-r--r--fpga/usrp3/lib/packet_proc/ip_hdr_checksum.v29
-rw-r--r--fpga/usrp3/lib/packet_proc/ip_hdr_checksum_tb.v43
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