diff options
Diffstat (limited to 'fpga/usrp3/lib')
-rw-r--r-- | fpga/usrp3/lib/io_port2/Makefile.srcs | 1 | ||||
-rw-r--r-- | fpga/usrp3/lib/io_port2/pcie_basic_regs.v | 9 | ||||
-rw-r--r-- | fpga/usrp3/lib/io_port2/pcie_dma_ctrl.v | 17 | ||||
-rw-r--r-- | fpga/usrp3/lib/io_port2/pcie_lossy_samp_gate.v | 26 | ||||
-rw-r--r-- | fpga/usrp3/lib/packet_proc/eth_dispatch.v | 937 | ||||
-rw-r--r-- | fpga/usrp3/lib/vita/new_tx_control.v | 40 |
6 files changed, 531 insertions, 499 deletions
diff --git a/fpga/usrp3/lib/io_port2/Makefile.srcs b/fpga/usrp3/lib/io_port2/Makefile.srcs index 507b8895a..4ee23a7b4 100644 --- a/fpga/usrp3/lib/io_port2/Makefile.srcs +++ b/fpga/usrp3/lib/io_port2/Makefile.srcs @@ -16,4 +16,5 @@ IOPORT2_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/io_port2/, \ ./pcie_basic_regs.v \ ./pcie_dma_ctrl.v \ ./data_swapper_64.v \ +./pcie_lossy_samp_gate.v \ )) diff --git a/fpga/usrp3/lib/io_port2/pcie_basic_regs.v b/fpga/usrp3/lib/io_port2/pcie_basic_regs.v index e3790e81c..e360b6812 100644 --- a/fpga/usrp3/lib/io_port2/pcie_basic_regs.v +++ b/fpga/usrp3/lib/io_port2/pcie_basic_regs.v @@ -3,7 +3,10 @@ // -module pcie_basic_regs ( +module pcie_basic_regs #( + parameter SIGNATURE = 32'h0, + parameter CLK_FREQ = 32'h0 +) ( input clk, input reset, @@ -16,8 +19,8 @@ module pcie_basic_regs ( input [31:0] misc_status ); - localparam PCIE_FPGA_SIG_VAL = 32'h58333030; //X300 (ASCII) - localparam PCIE_FPGA_COUNTER_FREQ = 32'h0A6E49C0; //175MHz + localparam PCIE_FPGA_SIG_VAL = SIGNATURE; + localparam PCIE_FPGA_COUNTER_FREQ = CLK_FREQ; localparam PCIE_REG_ADDR_MASK = 20'h001FF; diff --git a/fpga/usrp3/lib/io_port2/pcie_dma_ctrl.v b/fpga/usrp3/lib/io_port2/pcie_dma_ctrl.v index 6809939af..9e0f05040 100644 --- a/fpga/usrp3/lib/io_port2/pcie_dma_ctrl.v +++ b/fpga/usrp3/lib/io_port2/pcie_dma_ctrl.v @@ -35,12 +35,14 @@ module pcie_dma_ctrl #( output rego_tvalid, input rego_tready, + output reg [NUM_STREAMS-1:0] set_enabled, output reg [NUM_STREAMS-1:0] set_clear, output [(NUM_STREAMS*FRAME_SIZE_W)-1:0] set_frame_size, output [(NUM_STREAMS*3)-1:0] swap_lanes, input [NUM_STREAMS-1:0] packet_stb, input [NUM_STREAMS-1:0] sample_stb, + input [NUM_STREAMS-1:0] stream_busy, input [NUM_STREAMS-1:0] stream_err, input [ROUTER_SID_W-1:0] rtr_sid, @@ -48,7 +50,7 @@ module pcie_dma_ctrl #( ); localparam DMA_REG_GRP_W = 4; - localparam DMA_CTRL_STATUS_REG = 4'h0; //[RW] R: Stream Error, W: Reset stream + localparam DMA_CTRL_STATUS_REG = 4'h0; //[RW] R: Stream Status, W: Stream Control localparam DMA_FSIZE_REG = 4'h4; //[RW] R: Frame Size, W: Frame Size localparam DMA_SAMP_CNT_REG = 4'h8; //[RW] R: Sample Count, W: Reset Count to 0 localparam DMA_PKT_CNT_REG = 4'hC; //[RW] R: Packet Count, W: Reset Count to 0 @@ -92,14 +94,15 @@ module pcie_dma_ctrl #( if (reset) begin frame_size_mem[i] <= DEFAULT_FSIZE; set_clear[i] <= 0; + set_enabled[i] <= 0; sw_buf_width_mem[i] <= 1; end else if (regi_tready & regi_tvalid & regi_wr) begin if (regi_addr == `GET_REG_OFFSET(DMA_CTRL_STATUS_REG, i)) begin - set_clear[i] <= regi_payload[0]; //DMA_CTRL_STATUS_REG[0] == Clear DMA queues + set_clear[i] <= regi_payload[0]; //DMA_CTRL_STATUS_REG[0] == Clear DMA queues + set_enabled[i] <= regi_payload[1]; //DMA_CTRL_STATUS_REG[1] == Enable DMA channel sw_buf_width_mem[i] <= regi_payload[4]; //DMA_CTRL_STATUS_REG[5:4] == SW Buffer Size (See note above) end else if (regi_addr == `GET_REG_OFFSET(DMA_FSIZE_REG, i)) begin frame_size_mem[i] <= regi_payload[FRAME_SIZE_W-1:0]; //DMA_FSIZE_REG[14:0] == DMA Frame size - set_clear[i] <= 1; end end else begin set_clear[i] <= 0; //set_clear should be "self-clearing" @@ -123,7 +126,7 @@ module pcie_dma_ctrl #( samp_count_mem[i] <= samp_count_mem[i] + 1; end end - end + end endgenerate //Readback @@ -131,14 +134,14 @@ module pcie_dma_ctrl #( (regi_addr[DMA_REG_GRP_W-1:0] == DMA_PKT_CNT_REG) ? pkt_count_mem[`EXTRACT_CHAN_NUM(regi_addr)] : ( (regi_addr[DMA_REG_GRP_W-1:0] == DMA_SAMP_CNT_REG) ? samp_count_mem[`EXTRACT_CHAN_NUM(regi_addr)] : ( (regi_addr[DMA_REG_GRP_W-1:0] == DMA_FSIZE_REG) ? frame_size_mem[`EXTRACT_CHAN_NUM(regi_addr)] : ( - (regi_addr[DMA_REG_GRP_W-1:0] == DMA_CTRL_STATUS_REG) ? {31'h0, stream_err[`EXTRACT_CHAN_NUM(regi_addr)]} : ( + (regi_addr[DMA_REG_GRP_W-1:0] == DMA_CTRL_STATUS_REG) ? {30'h0, stream_busy[`EXTRACT_CHAN_NUM(regi_addr)], stream_err[`EXTRACT_CHAN_NUM(regi_addr)]} : ( 32'hFFFFFFFF)))); assign rego_tvalid = regi_tvalid && regi_rd; assign regi_tready = rego_tready || (regi_tvalid && regi_wr); //Optional router - if (ENABLE_ROUTER == 1) begin + generate if (ENABLE_ROUTER == 1) begin pcie_pkt_route_specifier #( .BASE_ADDR((1<<ROUTER_SID_W) + REG_BASE_ADDR), .ADDR_MASK(20'hFFFFF^((1<<ROUTER_SID_W)-1)), .SID_WIDTH(ROUTER_SID_W), .DST_WIDTH(ROUTER_DST_W) @@ -147,7 +150,7 @@ module pcie_dma_ctrl #( .regi_tdata(regi_tdata), .regi_tvalid(regi_tvalid), .regi_tready(), .local_sid(rtr_sid), .fifo_dst(rtr_dst) ); - end + end endgenerate endmodule diff --git a/fpga/usrp3/lib/io_port2/pcie_lossy_samp_gate.v b/fpga/usrp3/lib/io_port2/pcie_lossy_samp_gate.v new file mode 100644 index 000000000..6f6b6377a --- /dev/null +++ b/fpga/usrp3/lib/io_port2/pcie_lossy_samp_gate.v @@ -0,0 +1,26 @@ +// +// Copyright 2013 Ettus Research LLC +// + + +module pcie_lossy_samp_gate +( + input [63:0] i_tdata, + input i_tvalid, + output i_tready, + + output [63:0] o_tdata, + output o_tvalid, + input o_tready, + + input drop, + output dropping +); + + assign o_tdata = i_tdata; + assign o_tvalid = i_tvalid & ~drop; + assign i_tready = o_tready | drop; + + assign dropping = drop & i_tvalid; + +endmodule // pcie_lossy_samp_gate diff --git a/fpga/usrp3/lib/packet_proc/eth_dispatch.v b/fpga/usrp3/lib/packet_proc/eth_dispatch.v index 7068d5a77..07f40d50e 100644 --- a/fpga/usrp3/lib/packet_proc/eth_dispatch.v +++ b/fpga/usrp3/lib/packet_proc/eth_dispatch.v @@ -11,7 +11,7 @@ // the vita port. // // If at the end of the headers we determine the packet should go to zpu, then we send an -// error indication on the out port, the rest of the packet to zpu and nothing on vita. +// error indication on the out port, the rest of the packet to zpu and nothing on vita. // If it should go to out, we send the error indication to zpu, the rest of the packet to out, // and nothing on vita. // @@ -40,148 +40,148 @@ module eth_dispatch #(parameter BASE=0) ( // Clocking and reset interface - input clk, - input reset, - input clear, + input clk, + input reset, + input clear, // Setting register interface - input set_stb, - input [15:0] set_addr, + input set_stb, + input [15:0] set_addr, input [31:0] set_data, // Input 68bit AXI-Stream interface (from MAC) - input [63:0] in_tdata, - input [3:0] in_tuser, - input in_tlast, - input in_tvalid, + input [63:0] in_tdata, + input [3:0] in_tuser, + input in_tlast, + input in_tvalid, output in_tready, // Output AXI-STream interface to VITA Radio Core output [63:0] vita_tdata, - output [3:0] vita_tuser, - output vita_tlast, - output vita_tvalid, + output [3:0] vita_tuser, + output vita_tlast, + output vita_tvalid, input vita_tready, // Output AXI-Stream interface to ZPU - output [63:0] zpu_tdata, - output [3:0] zpu_tuser, - output zpu_tlast, - output zpu_tvalid, + output [63:0] zpu_tdata, + output [3:0] zpu_tuser, + output zpu_tlast, + output zpu_tvalid, input zpu_tready, // Output AXI-Stream interface to cross-over MAC - output [63:0] xo_tdata, - output [3:0] xo_tuser, - output xo_tlast, - output xo_tvalid, + output [63:0] xo_tdata, + output [3:0] xo_tuser, + output xo_tlast, + output xo_tvalid, input xo_tready, // Debug output [2:0] debug_flags, output [31:0] debug ); - // - // State machine declarations - // - reg [2:0] state; - - localparam WAIT_PACKET = 0; - localparam READ_HEADER = 1; - localparam FORWARD_ZPU = 2; - localparam FORWARD_ZPU_AND_XO = 3; - localparam FORWARD_XO = 4; - localparam FORWARD_RADIO_CORE = 5; - localparam DROP_PACKET = 6; - localparam CLASSIFY_PACKET = 7; - - - // - // Small RAM stores packet header during parsing. - // - // IJB consider changing HEADER_RAM_SIZE to 7 - localparam HEADER_RAM_SIZE = 9; - (*ram_style="distributed"*) - reg [68:0] header_ram [HEADER_RAM_SIZE-1:0]; - reg [3:0] header_ram_addr; - reg drop_this_packet; - - wire header_done = (header_ram_addr == HEADER_RAM_SIZE-1); - reg fwd_input; - - // - reg [63:0] in_tdata_reg; - - // - wire out_tvalid; - wire out_tready; - wire out_tlast; - wire [3:0] out_tuser; - wire [63:0] out_tdata; - - // - // Output AXI-Stream interface to VITA Radio Core - wire [63:0] vita_pre_tdata; - wire [3:0] vita_pre_tuser; - wire vita_pre_tlast; - wire vita_pre_tvalid; - wire vita_pre_tready; - // Output AXI-Stream interface to ZPU - wire [63:0] zpu_pre_tdata; - wire [3:0] zpu_pre_tuser; - wire zpu_pre_tlast; - wire zpu_pre_tvalid; - wire zpu_pre_tready; - // Output AXI-Stream interface to cross-over MAC - wire [63:0] xo_pre_tdata; - wire [3:0] xo_pre_tuser; - wire xo_pre_tlast; - wire xo_pre_tvalid; - wire xo_pre_tready; - - // - // Packet Parse Flags - // - reg is_eth_dst_addr; - reg is_eth_broadcast; - reg is_eth_type_ipv4; - reg is_ipv4_dst_addr; - reg is_ipv4_proto_udp; - reg is_ipv4_proto_icmp; - reg [1:0] is_udp_dst_ports; - reg is_icmp_no_fwd; - reg is_chdr; - - // - // Settings regs - // - - wire [47:0] my_mac; - - setting_reg #(.my_addr(BASE), .awidth(16), .width(32)) sr_my_mac_lsb - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out(my_mac[31:0]),.changed()); - - setting_reg #(.my_addr(BASE+1), .awidth(16), .width(16)) sr_my_mac_msb - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out(my_mac[47:32]),.changed()); - - wire [31:0] my_ip; - - setting_reg #(.my_addr(BASE+2), .awidth(16), .width(32)) sr_my_ip - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out(my_ip[31:0]),.changed()); - - wire [15:0] my_port0, my_port1; - - setting_reg #(.my_addr(BASE+3), .awidth(16), .width(32)) sr_udp_port - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out({my_port1[15:0],my_port0[15:0]}),.changed()); - - wire forward_ndest, forward_bcast; - setting_reg #(.my_addr(BASE+4), .awidth(16), .width(2)) sr_forward_ctrl - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out({forward_ndest, forward_bcast}),.changed()); - - wire [7:0] my_icmp_type, my_icmp_code; - setting_reg #(.my_addr(BASE+5), .awidth(16), .width(16)) sr_icmp_ctrl - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out({my_icmp_type, my_icmp_code}),.changed()); + // + // State machine declarations + // + reg [2:0] state; + + localparam WAIT_PACKET = 0; + localparam READ_HEADER = 1; + localparam FORWARD_ZPU = 2; + localparam FORWARD_ZPU_AND_XO = 3; + localparam FORWARD_XO = 4; + localparam FORWARD_RADIO_CORE = 5; + localparam DROP_PACKET = 6; + localparam CLASSIFY_PACKET = 7; + + + // + // Small RAM stores packet header during parsing. + // + // IJB consider changing HEADER_RAM_SIZE to 7 + localparam HEADER_RAM_SIZE = 9; + (*ram_style="distributed"*) + reg [68:0] header_ram [HEADER_RAM_SIZE-1:0]; + reg [3:0] header_ram_addr; + reg drop_this_packet; + + wire header_done = (header_ram_addr == HEADER_RAM_SIZE-1); + reg fwd_input; + + // + reg [63:0] in_tdata_reg; + + // + wire out_tvalid; + wire out_tready; + wire out_tlast; + wire [3:0] out_tuser; + wire [63:0] out_tdata; + + // + // Output AXI-Stream interface to VITA Radio Core + wire [63:0] vita_pre_tdata; + wire [3:0] vita_pre_tuser; + wire vita_pre_tlast; + wire vita_pre_tvalid; + wire vita_pre_tready; + // Output AXI-Stream interface to ZPU + wire [63:0] zpu_pre_tdata; + wire [3:0] zpu_pre_tuser; + wire zpu_pre_tlast; + wire zpu_pre_tvalid; + wire zpu_pre_tready; + // Output AXI-Stream interface to cross-over MAC + wire [63:0] xo_pre_tdata; + wire [3:0] xo_pre_tuser; + wire xo_pre_tlast; + wire xo_pre_tvalid; + wire xo_pre_tready; + + // + // Packet Parse Flags + // + reg is_eth_dst_addr; + reg is_eth_broadcast; + reg is_eth_type_ipv4; + reg is_ipv4_dst_addr; + reg is_ipv4_proto_udp; + reg is_ipv4_proto_icmp; + reg [1:0] is_udp_dst_ports; + reg is_icmp_no_fwd; + reg is_chdr; + + // + // Settings regs + // + + wire [47:0] my_mac; + + setting_reg #(.my_addr(BASE), .awidth(16), .width(32)) sr_my_mac_lsb + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(my_mac[31:0]),.changed()); + + setting_reg #(.my_addr(BASE+1), .awidth(16), .width(16)) sr_my_mac_msb + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(my_mac[47:32]),.changed()); + + wire [31:0] my_ip; + + setting_reg #(.my_addr(BASE+2), .awidth(16), .width(32)) sr_my_ip + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(my_ip[31:0]),.changed()); + + wire [15:0] my_port0, my_port1; + + setting_reg #(.my_addr(BASE+3), .awidth(16), .width(32)) sr_udp_port + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out({my_port1[15:0],my_port0[15:0]}),.changed()); + + wire forward_ndest, forward_bcast; + setting_reg #(.my_addr(BASE+4), .awidth(16), .width(2)) sr_forward_ctrl + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out({forward_ndest, forward_bcast}),.changed()); + + wire [7:0] my_icmp_type, my_icmp_code; + setting_reg #(.my_addr(BASE+5), .awidth(16), .width(16)) sr_icmp_ctrl + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out({my_icmp_type, my_icmp_code}),.changed()); assign debug = { @@ -194,347 +194,346 @@ module eth_dispatch }; - // - // Packet Forwarding State machine. - // - - always @(posedge clk) - if (reset || clear) begin - state <= WAIT_PACKET; - header_ram_addr <= 0; - drop_this_packet <= 0; - fwd_input <= 0; - end else begin - // Defaults. - drop_this_packet <= 0; - - case(state) - // - // Wait for start of a packet - // IJB: Add protection for a premature EOF here - // - WAIT_PACKET: begin - if (in_tvalid && in_tready) begin - header_ram[header_ram_addr] <= {in_tlast,in_tuser,in_tdata}; - header_ram_addr <= header_ram_addr + 1; - state <= READ_HEADER; - end - fwd_input <= 0; - end - // - // Continue to read full packet header into RAM. - // - READ_HEADER: begin - if (in_tvalid && in_tready) begin - header_ram[header_ram_addr] <= {in_tlast,in_tuser,in_tdata}; - // Have we reached end of fields we parse in header or got a short packet? - if (header_done || in_tlast) begin - // Make decision about where this packet is forwarded to. - state <= CLASSIFY_PACKET; - end // if (header_done || in_tlast) - else begin - header_ram_addr <= header_ram_addr + 1; - state <= READ_HEADER; - end // else: !if(header_done || in_tlast) - end // if (in_tvalid && in_tready) - end // case: READ_HEADER - - // - // Classify Packet - // - CLASSIFY_PACKET: begin - // Make decision about where this packet is forwarded to. - if (is_eth_type_ipv4 && is_ipv4_proto_icmp && is_icmp_no_fwd) begin - header_ram_addr <= 0; - state <= FORWARD_ZPU; - end else if (is_eth_broadcast) begin - header_ram_addr <= 0; - state <= forward_bcast? FORWARD_ZPU_AND_XO : FORWARD_ZPU; - end else if (!is_eth_dst_addr) begin - header_ram_addr <= 0; - state <= forward_ndest? FORWARD_XO : DROP_PACKET; - end else if ((is_udp_dst_ports != 0) && is_chdr) begin - header_ram_addr <= 6; // Jump to CHDR - state <= FORWARD_RADIO_CORE; - end else if (drop_this_packet) begin - header_ram_addr <= HEADER_RAM_SIZE-1; - state <= DROP_PACKET; - end else begin - header_ram_addr <= 0; - state <= FORWARD_ZPU; - end - end // case: CLASSIFY_PACKET - - // - // Forward this packet only to local ZPU - // - FORWARD_ZPU: begin - if (out_tvalid && out_tready) begin - if (out_tlast) begin - state <= WAIT_PACKET; - end - if (header_done) fwd_input <= 1; - header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; - end - end - // - // Forward this packet to both local ZPU and XO - // - FORWARD_ZPU_AND_XO: begin - if (out_tvalid && out_tready) begin - if (out_tlast) begin - state <= WAIT_PACKET; - end - if (header_done) fwd_input <= 1; - header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; - end - end - // - // Forward this packet to XO only - // - FORWARD_XO: begin - if (out_tvalid && out_tready) begin - if (out_tlast) begin - state <= WAIT_PACKET; - end - if (header_done) fwd_input <= 1; - header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; - end - end - // - // Forward this packet to the Radio Core only - // - FORWARD_RADIO_CORE: begin - if (out_tvalid && out_tready) begin - if (out_tlast) begin - state <= WAIT_PACKET; - end - if (header_done) fwd_input <= 1; - header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; - end - end - // - // Drop this packet on the ground - // - DROP_PACKET: begin - if (out_tvalid && out_tready) begin - if (out_tlast) begin - state <= WAIT_PACKET; - end - if (header_done) fwd_input <= 1; - header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; - end - end - endcase // case (state) - end // else: !if(reset || clear) - - // - // Classifier State machine. - // Deep packet inspection during header ingress. - // - always @(posedge clk) - if (reset || clear) begin - is_eth_dst_addr <= 1'b0; - is_eth_broadcast <= 1'b0; - is_eth_type_ipv4 <= 1'b0; - is_ipv4_dst_addr <= 1'b0; - is_ipv4_proto_udp <= 1'b0; - is_ipv4_proto_icmp <= 1'b0; - is_udp_dst_ports <= 0; - is_icmp_no_fwd <= 0; - is_chdr <= 1'b0; - - // space_in_fifo <= 0; - // is_there_fifo_space <= 1; - // packet_length <= 0; - end else if (in_tvalid && in_tready) begin // if (reset || clear) - in_tdata_reg <= in_tdata; - - case (header_ram_addr) - // Pipelined, so nothing to look at first cycle. - // Reset all the flags here. - 0: begin - is_eth_dst_addr <= 1'b0; - is_eth_broadcast <= 1'b0; - is_eth_type_ipv4 <= 1'b0; - is_ipv4_dst_addr <= 1'b0; - is_ipv4_proto_udp <= 1'b0; - is_ipv4_proto_icmp <= 1'b0; - is_udp_dst_ports <= 0; - is_icmp_no_fwd <= 0; - is_chdr <= 1'b0; - end - 1: begin - // Look at upper 16bits of MAC Dst Addr. - if (in_tdata_reg[15:0] == 16'hFFFF) - is_eth_broadcast <= 1'b1; - if (in_tdata_reg[15:0] == my_mac[47:32]) - is_eth_dst_addr <= 1'b1; - end - 2: begin - // Look at lower 32bits of MAC Dst Addr. - if (is_eth_broadcast && (in_tdata_reg[63:32] == 32'hFFFFFFFF)) - is_eth_broadcast <= 1'b1; - else - is_eth_broadcast <= 1'b0; - if (is_eth_dst_addr && (in_tdata_reg[63:32] == my_mac[31:0])) - is_eth_dst_addr <= 1'b1; - else - is_eth_dst_addr <= 1'b0; - end // case: 2 - 3: begin - // Look at Ethertype - if (in_tdata_reg[47:32] == 16'h0800) - is_eth_type_ipv4 <= 1'b1; - // Extract Packet Length - // ADD THIS HERE. - end - 4: begin - // Look at protocol enapsulated by IPv4 - if ((in_tdata_reg[23:16] == 8'h11) && is_eth_type_ipv4) - is_ipv4_proto_udp <= 1'b1; - if ((in_tdata_reg[23:16] == 8'h01) && is_eth_type_ipv4) - is_ipv4_proto_icmp <= 1'b1; - end - 5: begin - // Look at IP DST Address. - if ((in_tdata_reg[31:0] == my_ip[31:0]) && is_eth_type_ipv4) - is_ipv4_dst_addr <= 1'b1; - end - 6: begin - // Look at UDP dest port - if ((in_tdata_reg[47:32] == my_port0[15:0]) && is_ipv4_proto_udp) - is_udp_dst_ports[0] <= 1'b1; - if ((in_tdata_reg[47:32] == my_port1[15:0]) && is_ipv4_proto_udp) - is_udp_dst_ports[1] <= 1'b1; - // Look at ICMP type and code - if (in_tdata_reg[63:48] == {my_icmp_type, my_icmp_code} && is_ipv4_proto_icmp) - is_icmp_no_fwd <= 1'b1; - end - 7: begin - // Look for a possible CHDR header string - // IJB. NOTE this is not a good test for a CHDR packet, we perhaps don;t need this state anyhow. - if (in_tdata_reg[63:32] != 32'h0) - is_chdr <= 1'b1; - end - 8: begin - // Check VRT Stream ID - // ADD THIS HERE. - // IJB. Perhaps delete this state. - end - endcase // case (header_ram_addr) - end // if (in_tvalid && in_tready) - - - // - // Output (Egress) Interface muxing - // - assign out_tready = - (state == DROP_PACKET) || - ((state == FORWARD_RADIO_CORE) && vita_pre_tready) || - ((state == FORWARD_XO) && xo_pre_tready) || - ((state == FORWARD_ZPU) && zpu_pre_tready) || - ((state == FORWARD_ZPU_AND_XO) && zpu_pre_tready && xo_pre_tready); - - assign out_tvalid = ((state == FORWARD_RADIO_CORE) || - (state == FORWARD_XO) || - (state == FORWARD_ZPU) || - (state == FORWARD_ZPU_AND_XO) || - (state == DROP_PACKET)) && (!fwd_input || in_tvalid); - - assign {out_tlast,out_tuser,out_tdata} = fwd_input ? {in_tlast,in_tuser,in_tdata} : header_ram[header_ram_addr]; - - assign in_tready = (state == WAIT_PACKET) || - (state == READ_HEADER) || - (state == DROP_PACKET) || - (out_tready && fwd_input); - - - // - // Because we can forward to both the ZPU and XO FIFO's concurrently - // we have to make sure both can accept data in the same cycle. - // This makes it possible for either destination to block the other. - // Make sure (both) destination(s) can accept data before passing it. - // - assign xo_pre_tvalid = out_tvalid && - ((state == FORWARD_XO) || - ((state == FORWARD_ZPU_AND_XO) && zpu_pre_tready)); - assign zpu_pre_tvalid = out_tvalid && - ((state == FORWARD_ZPU) || - ((state == FORWARD_ZPU_AND_XO) && xo_pre_tready)); - assign vita_pre_tvalid = out_tvalid && (state == FORWARD_RADIO_CORE); - - assign {zpu_pre_tuser,zpu_pre_tdata} = ((state == FORWARD_ZPU_AND_XO) || (state == FORWARD_ZPU)) ? - {out_tuser,out_tdata} : 0; - - assign {xo_pre_tuser,xo_pre_tdata} = ((state == FORWARD_ZPU_AND_XO) || (state == FORWARD_XO)) ? - {out_tuser,out_tdata} : 0; - - assign {vita_pre_tuser,vita_pre_tdata} = (state == FORWARD_RADIO_CORE) ? {out_tuser,out_tdata} : 0; - - assign zpu_pre_tlast = out_tlast && ((state == FORWARD_ZPU) || (state == FORWARD_ZPU_AND_XO)); - - assign xo_pre_tlast = out_tlast && ((state == FORWARD_XO) || (state == FORWARD_ZPU_AND_XO)); - - assign vita_pre_tlast = out_tlast && (state == FORWARD_RADIO_CORE); - - // - // Egress FIFO's (Large) - // - axi_fifo #(.WIDTH(69),.SIZE(10)) - axi_fifo_zpu ( - .clk(clk), - .reset(reset), - .clear(clear), - .i_tdata({zpu_pre_tlast,zpu_pre_tuser,zpu_pre_tdata}), - .i_tvalid(zpu_pre_tvalid), - .i_tready(zpu_pre_tready), - .o_tdata({zpu_tlast,zpu_tuser,zpu_tdata}), - .o_tvalid(zpu_tvalid), - .o_tready(zpu_tready), - .space(), - .occupied() - ); - - axi_fifo #(.WIDTH(69),.SIZE(10)) - axi_fifo_xo ( - .clk(clk), - .reset(reset), - .clear(clear), - .i_tdata({xo_pre_tlast,xo_pre_tuser,xo_pre_tdata}), - .i_tvalid(xo_pre_tvalid), - .i_tready(xo_pre_tready), - .o_tdata({xo_tlast,xo_tuser,xo_tdata}), - .o_tvalid(xo_tvalid), - .o_tready(xo_tready), - .space(), - .occupied() - ); - - axi_fifo #(.WIDTH(69),.SIZE(10)) - axi_fifo_vita ( - .clk(clk), - .reset(reset), - .clear(clear), - .i_tdata({vita_pre_tlast,vita_pre_tuser,vita_pre_tdata}), - .i_tvalid(vita_pre_tvalid), - .i_tready(vita_pre_tready), - .o_tdata({vita_tlast,vita_tuser,vita_tdata}), - .o_tvalid(vita_tvalid), - .o_tready(vita_tready), - .space(), - .occupied() - ); - - assign debug_flags = {vita_pre_tready,xo_pre_tready,zpu_pre_tready}; - - - + // + // Packet Forwarding State machine. + // + + always @(posedge clk) + if (reset || clear) begin + state <= WAIT_PACKET; + header_ram_addr <= 0; + drop_this_packet <= 0; + fwd_input <= 0; + end else begin + // Defaults. + drop_this_packet <= 0; + + case(state) + // + // Wait for start of a packet + // IJB: Add protection for a premature EOF here + // + WAIT_PACKET: begin + if (in_tvalid && in_tready) begin + header_ram[header_ram_addr] <= {in_tlast,in_tuser,in_tdata}; + header_ram_addr <= header_ram_addr + 1; + state <= READ_HEADER; + end + fwd_input <= 0; + end + // + // Continue to read full packet header into RAM. + // + READ_HEADER: begin + if (in_tvalid && in_tready) begin + header_ram[header_ram_addr] <= {in_tlast,in_tuser,in_tdata}; + // Have we reached end of fields we parse in header or got a short packet? + if (header_done || in_tlast) begin + // Make decision about where this packet is forwarded to. + state <= CLASSIFY_PACKET; + end // if (header_done || in_tlast) + else begin + header_ram_addr <= header_ram_addr + 1; + state <= READ_HEADER; + end // else: !if(header_done || in_tlast) + end // if (in_tvalid && in_tready) + end // case: READ_HEADER + + // + // Classify Packet + // + CLASSIFY_PACKET: begin + // Make decision about where this packet is forwarded to. + if (is_eth_type_ipv4 && is_ipv4_proto_icmp && is_icmp_no_fwd) begin + header_ram_addr <= 0; + state <= FORWARD_ZPU; + end else if (is_eth_broadcast) begin + header_ram_addr <= 0; + state <= forward_bcast? FORWARD_ZPU_AND_XO : FORWARD_ZPU; + end else if (!is_eth_dst_addr) begin + header_ram_addr <= 0; + state <= forward_ndest? FORWARD_XO : DROP_PACKET; + end else if ((is_udp_dst_ports != 0) && is_chdr) begin + header_ram_addr <= 6; // Jump to CHDR + state <= FORWARD_RADIO_CORE; + end else if (drop_this_packet) begin + header_ram_addr <= HEADER_RAM_SIZE-1; + state <= DROP_PACKET; + end else begin + header_ram_addr <= 0; + state <= FORWARD_ZPU; + end + end // case: CLASSIFY_PACKET + + // + // Forward this packet only to local ZPU + // + FORWARD_ZPU: begin + if (out_tvalid && out_tready) begin + if (out_tlast) begin + state <= WAIT_PACKET; + end + if (header_done) fwd_input <= 1; + header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; + end + end + // + // Forward this packet to both local ZPU and XO + // + FORWARD_ZPU_AND_XO: begin + if (out_tvalid && out_tready) begin + if (out_tlast) begin + state <= WAIT_PACKET; + end + if (header_done) fwd_input <= 1; + header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; + end + end + // + // Forward this packet to XO only + // + FORWARD_XO: begin + if (out_tvalid && out_tready) begin + if (out_tlast) begin + state <= WAIT_PACKET; + end + if (header_done) fwd_input <= 1; + header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; + end + end + // + // Forward this packet to the Radio Core only + // + FORWARD_RADIO_CORE: begin + if (out_tvalid && out_tready) begin + if (out_tlast) begin + state <= WAIT_PACKET; + end + if (header_done) fwd_input <= 1; + header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; + end + end + // + // Drop this packet on the ground + // + DROP_PACKET: begin + if (out_tvalid && out_tready) begin + if (out_tlast) begin + state <= WAIT_PACKET; + end + if (header_done) fwd_input <= 1; + header_ram_addr <= out_tlast? 4'b0 : header_ram_addr + 1; + end + end + endcase // case (state) + end // else: !if(reset || clear) + + // + // Classifier State machine. + // Deep packet inspection during header ingress. + // + always @(posedge clk) + if (reset || clear) begin + is_eth_dst_addr <= 1'b0; + is_eth_broadcast <= 1'b0; + is_eth_type_ipv4 <= 1'b0; + is_ipv4_dst_addr <= 1'b0; + is_ipv4_proto_udp <= 1'b0; + is_ipv4_proto_icmp <= 1'b0; + is_udp_dst_ports <= 0; + is_icmp_no_fwd <= 0; + is_chdr <= 1'b0; + + //space_in_fifo <= 0; + //is_there_fifo_space <= 1; + //packet_length <= 0; + end else if (in_tvalid && in_tready) begin // if (reset || clear) + in_tdata_reg <= in_tdata; + + case (header_ram_addr) + // Pipelined, so nothing to look at first cycle. + // Reset all the flags here. + 0: begin + is_eth_dst_addr <= 1'b0; + is_eth_broadcast <= 1'b0; + is_eth_type_ipv4 <= 1'b0; + is_ipv4_dst_addr <= 1'b0; + is_ipv4_proto_udp <= 1'b0; + is_ipv4_proto_icmp <= 1'b0; + is_udp_dst_ports <= 0; + is_icmp_no_fwd <= 0; + is_chdr <= 1'b0; + end + 1: begin + // Look at upper 16bits of MAC Dst Addr. + if (in_tdata_reg[15:0] == 16'hFFFF) + is_eth_broadcast <= 1'b1; + if (in_tdata_reg[15:0] == my_mac[47:32]) + is_eth_dst_addr <= 1'b1; + end + 2: begin + // Look at lower 32bits of MAC Dst Addr. + if (is_eth_broadcast && (in_tdata_reg[63:32] == 32'hFFFFFFFF)) + is_eth_broadcast <= 1'b1; + else + is_eth_broadcast <= 1'b0; + if (is_eth_dst_addr && (in_tdata_reg[63:32] == my_mac[31:0])) + is_eth_dst_addr <= 1'b1; + else + is_eth_dst_addr <= 1'b0; + end // case: 2 + 3: begin + // Look at Ethertype + if (in_tdata_reg[47:32] == 16'h0800) + is_eth_type_ipv4 <= 1'b1; + // Extract Packet Length + // ADD THIS HERE. + end + 4: begin + // Look at protocol enapsulated by IPv4 + if ((in_tdata_reg[23:16] == 8'h11) && is_eth_type_ipv4) + is_ipv4_proto_udp <= 1'b1; + if ((in_tdata_reg[23:16] == 8'h01) && is_eth_type_ipv4) + is_ipv4_proto_icmp <= 1'b1; + end + 5: begin + // Look at IP DST Address. + if ((in_tdata_reg[31:0] == my_ip[31:0]) && is_eth_type_ipv4) + is_ipv4_dst_addr <= 1'b1; + end + 6: begin + // Look at UDP dest port + if ((in_tdata_reg[47:32] == my_port0[15:0]) && is_ipv4_proto_udp) + is_udp_dst_ports[0] <= 1'b1; + if ((in_tdata_reg[47:32] == my_port1[15:0]) && is_ipv4_proto_udp) + is_udp_dst_ports[1] <= 1'b1; + // Look at ICMP type and code + if (in_tdata_reg[63:48] == {my_icmp_type, my_icmp_code} && is_ipv4_proto_icmp) + is_icmp_no_fwd <= 1'b1; + end + 7: begin + // Look for a possible CHDR header string + // IJB. NOTE this is not a good test for a CHDR packet, we perhaps don;t need this state anyhow. + if (in_tdata_reg[63:32] != 32'h0) + is_chdr <= 1'b1; + end + 8: begin + // Check VRT Stream ID + // ADD THIS HERE. + // IJB. Perhaps delete this state. + end + endcase // case (header_ram_addr) + end // if (in_tvalid && in_tready) + + + // + // Output (Egress) Interface muxing + // + assign out_tready = + (state == DROP_PACKET) || + ((state == FORWARD_RADIO_CORE) && vita_pre_tready) || + ((state == FORWARD_XO) && xo_pre_tready) || + ((state == FORWARD_ZPU) && zpu_pre_tready) || + ((state == FORWARD_ZPU_AND_XO) && zpu_pre_tready && xo_pre_tready); + + assign out_tvalid = ((state == FORWARD_RADIO_CORE) || + (state == FORWARD_XO) || + (state == FORWARD_ZPU) || + (state == FORWARD_ZPU_AND_XO) || + (state == DROP_PACKET)) && (!fwd_input || in_tvalid); + + assign {out_tlast,out_tuser,out_tdata} = fwd_input ? {in_tlast,in_tuser,in_tdata} : header_ram[header_ram_addr]; + + assign in_tready = (state == WAIT_PACKET) || + (state == READ_HEADER) || + (out_tready && fwd_input); + + + // + // Because we can forward to both the ZPU and XO FIFO's concurrently + // we have to make sure both can accept data in the same cycle. + // This makes it possible for either destination to block the other. + // Make sure (both) destination(s) can accept data before passing it. + // + assign xo_pre_tvalid = out_tvalid && + ((state == FORWARD_XO) || + ((state == FORWARD_ZPU_AND_XO) && zpu_pre_tready)); + assign zpu_pre_tvalid = out_tvalid && + ((state == FORWARD_ZPU) || + ((state == FORWARD_ZPU_AND_XO) && xo_pre_tready)); + assign vita_pre_tvalid = out_tvalid && (state == FORWARD_RADIO_CORE); + + assign {zpu_pre_tuser,zpu_pre_tdata} = ((state == FORWARD_ZPU_AND_XO) || (state == FORWARD_ZPU)) ? + {out_tuser,out_tdata} : 0; + + assign {xo_pre_tuser,xo_pre_tdata} = ((state == FORWARD_ZPU_AND_XO) || (state == FORWARD_XO)) ? + {out_tuser,out_tdata} : 0; + + assign {vita_pre_tuser,vita_pre_tdata} = (state == FORWARD_RADIO_CORE) ? {out_tuser,out_tdata} : 0; + + assign zpu_pre_tlast = out_tlast && ((state == FORWARD_ZPU) || (state == FORWARD_ZPU_AND_XO)); + + assign xo_pre_tlast = out_tlast && ((state == FORWARD_XO) || (state == FORWARD_ZPU_AND_XO)); + + assign vita_pre_tlast = out_tlast && (state == FORWARD_RADIO_CORE); + + // + // Egress FIFO's (Large) + // + axi_fifo #(.WIDTH(69),.SIZE(10)) + axi_fifo_zpu ( + .clk(clk), + .reset(reset), + .clear(clear), + .i_tdata({zpu_pre_tlast,zpu_pre_tuser,zpu_pre_tdata}), + .i_tvalid(zpu_pre_tvalid), + .i_tready(zpu_pre_tready), + .o_tdata({zpu_tlast,zpu_tuser,zpu_tdata}), + .o_tvalid(zpu_tvalid), + .o_tready(zpu_tready), + .space(), + .occupied() + ); + + axi_fifo #(.WIDTH(69),.SIZE(10)) + axi_fifo_xo ( + .clk(clk), + .reset(reset), + .clear(clear), + .i_tdata({xo_pre_tlast,xo_pre_tuser,xo_pre_tdata}), + .i_tvalid(xo_pre_tvalid), + .i_tready(xo_pre_tready), + .o_tdata({xo_tlast,xo_tuser,xo_tdata}), + .o_tvalid(xo_tvalid), + .o_tready(xo_tready), + .space(), + .occupied() + ); + + axi_fifo #(.WIDTH(69),.SIZE(10)) + axi_fifo_vita ( + .clk(clk), + .reset(reset), + .clear(clear), + .i_tdata({vita_pre_tlast,vita_pre_tuser,vita_pre_tdata}), + .i_tvalid(vita_pre_tvalid), + .i_tready(vita_pre_tready), + .o_tdata({vita_tlast,vita_tuser,vita_tdata}), + .o_tvalid(vita_tvalid), + .o_tready(vita_tready), + .space(), + .occupied() + ); + + assign debug_flags = {vita_pre_tready,xo_pre_tready,zpu_pre_tready}; + + + /* -----\/----- EXCLUDED -----\/----- - + wire vready, zready, oready; wire vvalid, zvalid, ovalid; - + reg [2:0] ed_state; localparam ED_IDLE = 3'd0; localparam ED_IN_HDR = 3'd1; @@ -556,22 +555,22 @@ module eth_dispatch ; endcase // case (ed_state) */ - + /* -----\/----- EXCLUDED -----\/----- axi_packet_gate #(.WIDTH(64), .SIZE(10)) vita_gate (.clk(clk), .reset(reset), .clear(clear), .i_tdata(in_tdata), .i_tlast(), .i_terror(), .i_tvalid(1'b0), .i_tready(vready), .o_tdata(vita_tdata), .o_tlast(vita_tlast), .o_tvalid(vita_tvalid), .o_tready(vita_tready)); - + axi_packet_gate #(.WIDTH(68), .SIZE(10)) zpu_gate (.clk(clk), .reset(reset), .clear(clear), .i_tdata({in_tuser,in_tdata}), .i_tlast(in_tlast), .i_terror(in_tuser[3]), .i_tvalid(in_tvalid), .i_tready(in_tready), .o_tdata({zpu_tuser,zpu_tdata}), .o_tlast(zpu_tlast), .o_tvalid(zpu_tvalid), .o_tready(zpu_tready)); - + axi_packet_gate #(.WIDTH(68), .SIZE(10)) out_gate (.clk(clk), .reset(reset), .clear(clear), .i_tdata({in_tuser,in_tdata}), .i_tlast(), .i_terror(), .i_tvalid(1'b0), .i_tready(oready), .o_tdata({out_tuser,out_tdata}), .o_tlast(out_tlast), .o_tvalid(out_tvalid), .o_tready(out_tready)); -----/\----- EXCLUDED -----/\----- */ - + endmodule // eth_dispatch diff --git a/fpga/usrp3/lib/vita/new_tx_control.v b/fpga/usrp3/lib/vita/new_tx_control.v index 4cdb54a24..910cc1f83 100644 --- a/fpga/usrp3/lib/vita/new_tx_control.v +++ b/fpga/usrp3/lib/vita/new_tx_control.v @@ -4,26 +4,26 @@ module new_tx_control #(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] vita_time, output reg ack_or_error, output packet_consumed, output [11:0] seqnum, output reg [63:0] error_code, output [31:0] sid, - + // From tx_deframer input [175:0] sample_tdata, input sample_tvalid, output sample_tready, - + // To DSP Core - output [31:0] sample, + output [31:0] sample, output run, input strobe, - + output [31:0] debug ); - + wire [31:0] sample1 = sample_tdata[31:0]; wire [31:0] sample0 = sample_tdata[63:32]; wire [63:0] send_time = sample_tdata[127:64]; @@ -33,39 +33,39 @@ module new_tx_control wire eob = sample_tdata[173]; wire send_at = sample_tdata[174]; wire odd = sample_tdata[175]; - + wire now, early, late, too_early; wire policy_next_burst, policy_next_packet, policy_wait; wire clear_seqnum; - + setting_reg #(.my_addr(BASE), .width(3)) sr_error_policy (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),.out({policy_next_burst,policy_next_packet,policy_wait}),.changed(clear_seqnum)); - time_compare + time_compare time_compare (.clk(clk), .reset(reset), .time_now(vita_time), .trigger_time(send_time), .now(now), .early(early), .late(late), .too_early(too_early)); assign run = (state == ST_SAMP0) | (state == ST_SAMP1); - + assign sample = (state == ST_SAMP0) ? sample0 : sample1; - + reg [2:0] state; - + localparam ST_IDLE = 0; localparam ST_SAMP0 = 1; localparam ST_SAMP1 = 2; localparam ST_ERROR = 3; localparam ST_WAIT = 4; + reg [11:0] expected_seqnum; + wire [63:0] CODE_EOB_ACK = {32'd1,20'd0,seqnum}; wire [63:0] CODE_UNDERRUN = {32'd2,20'd0,seqnum}; - wire [63:0] CODE_SEQ_ERROR = {32'd4,20'd0,seqnum}; + wire [63:0] CODE_SEQ_ERROR = {32'd4,4'd0,expected_seqnum,4'd0,seqnum}; wire [63:0] CODE_TIME_ERROR = {32'd8,20'd0,seqnum}; wire [63:0] CODE_UNDERRUN_MIDPKT = {32'd16,20'd0,seqnum}; - wire [63:0] CODE_SEQ_ERROR_MIDBURST = {32'd32,20'd0,seqnum}; - - reg [11:0] expected_seqnum; + wire [63:0] CODE_SEQ_ERROR_MIDBURST = {32'd32,4'd0,expected_seqnum,4'd0,seqnum}; always @(posedge clk) if(reset | clear | clear_seqnum) @@ -73,14 +73,14 @@ module new_tx_control else if(sample_tvalid & sample_tready & eop) expected_seqnum <= seqnum + 12'd1; - + always @(posedge clk) if(reset | clear) begin state <= ST_IDLE; ack_or_error <= 1'b0; error_code <= 64'd0; - end + end else case(state) ST_IDLE : @@ -151,7 +151,7 @@ module new_tx_control assign sample_tready = (state == ST_ERROR) | (strobe & ( (state == ST_SAMP1) | ((state == ST_SAMP0) & eop & odd) ) ); assign packet_consumed = eop & sample_tvalid & sample_tready; - + assign debug = { error_code[37:32], // [30:25] error_code[11:0], // [24:13] @@ -168,5 +168,5 @@ module new_tx_control state[2:0] // [2:0] }; - + endmodule // new_tx_control |