aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/packet_proc_200
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/packet_proc_200')
-rw-r--r--fpga/usrp3/lib/packet_proc_200/Makefile.srcs14
-rw-r--r--fpga/usrp3/lib/packet_proc_200/cvita_dest_lookup_legacy.v53
-rw-r--r--fpga/usrp3/lib/packet_proc_200/source_flow_control_legacy.v150
-rw-r--r--fpga/usrp3/lib/packet_proc_200/source_flow_control_legacy_tb.v254
4 files changed, 471 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/packet_proc_200/Makefile.srcs b/fpga/usrp3/lib/packet_proc_200/Makefile.srcs
new file mode 100644
index 000000000..3f0834df9
--- /dev/null
+++ b/fpga/usrp3/lib/packet_proc_200/Makefile.srcs
@@ -0,0 +1,14 @@
+#
+# 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_200_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/packet_proc_200/, \
+cvita_dest_lookup_legacy.v \
+source_flow_control_legacy.v \
+))
diff --git a/fpga/usrp3/lib/packet_proc_200/cvita_dest_lookup_legacy.v b/fpga/usrp3/lib/packet_proc_200/cvita_dest_lookup_legacy.v
new file mode 100644
index 000000000..17954baaa
--- /dev/null
+++ b/fpga/usrp3/lib/packet_proc_200/cvita_dest_lookup_legacy.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_legacy
+#(
+ 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[23:16];
+ 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_legacy
diff --git a/fpga/usrp3/lib/packet_proc_200/source_flow_control_legacy.v b/fpga/usrp3/lib/packet_proc_200/source_flow_control_legacy.v
new file mode 100644
index 000000000..46906f97d
--- /dev/null
+++ b/fpga/usrp3/lib/packet_proc_200/source_flow_control_legacy.v
@@ -0,0 +1,150 @@
+//
+// Copyright 2014-2016 Ettus Research
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// This block passes the in_* AXI port to the out_* AXI port only when it has
+// enough flow control credits. Data is held when there are not enough credits.
+// Credits are replenished with extension context packets which update the
+// last_consumed packet register. Max credits are controlled by settings regs.
+// The 2nd line of the packet contains the sequence number in the low 12 bits.
+// These packets should not have a time value, but if they do it will be ignored.
+
+module source_flow_control_legacy #(
+ parameter BASE=0
+) (
+ input clk, input reset, input clear,
+ input set_stb, input [7:0] set_addr, input [31:0] set_data,
+ input [63:0] fc_tdata, input fc_tlast, input fc_tvalid, output fc_tready,
+ input [63:0] in_tdata, input in_tlast, input in_tvalid, output in_tready,
+ output [63:0] out_tdata, output out_tlast, output out_tvalid, input out_tready,
+ output busy
+);
+ reg [31:0] last_seqnum_consumed;
+ wire [31:0] window_size;
+ wire [31:0] go_until_seqnum = last_seqnum_consumed + window_size + 1;
+ reg [31:0] current_seqnum;
+ wire window_reset;
+ wire window_enable;
+
+ //Sets the size of the flow control window
+ setting_reg #(.my_addr(BASE)) sr_window_size
+ (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
+ .out(window_size),.changed());
+
+ //Setting to enable/disable the flow control window
+ //When this register is hit, the window will reset.
+ //As a part of the reset process, all FC blocked data upstream will be
+ //dropped by this module and it will reset to the SFC_HEAD head state.
+ //The reset sequence can take more than one cycle during which this
+ //module will hold off all flow control data.
+ setting_reg #(.my_addr(BASE+1), .width(1)) sr_window_enable
+ (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
+ .out(window_enable),.changed(window_reset));
+
+ reg go;
+ reg window_reseting;
+ reg [11:0] window_reset_cnt; //Counter to make reset tolerant to bubble cycles
+ reg [1:0] sfc_state;
+
+ always @(posedge clk) begin
+ if (reset | clear) begin
+ window_reseting <= 1'b0;
+ end else if (window_reset) begin //Reset start
+ window_reseting <= 1'b1;
+ window_reset_cnt <= 12'd0;
+ end else if (window_reseting & ~in_tvalid) begin //Reset end
+ window_reset_cnt <= window_reset_cnt + 12'd1;
+ window_reseting <= (window_reset_cnt == 12'hFFF);
+ end
+ end
+
+ localparam SFC_HEAD = 2'd0;
+ localparam SFC_TIME = 2'd1;
+ localparam SFC_BODY = 2'd2;
+ localparam SFC_DUMP = 2'd3;
+
+ always @(posedge clk)
+ if (reset | clear | window_reset) begin
+ last_seqnum_consumed <= 32'hFFFFFFFF;
+ sfc_state <= SFC_HEAD;
+ end else if (fc_tvalid & fc_tready)
+ case(sfc_state)
+ SFC_HEAD :
+ if(fc_tlast)
+ sfc_state <= SFC_HEAD; // Error. CHDR packet with only a header is an error.
+ else if(~fc_tdata[63]) // Is this NOT an extension context packet?
+ sfc_state <= SFC_DUMP; // Error. Only extension context packets should come in on this interface.
+ else if(fc_tdata[61]) // Does this packet have time?
+ sfc_state <= SFC_TIME;
+ else
+ sfc_state <= SFC_BODY;
+
+ SFC_TIME :
+ if(fc_tlast)
+ sfc_state <= SFC_HEAD; // Error, CHDR packet with only header and time is an error.
+ else
+ sfc_state <= SFC_BODY;
+
+ SFC_BODY :
+ begin
+ last_seqnum_consumed <= fc_tdata[31:0]; // Sequence number is in lower 32bits.
+ if(fc_tlast)
+ sfc_state <= SFC_HEAD;
+ else
+ sfc_state <= SFC_DUMP; // Error. Not expecting any more data in a CHDR packet.
+ end
+
+ SFC_DUMP : // shouldn't ever need to be here, this is an error condition
+ if(fc_tlast)
+ sfc_state <= SFC_HEAD;
+
+ endcase // case (sfc_state)
+
+ assign busy = window_reseting;
+ assign fc_tready = ~window_reseting; // Consume FC if not in reset
+ assign out_tdata = in_tdata; // CHDR data flows through combinatorially.
+ assign out_tlast = in_tlast;
+ assign in_tready = (go ? out_tready : 1'b0) | window_reseting;
+ assign out_tvalid = (go & ~window_reseting) ? in_tvalid : 1'b0;
+
+ //
+ // Each time we receive the end of an IF data packet increment the current_seqnum.
+ // We bravely assume that no packets go missing...or at least that they will be detected elsewhere
+ // and then handled appropriately.
+ // The SEQNUM needs to be initialized every time we start a new stream. In new_rx_framer this is done
+ // as a side effect of writing a new SID value to the setting reg.
+ //
+ // By incrementing current_seqnum on the last signal we get the nice effect that packet flow is
+ // always suspended between packets rather than within a packet.
+ //
+ always @(posedge clk)
+ if(reset | clear | window_reseting)
+ current_seqnum <= 32'd0;
+ else if (in_tvalid && in_tready && in_tlast)
+ current_seqnum <= current_seqnum + 32'd1;
+
+ always @(posedge clk)
+ if(reset | clear) begin
+ go <= 1'b0;
+ end else begin
+ if(~window_enable)
+ go <= 1'b1;
+ else
+ case(go)
+ 1'b0:
+ // This test assumes the host is well behaved in sending good numbers for packets consumed
+ // and that current_seqnum increments always by 1 only.
+ // This way wraps are dealt with without a large logic penalty.
+ if (in_tvalid & (go_until_seqnum - current_seqnum != 0))
+ go <= 1'b1;
+ //if(in_tvalid & (go_until_seqnum > current_seqnum)) // FIXME will need to handle wrap of 32-bit seqnum
+
+ 1'b1:
+ if(in_tvalid & in_tready & in_tlast)
+ go <= 1'b0;
+ endcase // case (go)
+ end
+
+endmodule // source_flow_control_legacy
diff --git a/fpga/usrp3/lib/packet_proc_200/source_flow_control_legacy_tb.v b/fpga/usrp3/lib/packet_proc_200/source_flow_control_legacy_tb.v
new file mode 100644
index 000000000..e8f7cccdf
--- /dev/null
+++ b/fpga/usrp3/lib/packet_proc_200/source_flow_control_legacy_tb.v
@@ -0,0 +1,254 @@
+//
+// Copyright 2016 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+`timescale 1ns/1ps
+
+module source_flow_control_legacy_tb();
+
+ reg clk = 0;
+ reg reset = 1;
+
+ always #10 clk = ~clk;
+
+ initial $dumpfile("source_flow_control_legacy_tb.vcd");
+ initial $dumpvars(0,source_flow_control_legacy_tb);
+
+ initial
+ begin
+ #1000 reset = 0;
+ #20000;
+ $finish;
+ end
+
+ reg [63:0] tdata;
+ wire [63:0] tdata_int;
+ reg tlast;
+ wire tlast_int;
+ reg tvalid = 1'b0;
+ wire tvalid_int;
+ wire tready, tready_int;
+
+ reg [63:0] fc_tdata;
+ reg fc_tlast, fc_tvalid;
+ wire fc_tready;
+
+ wire [63:0] out_tdata;
+ wire out_tlast, out_tready, out_tvalid;
+
+ wire [15:0] occ_in, occ_out;
+ reg set_stb = 0;
+ reg [7:0] set_addr;
+ reg [31:0] set_data;
+
+
+ task send_fc_packet;
+ input [31:0] seqnum;
+ input [31:0] sid;
+ input always_go;
+
+ begin
+ @(posedge clk);
+ fc_tlast <= 1'b0;
+ fc_tdata <= { 1'b1, 1'b0, 1'b0, 1'b0, 12'hABC, 16'd4, sid };
+ fc_tvalid <= 1;
+ @(posedge clk);
+ fc_tlast <= 1'b1;
+ //fc_tdata <= { 52'h0,seqnum };
+ fc_tdata <= { 31'h0,always_go, seqnum };
+ @(posedge clk);
+ fc_tvalid <= 0;
+ @(posedge clk);
+ end
+ endtask // send_packet
+
+ task send_packet;
+ input ec;
+ input timed;
+ input [11:0] seqnum;
+ input [31:0] sid;
+ input [63:0] vtime;
+ input [15:0] addr;
+ input [31:0] data;
+
+ begin
+ // Send a packet
+ @(posedge clk);
+ tlast <= 1'b0;
+ tdata <= { ec, 1'b0, timed, 1'b0, seqnum, timed ? 16'd6 : 16'd4, sid };
+ tvalid <= 1;
+ @(posedge clk);
+ if(timed)
+ begin
+ tdata <= vtime;
+ @(posedge clk);
+ end
+ tlast <= 1'b1;
+ tdata <= { 16'h0, addr, data };
+ @(posedge clk);
+ tlast <= 1'b0;
+ tvalid <= 0;
+ @(posedge clk);
+ end
+ endtask // send_packet
+
+ initial
+ begin
+ tvalid <= 1'b0;
+ while(reset)
+ @(posedge clk);
+ @(posedge clk);
+ // Set flow control window to be 2
+ set_stb <= 1;
+ set_addr <= 0;
+ set_data <= 2;
+ @(posedge clk);
+ set_stb <= 0;
+ // ExtContext. Time. Seq=0, SID=DEAD_6789, Time=10
+ send_packet(1'b1,1'b1,12'h0,32'hDEAD_6789,64'h10,16'hB,32'hF00D_1234);
+ send_packet(1'b1,1'b1,12'h1,32'hDEAD_6789,64'h20,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h2,32'hDEAD_6789,64'h30,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h3,32'hDEAD_6789,64'h30,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h4,32'hDEAD_6789,64'h30,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h5,32'hDEAD_6789,64'h30,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h6,32'hDEAD_6789,64'h30,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h7,32'hDEAD_6789,64'h30,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h8,32'hDEAD_6789,64'h30,16'hC,32'hABCD_4321);
+ #500;
+ // Consumed 2 packets
+ send_fc_packet(32'd1,32'h3,1'b0);
+ #300;
+ // Consumed 1 packet
+ send_fc_packet(32'd2,32'h3,1'b0);
+ #500;
+ // Consumed 2 packets
+ send_fc_packet(32'd4,32'h3,1'b0);
+ #400;
+ // Send same SEQ ID again to test it causes no changes.
+ send_fc_packet(32'd4,32'h3,1'b0);
+ #300;
+ // Consumed 1 packet
+ send_fc_packet(32'd5,32'h3,1'b0);
+ #500;
+ // Consumed 2 packets
+ send_fc_packet(32'd7,32'h3,1'b0);
+ #500;
+ send_packet(1'b1,1'b1,12'h9,32'hDEAD_6789,64'h30,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'hA,32'hDEAD_6789,64'h30,16'hC,32'hABCD_4321);
+ #300;
+ // Consumed 1 packet
+ send_fc_packet(32'd8,32'h3,1'b0);
+ //
+ // Now force internal sequence count to close to wrap value to test corner case
+ //
+ #100;
+ source_flow_control_legacy.current_seqnum <= 32'hFFFF_FFFC;
+ #100;
+ send_fc_packet(32'hFFFF_FFFA,32'h3,1'b0);
+ #100;
+ send_packet(1'b1,1'b1,12'hFFC,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ #200;
+ send_packet(1'b1,1'b1,12'hFFD,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'hFFE,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'hFFF,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h000,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h001,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h002,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ #200;
+ // Consumed 2 packets
+ send_fc_packet(32'hFFFF_FFFC,32'h3,1'b0);
+ #200;
+ // Consumed 2 packets
+ send_fc_packet(32'hFFFF_FFFE,32'h3,1'b0);
+ send_packet(1'b1,1'b1,12'h003,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h004,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ #200;
+ // Consumed 2 packets
+ send_fc_packet(32'h0,32'h3,1'b0);
+ #200;
+ // Consumed 2 packets
+ send_fc_packet(32'h2,32'h3,1'b0);
+ #500;
+ //
+ // Again force internal sequence count to close to wrap value to test new corner case
+ //
+ #100;
+ source_flow_control_legacy.current_seqnum <= 32'hFFFF_FFFC;
+ #100;
+ send_fc_packet(32'hFFFF_FFFA,32'h3,1'b0);
+ #100;
+ send_packet(1'b1,1'b1,12'hFFC,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ #200;
+ send_packet(1'b1,1'b1,12'hFFD,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'hFFE,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'hFFF,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h000,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h001,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h002,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ #200;
+ // Consumed 1 packets
+ send_fc_packet(32'hFFFF_FFFB,32'h3,1'b0);
+ #200;
+ // Consumed 1 packets
+ send_fc_packet(32'hFFFF_FFFC,32'h3,1'b0);
+ send_packet(1'b1,1'b1,12'h003,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ send_packet(1'b1,1'b1,12'h004,32'hDEAD_6789,64'h40,16'hC,32'hABCD_4321);
+ #200;
+ // Consumed 1 packets
+ send_fc_packet(32'hFFFF_FFFD,32'h3,1'b0);
+ #200;
+ // Consumed 1 packets
+ send_fc_packet(32'hFFFF_FFFE,32'h3,1'b0);
+ #200;
+ // Consumed 1 packets
+ send_fc_packet(32'hFFFF_FFFF,32'h3,1'b0);
+ #200;
+ // Consumed 1 packets
+ send_fc_packet(32'h0,32'h3,1'b0);
+ #200;
+ // Consumed 1 packets
+ send_fc_packet(32'h1,32'h3,1'b0);
+ #200;
+ // Consumed 1 packets
+ send_fc_packet(32'h2,32'h3,1'b0);
+ #500;
+
+
+
+
+ end
+
+ axi_fifo #(.WIDTH(65), .SIZE(10)) fifo_in
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata({tlast,tdata}), .i_tvalid(tvalid), .i_tready(tready),
+ .o_tdata({tlast_int,tdata_int}), .o_tvalid(tvalid_int), .o_tready(tready_int),
+ .occupied(occ_in));
+
+ source_flow_control_legacy source_flow_control_legacy
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
+ .fc_tdata(fc_tdata), .fc_tlast(fc_tlast), .fc_tvalid(fc_tvalid), .fc_tready(fc_tready),
+ .in_tdata(tdata_int), .in_tlast(tlast_int), .in_tvalid(tvalid_int), .in_tready(tready_int),
+ .out_tdata(out_tdata), .out_tlast(out_tlast), .out_tvalid(out_tvalid), .out_tready(out_tready)
+ );
+
+ wire [63:0] dump_tdata;
+ wire dump_tlast, dump_tvalid, dump_tready;
+
+ axi_fifo #(.WIDTH(65), .SIZE(10)) fifo_out
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata({out_tlast,out_tdata}), .i_tvalid(out_tvalid), .i_tready(out_tready),
+ .o_tdata({dump_tlast,dump_tdata}), .o_tvalid(dump_tvalid), .o_tready(dump_tready),
+ .occupied(occ_out));
+
+ assign dump_tready = 0;
+
+ always @(posedge clk)
+ if(out_tvalid & out_tready)
+ begin
+ $display("%x",out_tdata);
+ if(out_tlast)
+ $display("TLAST");
+ end
+endmodule // source_flow_control_legacy_tb