aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp2/udp/prot_eng_tx.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp2/udp/prot_eng_tx.v')
-rw-r--r--fpga/usrp2/udp/prot_eng_tx.v166
1 files changed, 65 insertions, 101 deletions
diff --git a/fpga/usrp2/udp/prot_eng_tx.v b/fpga/usrp2/udp/prot_eng_tx.v
index c642842f6..b4f6e55b8 100644
--- a/fpga/usrp2/udp/prot_eng_tx.v
+++ b/fpga/usrp2/udp/prot_eng_tx.v
@@ -1,146 +1,110 @@
-// The input FIFO contents should be 16 bits wide
-// The first word is 1 for fast path (accelerated protocol)
-// 0 for software implemented protocol
-// The second word is the number of bytes in the packet,
-// and must be valid even if we are in slow path mode
-// Odd means the last word is half full
-// Flags[1:0] is {eop, sop}
-// Protocol word format is:
-// 21 UDP Source Port Here
-// 20 UDP Dest Port Here
-// 19 Last Header Line
-// 18 IP Header Checksum XOR
-// 17 IP Length Here
-// 16 UDP Length Here
-// 15:0 data word to be sent
-
module prot_eng_tx
#(parameter BASE=0)
(input clk, input reset, input clear,
input set_stb, input [7:0] set_addr, input [31:0] set_data,
- input [18:0] datain, input src_rdy_i, output dst_rdy_o,
- output [18:0] dataout, output src_rdy_o, input dst_rdy_i);
-
- wire [2:0] flags_i = datain[18:16];
- reg [15:0] dataout_int;
- reg fast_path, sof_o;
-
- wire [2:0] flags_o = {flags_i[2], flags_i[1], sof_o}; // OCC, EOF, SOF
+ input [35:0] datain, input src_rdy_i, output dst_rdy_o,
+ output [35:0] dataout, output src_rdy_o, input dst_rdy_i);
- assign dataout = {flags_o[2:0], dataout_int[15:0]};
+ wire src_rdy_int1, dst_rdy_int1;
+ wire src_rdy_int2, dst_rdy_int2;
+ wire [35:0] data_int1, data_int2;
- reg [4:0] state;
- wire do_payload = (state == 31);
-
- assign dst_rdy_o = dst_rdy_i & (do_payload | (state==0) | (state==1) | (state==30));
- assign src_rdy_o = src_rdy_i & ~((state==0) | (state==1) | (state==30));
-
- localparam HDR_WIDTH = 16 + 6; // 16 bits plus flags
- localparam HDR_LEN = 32; // Up to 64 bytes of protocol
+ // Shortfifo on input to guarantee no deadlock
+ fifo_short #(.WIDTH(36)) head_fifo
+ (.clk(clk),.reset(reset),.clear(clear),
+ .datain(datain), .src_rdy_i(src_rdy_i), .dst_rdy_o(dst_rdy_o),
+ .dataout(data_int1), .src_rdy_o(src_rdy_int1), .dst_rdy_i(dst_rdy_int1),
+ .space(),.occupied() );
// Store header values in a small dual-port (distributed) ram
- reg [HDR_WIDTH-1:0] header_ram[0:HDR_LEN-1];
- wire [HDR_WIDTH-1:0] header_word;
-
- reg [1:0] port_sel;
- reg [31:0] per_port_data[0:3];
- reg [15:0] udp_src_port, udp_dst_port, chk_precompute;
-
- always @(posedge clk) udp_src_port <= per_port_data[port_sel][31:16];
- always @(posedge clk) udp_dst_port <= per_port_data[port_sel][15:0];
-
+ reg [31:0] header_ram[0:63];
+ reg [3:0] state;
+ reg [1:0] port_sel;
+
always @(posedge clk)
- if(set_stb & ((set_addr & 8'hE0) == BASE))
- header_ram[set_addr[4:0]] <= set_data;
+ if(set_stb & ((set_addr & 8'hC0) == BASE))
+ header_ram[set_addr[5:0]] <= set_data;
- always @(posedge clk)
- if(set_stb & (set_addr == (BASE + 14)))
- chk_precompute <= set_data[15:0];
+ wire [31:0] header_word = header_ram[{port_sel[1:0],state[3:0]}];
+ reg [15:0] pre_checksums [0:3];
always @(posedge clk)
- if(set_stb & ((set_addr & 8'hFC) == (BASE+24)))
- per_port_data[set_addr[1:0]] <= set_data;
-
- wire do_udp_src_port = header_word[21];
- wire do_udp_dst_port = header_word[20];
- wire last_hdr_line = header_word[19];
- wire do_ip_chk = header_word[18];
- wire do_ip_len = header_word[17];
- wire do_udp_len = header_word[16];
+ if(set_stb & ((set_addr & 8'hCF)== (BASE+7)))
+ pre_checksums[set_addr[5:4]] <= set_data[15:0];
+
+ wire [15:0] pre_checksum = pre_checksums[port_sel[1:0]];
- assign header_word = header_ram[state];
-
// Protocol State Machine
reg [15:0] length;
wire [15:0] ip_length = length + 28; // IP HDR + UDP HDR
wire [15:0] udp_length = length + 8; // UDP HDR
-
+ reg sof_o;
+ reg [31:0] prot_data;
+
always @(posedge clk)
if(reset)
begin
- state <= 0;
- fast_path <= 0;
+ state <= 0;
sof_o <= 0;
end
else
- if(src_rdy_i & dst_rdy_i)
+ if(src_rdy_int1 & dst_rdy_int2)
case(state)
0 :
begin
- fast_path <= datain[0];
- port_sel <= datain[2:1];
- state <= 1;
- end
- 1 :
- begin
- length <= datain[15:0];
+ port_sel <= data_int1[18:17];
+ length <= data_int1[15:0];
sof_o <= 1;
- if(fast_path)
- state <= 2;
+ if(data_int1[16])
+ state <= 1;
else
- state <= 30; // Skip 1 word for alignment
+ state <= 12;
end
- 30 :
- state <= 31;
- 31 :
+ 12 :
begin
sof_o <= 0;
- if(flags_i[1]) // eop
+ if(data_int1[33]) // eof
state <= 0;
end
default :
begin
sof_o <= 0;
- if(~last_hdr_line)
- state <= state + 1;
- else
- state <= 31;
+ state <= state + 1;
end
endcase // case (state)
- wire [15:0] checksum;
+ wire [15:0] ip_checksum;
add_onescomp #(.WIDTH(16)) add_onescomp
- (.A(chk_precompute),.B(ip_length),.SUM(checksum));
-
- reg [15:0] checksum_reg;
- always @(posedge clk)
- checksum_reg <= checksum;
+ (.A(pre_checksum),.B(ip_length),.SUM(ip_checksum));
+ reg [15:0] ip_checksum_reg;
+ always @(posedge clk) ip_checksum_reg <= ip_checksum;
always @*
- if(do_payload)
- dataout_int <= datain[15:0];
- else if(do_ip_chk)
- dataout_int <= 16'hFFFF ^ checksum_reg;
- else if(do_ip_len)
- dataout_int <= ip_length;
- else if(do_udp_len)
- dataout_int <= udp_length;
- else if(do_udp_src_port)
- dataout_int <= udp_src_port;
- else if(do_udp_dst_port)
- dataout_int <= udp_dst_port;
- else
- dataout_int <= header_word[15:0];
+ case(state)
+ 1 : prot_data <= header_word; // ETH, top half ignored
+ 2 : prot_data <= header_word; // ETH
+ 3 : prot_data <= header_word; // ETH
+ 4 : prot_data <= header_word; // ETH
+ 5 : prot_data <= { header_word[31:16], ip_length }; // IP
+ 6 : prot_data <= header_word; // IP
+ 7 : prot_data <= { header_word[31:16], (16'hFFFF ^ ip_checksum_reg) }; // IP
+ 8 : prot_data <= header_word; // IP
+ 9 : prot_data <= header_word; // IP
+ 10: prot_data <= header_word; // UDP
+ 11: prot_data <= { udp_length, header_word[15:0]}; // UDP
+ default : prot_data <= data_int1[31:0];
+ endcase // case (state)
+
+ assign data_int2 = { data_int1[35:33] & {3{state[3]}}, sof_o, prot_data };
+ assign dst_rdy_int1 = dst_rdy_int2 & ((state == 0) | (state == 12));
+ assign src_rdy_int2 = src_rdy_int1 & (state != 0);
+
+ // Shortfifo on output to guarantee no deadlock
+ fifo_short #(.WIDTH(36)) tail_fifo
+ (.clk(clk),.reset(reset),.clear(clear),
+ .datain(data_int2), .src_rdy_i(src_rdy_int2), .dst_rdy_o(dst_rdy_int2),
+ .dataout(dataout), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i),
+ .space(),.occupied() );
endmodule // prot_eng_tx