diff options
Diffstat (limited to 'fpga/usrp2/fifo')
-rw-r--r-- | fpga/usrp2/fifo/Makefile.srcs | 6 | ||||
-rw-r--r-- | fpga/usrp2/fifo/buffer_int2.v | 22 | ||||
-rw-r--r-- | fpga/usrp2/fifo/dsp_framer36.v | 143 | ||||
-rw-r--r-- | fpga/usrp2/fifo/fifo18_to_fifo36.v | 20 | ||||
-rw-r--r-- | fpga/usrp2/fifo/fifo19_to_fifo36.v | 74 | ||||
-rw-r--r-- | fpga/usrp2/fifo/fifo36_mux.v | 37 | ||||
-rw-r--r-- | fpga/usrp2/fifo/fifo36_to_fifo19.v | 48 | ||||
-rw-r--r-- | fpga/usrp2/fifo/fifo36_to_fifo72.v | 125 | ||||
-rw-r--r-- | fpga/usrp2/fifo/fifo36_to_ll8.v | 80 | ||||
-rw-r--r-- | fpga/usrp2/fifo/fifo72_to_fifo36.v | 63 | ||||
-rw-r--r-- | fpga/usrp2/fifo/fifo_pacer.v | 24 | ||||
-rw-r--r-- | fpga/usrp2/fifo/fifo_tb.v | 166 | ||||
-rw-r--r-- | fpga/usrp2/fifo/ll8_to_fifo19.v | 76 | ||||
-rw-r--r-- | fpga/usrp2/fifo/packet32_tb.v | 27 | ||||
-rw-r--r-- | fpga/usrp2/fifo/packet_dispatcher36_x3.v | 270 | ||||
-rw-r--r-- | fpga/usrp2/fifo/packet_generator.v | 83 | ||||
-rw-r--r-- | fpga/usrp2/fifo/packet_generator32.v | 23 | ||||
-rw-r--r-- | fpga/usrp2/fifo/packet_router.v | 319 | ||||
-rw-r--r-- | fpga/usrp2/fifo/packet_tb.v | 29 | ||||
-rw-r--r-- | fpga/usrp2/fifo/packet_verifier.v | 61 | ||||
-rw-r--r-- | fpga/usrp2/fifo/packet_verifier32.v | 30 |
21 files changed, 1069 insertions, 657 deletions
diff --git a/fpga/usrp2/fifo/Makefile.srcs b/fpga/usrp2/fifo/Makefile.srcs index f0b5b7bae..31b1f505a 100644 --- a/fpga/usrp2/fifo/Makefile.srcs +++ b/fpga/usrp2/fifo/Makefile.srcs @@ -28,4 +28,10 @@ fifo36_demux.v \ packet_router.v \ splitter36.v \ valve36.v \ +fifo_pacer.v \ +packet_dispatcher36_x3.v \ +packet_generator32.v \ +packet_generator.v \ +packet_verifier32.v \ +packet_verifier.v \ )) diff --git a/fpga/usrp2/fifo/buffer_int2.v b/fpga/usrp2/fifo/buffer_int2.v index 765b125fb..532980aa2 100644 --- a/fpga/usrp2/fifo/buffer_int2.v +++ b/fpga/usrp2/fifo/buffer_int2.v @@ -31,13 +31,15 @@ module buffer_int2 input rd_ready_i ); - reg [BUF_SIZE-1:0] rd_addr, wr_addr; + reg [15:0] rd_addr, wr_addr; // Handle pkt bigger than buffer + wire [15:0] rd_addr_next = rd_addr + 1; + reg [15:0] rd_length; + wire [31:0] ctrl; wire wr_done, wr_error, wr_idle; wire rd_done, rd_error, rd_idle; wire we, en, go; - reg [BUF_SIZE-1:0] lastline; wire read = ctrl[3]; wire rd_clear = ctrl[2]; wire write = ctrl[1]; @@ -72,13 +74,13 @@ module buffer_int2 begin rd_addr <= 0; rd_state <= PRE_READ; - lastline <= ctrl[15+BUF_SIZE:16]; + rd_length <= ctrl[31:16]; end PRE_READ : begin rd_state <= READING; - rd_addr <= rd_addr + 1; + rd_addr <= rd_addr_next; rd_occ <= 2'b00; rd_sop <= 1; rd_eop <= 0; @@ -88,8 +90,8 @@ module buffer_int2 if(rd_ready_i) begin rd_sop <= 0; - rd_addr <= rd_addr + 1; - if(rd_addr == lastline) + rd_addr <= rd_addr_next; + if(rd_addr_next == rd_length) begin rd_eop <= 1; // FIXME assign occ here @@ -145,17 +147,19 @@ module buffer_int2 assign rd_idle = (rd_state == IDLE); assign wr_idle = (wr_state == IDLE); + wire [BUF_SIZE-1:0] wr_addr_clip = (|wr_addr[15:BUF_SIZE]) ? {BUF_SIZE{1'b1}} : wr_addr[BUF_SIZE-1:0]; + ram_2port #(.DWIDTH(32),.AWIDTH(BUF_SIZE)) buffer_in // CPU reads here (.clka(wb_clk_i),.ena(wb_stb_i),.wea(1'b0), .addra(wb_adr_i[BUF_SIZE+1:2]),.dia(0),.doa(wb_dat_o), .clkb(clk),.enb(1'b1),.web(we), - .addrb(wr_addr),.dib(wr_data_i[31:0]),.dob()); + .addrb(wr_addr_clip),.dib(wr_data_i[31:0]),.dob()); ram_2port #(.DWIDTH(32),.AWIDTH(BUF_SIZE)) buffer_out // CPU writes here (.clka(wb_clk_i),.ena(wb_stb_i),.wea(wb_we_i), .addra(wb_adr_i[BUF_SIZE+1:2]),.dia(wb_dat_i),.doa(), .clkb(clk),.enb(en),.web(1'b0), - .addrb(rd_addr),.dib(0),.dob(rd_data_o[31:0])); + .addrb(rd_addr[BUF_SIZE-1:0]),.dib(0),.dob(rd_data_o[31:0])); always @(posedge wb_clk_i) if(wb_rst_i) @@ -167,7 +171,7 @@ module buffer_int2 sreg(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),.in(set_data), .out(ctrl),.changed(go)); - assign status = { {(16-BUF_SIZE){1'b0}},wr_addr, + assign status = { wr_addr, 8'b0,1'b0,rd_idle,rd_error,rd_done, 1'b0,wr_idle,wr_error,wr_done}; endmodule // buffer_int2 diff --git a/fpga/usrp2/fifo/dsp_framer36.v b/fpga/usrp2/fifo/dsp_framer36.v index f7d7fb68e..c2ae8f96c 100644 --- a/fpga/usrp2/fifo/dsp_framer36.v +++ b/fpga/usrp2/fifo/dsp_framer36.v @@ -2,98 +2,67 @@ // Frame DSP packets with a header line to be handled by the protocol machine module dsp_framer36 - #(parameter BUF_SIZE = 9, parameter PORT_SEL = 0) - ( - input clk, input rst, input clr, - input [35:0] inp_data, input inp_valid, output inp_ready, - output [35:0] out_data, output out_valid, input out_ready - ); + #(parameter BUF_SIZE = 9, + parameter PORT_SEL = 0) + (input clk, input reset, input clear, + input [35:0] data_i, input src_rdy_i, output dst_rdy_o, + output [35:0] data_o, output src_rdy_o, input dst_rdy_i); - localparam DSP_FRM_STATE_WAIT_SOF = 0; - localparam DSP_FRM_STATE_WAIT_EOF = 1; - localparam DSP_FRM_STATE_WRITE_HDR = 2; - localparam DSP_FRM_STATE_WRITE = 3; + wire dfifo_in_dst_rdy, dfifo_in_src_rdy, dfifo_out_dst_rdy, dfifo_out_src_rdy; + wire tfifo_in_dst_rdy, tfifo_in_src_rdy, tfifo_out_dst_rdy, tfifo_out_src_rdy; - reg [1:0] dsp_frm_state; - reg [BUF_SIZE-1:0] dsp_frm_addr; - reg [BUF_SIZE-1:0] dsp_frm_count; - wire [BUF_SIZE-1:0] dsp_frm_addr_next = dsp_frm_addr + 1'b1; + wire do_xfer_in = dfifo_in_src_rdy & dfifo_in_dst_rdy; + wire do_xfer_out = src_rdy_o & dst_rdy_i; + + wire have_space = dfifo_in_dst_rdy & tfifo_in_dst_rdy; + reg [15:0] pkt_len_in, pkt_len_out; + wire [15:0] tfifo_data; + wire [35:0] dfifo_out_data; + + assign dst_rdy_o = have_space; + assign dfifo_in_src_rdy = src_rdy_i & have_space; + + fifo_cascade #(.WIDTH(36), .SIZE(BUF_SIZE)) dfifo + (.clk(clk), .reset(reset), .clear(clear), + .datain(data_i), .src_rdy_i(dfifo_in_src_rdy), .dst_rdy_o(dfifo_in_dst_rdy), + .dataout(dfifo_out_data), .src_rdy_o(dfifo_out_src_rdy), .dst_rdy_i(dfifo_out_dst_rdy) ); - //DSP input stream ready in the following states - assign inp_ready = ( - dsp_frm_state == DSP_FRM_STATE_WAIT_SOF || - dsp_frm_state == DSP_FRM_STATE_WAIT_EOF - )? 1'b1 : 1'b0; + fifo_short #(.WIDTH(16)) tfifo + (.clk(clk), .reset(reset), .clear(clear), + .datain(pkt_len_in), .src_rdy_i(tfifo_in_src_rdy), .dst_rdy_o(tfifo_in_dst_rdy), + .dataout(tfifo_data), .src_rdy_o(tfifo_out_src_rdy), .dst_rdy_i(tfifo_out_dst_rdy), + .space(), .occupied() ); - //DSP framer output data mux (header or BRAM): - //The header is generated here from the count. - wire [31:0] dsp_frm_data_bram; - wire [15:0] dsp_frm_bytes = {dsp_frm_count, 2'b00}; - wire [1:0] port_sel_bits = PORT_SEL; - assign out_data = - (dsp_frm_state == DSP_FRM_STATE_WRITE_HDR)? {4'b0001, 13'b0, port_sel_bits, 1'b1, dsp_frm_bytes} : ( - (dsp_frm_addr == dsp_frm_count) ? {4'b0010, dsp_frm_data_bram} : ( - {4'b0000, dsp_frm_data_bram})); - assign out_valid = ( - (dsp_frm_state == DSP_FRM_STATE_WRITE_HDR) || - (dsp_frm_state == DSP_FRM_STATE_WRITE) - )? 1'b1 : 1'b0; + // FIXME won't handle single-line packets, will show wrong length + always @(posedge clk) + if(reset | clear) + pkt_len_in <= 0; + else if(do_xfer_in) + if(data_i[32]) // sof + pkt_len_in <= 2; // fixes off by one since number is stored before increment + else + pkt_len_in <= pkt_len_in + 1; - RAMB16_S36_S36 dsp_frm_buff( - //port A = DSP input interface (writes to BRAM) - .DOA(),.ADDRA(dsp_frm_addr),.CLKA(clk),.DIA(inp_data[31:0]),.DIPA(4'h0), - .ENA(inp_ready & inp_valid),.SSRA(0),.WEA(inp_ready & inp_valid), - //port B = DSP framer interface (reads from BRAM) - .DOB(dsp_frm_data_bram),.ADDRB(dsp_frm_addr),.CLKB(clk),.DIB(36'b0),.DIPB(4'h0), - .ENB(out_ready & out_valid),.SSRB(0),.WEB(1'b0) - ); + assign tfifo_in_src_rdy = do_xfer_in & data_i[33]; // store length when at eof in + assign tfifo_out_dst_rdy = do_xfer_out & data_o[33]; // remove length from list at eof out - always @(posedge clk) - if(rst | clr) begin - dsp_frm_state <= DSP_FRM_STATE_WAIT_SOF; - dsp_frm_addr <= 0; - end - else begin - case(dsp_frm_state) - DSP_FRM_STATE_WAIT_SOF: begin - if (inp_ready & inp_valid & inp_data[32]) begin - dsp_frm_addr <= dsp_frm_addr_next; - dsp_frm_state <= DSP_FRM_STATE_WAIT_EOF; - end - end + always @(posedge clk) + if(reset | clear) + pkt_len_out <= 0; + else if(do_xfer_out) + if(dfifo_out_data[33]) // eof + pkt_len_out <= 0; + else + pkt_len_out <= pkt_len_out + 1; + + assign dfifo_out_dst_rdy = do_xfer_out & (pkt_len_out != 0); - DSP_FRM_STATE_WAIT_EOF: begin - if (inp_ready & inp_valid) begin - if (inp_data[33]) begin - dsp_frm_count <= dsp_frm_addr_next; - dsp_frm_addr <= 0; - dsp_frm_state <= DSP_FRM_STATE_WRITE_HDR; - end - else begin - dsp_frm_addr <= dsp_frm_addr_next; - end - end - end + wire [1:0] port_sel_bits = PORT_SEL; + + assign data_o = (pkt_len_out == 0) ? {4'b0001, 13'b0, port_sel_bits, 1'b1, tfifo_data[13:0],2'b00} : + (pkt_len_out == 1) ? {4'b0000, dfifo_out_data[31:16],tfifo_data} : + {dfifo_out_data[35:33], 1'b0, dfifo_out_data[31:0] }; - DSP_FRM_STATE_WRITE_HDR: begin - if (out_ready & out_valid) begin - dsp_frm_addr <= dsp_frm_addr_next; - dsp_frm_state <= DSP_FRM_STATE_WRITE; - end - end - - DSP_FRM_STATE_WRITE: begin - if (out_ready & out_valid) begin - if (out_data[33]) begin - dsp_frm_addr <= 0; - dsp_frm_state <= DSP_FRM_STATE_WAIT_SOF; - end - else begin - dsp_frm_addr <= dsp_frm_addr_next; - end - end - end - endcase //dsp_frm_state - end - -endmodule //dsp_framer36 + assign src_rdy_o = dfifo_out_src_rdy & tfifo_out_src_rdy; + +endmodule // dsp_framer36 diff --git a/fpga/usrp2/fifo/fifo18_to_fifo36.v b/fpga/usrp2/fifo/fifo18_to_fifo36.v deleted file mode 100644 index 25bb215a1..000000000 --- a/fpga/usrp2/fifo/fifo18_to_fifo36.v +++ /dev/null @@ -1,20 +0,0 @@ - -// For now just assume FIFO18 is same as FIFO19 without occupancy bit - -module fifo18_to_fifo36 - (input clk, input reset, input clear, - input [17:0] f18_datain, - input f18_src_rdy_i, - output f18_dst_rdy_o, - - output [35:0] f36_dataout, - output f36_src_rdy_o, - input f36_dst_rdy_i - ); - - fifo19_to_fifo36 fifo19_to_fifo36 - (.clk(clk), .reset(reset), .clear(clear), - .f19_datain({1'b0,f18_datain}), .f19_src_rdy_i(f18_src_rdy_i), .f19_dst_rdy_o(f18_dst_rdy_o), - .f36_dataout(f36_dataout), .f36_src_rdy_o(f36_src_rdy_o), .f36_dst_rdy_i(f36_dst_rdy_i) ); - -endmodule // fifo18_to_fifo36 diff --git a/fpga/usrp2/fifo/fifo19_to_fifo36.v b/fpga/usrp2/fifo/fifo19_to_fifo36.v index ae2edddc7..502821435 100644 --- a/fpga/usrp2/fifo/fifo19_to_fifo36.v +++ b/fpga/usrp2/fifo/fifo19_to_fifo36.v @@ -15,60 +15,73 @@ module fifo19_to_fifo36 input f36_dst_rdy_i, output [31:0] debug ); - - reg f36_sof, f36_eof; - reg [1:0] f36_occ; + // Shortfifo on input to guarantee no deadlock + wire [18:0] f19_data_int; + wire f19_src_rdy_int, f19_dst_rdy_int; + + fifo_short #(.WIDTH(19)) head_fifo + (.clk(clk),.reset(reset),.clear(clear), + .datain(f19_datain), .src_rdy_i(f19_src_rdy_i), .dst_rdy_o(f19_dst_rdy_o), + .dataout(f19_data_int), .src_rdy_o(f19_src_rdy_int), .dst_rdy_i(f19_dst_rdy_int), + .space(),.occupied() ); + + // Actual f19 to f36 which could deadlock if not connected to shortfifos + reg f36_sof_int, f36_eof_int; + reg [1:0] f36_occ_int; + wire [35:0] f36_data_int; + wire f36_src_rdy_int, f36_dst_rdy_int; + reg [1:0] state; reg [15:0] dat0, dat1; - wire f19_sof = f19_datain[16]; - wire f19_eof = f19_datain[17]; - wire f19_occ = f19_datain[18]; + wire f19_sof_int = f19_data_int[16]; + wire f19_eof_int = f19_data_int[17]; + wire f19_occ_int = f19_data_int[18]; - wire xfer_out = f36_src_rdy_o & f36_dst_rdy_i; + wire xfer_out = f36_src_rdy_int & f36_dst_rdy_int; always @(posedge clk) - if(f19_src_rdy_i & ((state==0)|xfer_out)) - f36_sof <= f19_sof; + if(f19_src_rdy_int & ((state==0)|xfer_out)) + f36_sof_int <= f19_sof_int; always @(posedge clk) - if(f19_src_rdy_i & ((state != 2)|xfer_out)) - f36_eof <= f19_eof; + if(f19_src_rdy_int & ((state != 2)|xfer_out)) + f36_eof_int <= f19_eof_int; always @(posedge clk) if(reset) begin state <= 0; - f36_occ <= 0; + f36_occ_int <= 0; end else - if(f19_src_rdy_i) + if(f19_src_rdy_int) case(state) 0 : begin - dat0 <= f19_datain; - if(f19_eof) + dat0 <= f19_data_int; + if(f19_eof_int) begin state <= 2; - f36_occ <= f19_occ ? 2'b01 : 2'b10; + f36_occ_int <= f19_occ_int ? 2'b01 : 2'b10; end else state <= 1; end 1 : begin - dat1 <= f19_datain; + dat1 <= f19_data_int; state <= 2; - if(f19_eof) - f36_occ <= f19_occ ? 2'b11 : 2'b00; + if(f19_eof_int) + f36_occ_int <= f19_occ_int ? 2'b11 : 2'b00; end 2 : if(xfer_out) begin - dat0 <= f19_datain; - if(f19_eof) // remain in state 2 if we are at eof - f36_occ <= f19_occ ? 2'b01 : 2'b10; + dat0 <= f19_data_int; + if(f19_eof_int) // remain in state 2 if we are at eof + f36_occ_int <= f19_occ_int ? 2'b01 : 2'b10; else state <= 1; end @@ -77,14 +90,21 @@ module fifo19_to_fifo36 if(xfer_out) begin state <= 0; - f36_occ <= 0; + f36_occ_int <= 0; end - assign f19_dst_rdy_o = xfer_out | (state != 2); - assign f36_dataout = LE ? {f36_occ,f36_eof,f36_sof,dat1,dat0} : - {f36_occ,f36_eof,f36_sof,dat0,dat1}; - assign f36_src_rdy_o = (state == 2); + assign f19_dst_rdy_int = xfer_out | (state != 2); + assign f36_data_int = LE ? {f36_occ_int,f36_eof_int,f36_sof_int,dat1,dat0} : + {f36_occ_int,f36_eof_int,f36_sof_int,dat0,dat1}; + assign f36_src_rdy_int = (state == 2); assign debug = state; + + // Shortfifo on output to guarantee no deadlock + fifo_short #(.WIDTH(36)) tail_fifo + (.clk(clk),.reset(reset),.clear(clear), + .datain(f36_data_int), .src_rdy_i(f36_src_rdy_int), .dst_rdy_o(f36_dst_rdy_int), + .dataout(f36_dataout), .src_rdy_o(f36_src_rdy_o), .dst_rdy_i(f36_dst_rdy_i), + .space(),.occupied() ); endmodule // fifo19_to_fifo36 diff --git a/fpga/usrp2/fifo/fifo36_mux.v b/fpga/usrp2/fifo/fifo36_mux.v index c6fd40f27..7f0f803ff 100644 --- a/fpga/usrp2/fifo/fifo36_mux.v +++ b/fpga/usrp2/fifo/fifo36_mux.v @@ -10,6 +10,19 @@ module fifo36_mux input [35:0] data1_i, input src1_rdy_i, output dst1_rdy_o, output [35:0] data_o, output src_rdy_o, input dst_rdy_i); + wire [35:0] data0_int, data1_int; + wire src0_rdy_int, dst0_rdy_int, src1_rdy_int, dst1_rdy_int; + + fifo_short #(.WIDTH(36)) mux_fifo_in0 + (.clk(clk), .reset(reset), .clear(clear), + .datain(data0_i), .src_rdy_i(src0_rdy_i), .dst_rdy_o(dst0_rdy_o), + .dataout(data0_int), .src_rdy_o(src0_rdy_int), .dst_rdy_i(dst0_rdy_int)); + + fifo_short #(.WIDTH(36)) mux_fifo_in1 + (.clk(clk), .reset(reset), .clear(clear), + .datain(data1_i), .src_rdy_i(src1_rdy_i), .dst_rdy_o(dst1_rdy_o), + .dataout(data1_int), .src_rdy_o(src1_rdy_int), .dst_rdy_i(dst1_rdy_int)); + localparam MUX_IDLE0 = 0; localparam MUX_DATA0 = 1; localparam MUX_IDLE1 = 2; @@ -17,8 +30,8 @@ module fifo36_mux reg [1:0] state; - wire eof0 = data0_i[33]; - wire eof1 = data1_i[33]; + wire eof0 = data0_int[33]; + wire eof1 = data1_int[33]; wire [35:0] data_int; wire src_rdy_int, dst_rdy_int; @@ -29,33 +42,33 @@ module fifo36_mux else case(state) MUX_IDLE0 : - if(src0_rdy_i) + if(src0_rdy_int) state <= MUX_DATA0; - else if(src1_rdy_i) + else if(src1_rdy_int) state <= MUX_DATA1; MUX_DATA0 : - if(src0_rdy_i & dst_rdy_int & eof0) + if(src0_rdy_int & dst_rdy_int & eof0) state <= prio ? MUX_IDLE0 : MUX_IDLE1; MUX_IDLE1 : - if(src1_rdy_i) + if(src1_rdy_int) state <= MUX_DATA1; - else if(src0_rdy_i) + else if(src0_rdy_int) state <= MUX_DATA0; MUX_DATA1 : - if(src1_rdy_i & dst_rdy_int & eof1) + if(src1_rdy_int & dst_rdy_int & eof1) state <= MUX_IDLE0; default : state <= MUX_IDLE0; endcase // case (state) - assign dst0_rdy_o = (state==MUX_DATA0) ? dst_rdy_int : 0; - assign dst1_rdy_o = (state==MUX_DATA1) ? dst_rdy_int : 0; - assign src_rdy_int = (state==MUX_DATA0) ? src0_rdy_i : (state==MUX_DATA1) ? src1_rdy_i : 0; - assign data_int = (state==MUX_DATA0) ? data0_i : data1_i; + assign dst0_rdy_int = (state==MUX_DATA0) ? dst_rdy_int : 0; + assign dst1_rdy_int = (state==MUX_DATA1) ? dst_rdy_int : 0; + assign src_rdy_int = (state==MUX_DATA0) ? src0_rdy_int : (state==MUX_DATA1) ? src1_rdy_int : 0; + assign data_int = (state==MUX_DATA0) ? data0_int : data1_int; fifo_short #(.WIDTH(36)) mux_fifo (.clk(clk), .reset(reset), .clear(clear), diff --git a/fpga/usrp2/fifo/fifo36_to_fifo19.v b/fpga/usrp2/fifo/fifo36_to_fifo19.v index e016fe2c6..0e9b2d442 100644 --- a/fpga/usrp2/fifo/fifo36_to_fifo19.v +++ b/fpga/usrp2/fifo/fifo36_to_fifo19.v @@ -13,25 +13,37 @@ module fifo36_to_fifo19 output [18:0] f19_dataout, output f19_src_rdy_o, input f19_dst_rdy_i ); - - wire f36_sof = f36_datain[32]; - wire f36_eof = f36_datain[33]; - wire [1:0] f36_occ = f36_datain[35:34]; + + wire [18:0] f19_data_int; + wire f19_src_rdy_int, f19_dst_rdy_int; + wire [35:0] f36_data_int; + wire f36_src_rdy_int, f36_dst_rdy_int; + + // Shortfifo on input to guarantee no deadlock + fifo_short #(.WIDTH(36)) head_fifo + (.clk(clk),.reset(reset),.clear(clear), + .datain(f36_datain), .src_rdy_i(f36_src_rdy_i), .dst_rdy_o(f36_dst_rdy_o), + .dataout(f36_data_int), .src_rdy_o(f36_src_rdy_int), .dst_rdy_i(f36_dst_rdy_int), + .space(),.occupied() ); + + // Main fifo36_to_fifo19, needs shortfifos to guarantee no deadlock + wire [1:0] f36_occ_int = f36_data_int[35:34]; + wire f36_sof_int = f36_data_int[32]; + wire f36_eof_int = f36_data_int[33]; reg phase; + wire half_line = f36_eof_int & ((f36_occ_int==1)|(f36_occ_int==2)); - wire half_line = f36_eof & ((f36_occ==1)|(f36_occ==2)); - - assign f19_dataout[15:0] = (LE ^ phase) ? f36_datain[15:0] : f36_datain[31:16]; - assign f19_dataout[16] = phase ? 0 : f36_sof; - assign f19_dataout[17] = phase ? f36_eof : half_line; - assign f19_dataout[18] = f19_dataout[17] & ((f36_occ==1)|(f36_occ==3)); + assign f19_data_int[15:0] = (LE ^ phase) ? f36_data_int[15:0] : f36_data_int[31:16]; + assign f19_data_int[16] = phase ? 0 : f36_sof_int; + assign f19_data_int[17] = phase ? f36_eof_int : half_line; + assign f19_data_int[18] = f19_data_int[17] & ((f36_occ_int==1)|(f36_occ_int==3)); - assign f19_src_rdy_o = f36_src_rdy_i; - assign f36_dst_rdy_o = (phase | half_line) & f19_dst_rdy_i; + assign f19_src_rdy_int = f36_src_rdy_int; + assign f36_dst_rdy_int = (phase | half_line) & f19_dst_rdy_int; - wire f19_xfer = f19_src_rdy_o & f19_dst_rdy_i; - wire f36_xfer = f36_src_rdy_i & f36_dst_rdy_o; + wire f19_xfer = f19_src_rdy_int & f19_dst_rdy_int; + wire f36_xfer = f36_src_rdy_int & f36_dst_rdy_int; always @(posedge clk) if(reset) @@ -41,5 +53,11 @@ module fifo36_to_fifo19 else if(f19_xfer) phase <= 1; - + // Shortfifo on output to guarantee no deadlock + fifo_short #(.WIDTH(19)) tail_fifo + (.clk(clk),.reset(reset),.clear(clear), + .datain(f19_data_int), .src_rdy_i(f19_src_rdy_int), .dst_rdy_o(f19_dst_rdy_int), + .dataout(f19_dataout), .src_rdy_o(f19_src_rdy_o), .dst_rdy_i(f19_dst_rdy_i), + .space(),.occupied() ); + endmodule // fifo36_to_fifo19 diff --git a/fpga/usrp2/fifo/fifo36_to_fifo72.v b/fpga/usrp2/fifo/fifo36_to_fifo72.v new file mode 100644 index 000000000..038eda9e9 --- /dev/null +++ b/fpga/usrp2/fifo/fifo36_to_fifo72.v @@ -0,0 +1,125 @@ + +// Parameter LE tells us if we are little-endian. +// Little-endian means send lower 16 bits first. +// Default is big endian (network order), send upper bits first. + +module fifo36_to_fifo72 + #(parameter LE=0) + (input clk, input reset, input clear, + input [35:0] f36_datain, + input f36_src_rdy_i, + output f36_dst_rdy_o, + + output [71:0] f72_dataout, + output f72_src_rdy_o, + input f72_dst_rdy_i, + output [31:0] debug + ); + + // Shortfifo on input to guarantee no deadlock + wire [35:0] f36_data_int; + wire f36_src_rdy_int, f36_dst_rdy_int; + + fifo_short #(.WIDTH(36)) head_fifo + (.clk(clk),.reset(reset),.clear(clear), + .datain(f36_datain), .src_rdy_i(f36_src_rdy_i), .dst_rdy_o(f36_dst_rdy_o), + .dataout(f36_data_int), .src_rdy_o(f36_src_rdy_int), .dst_rdy_i(f36_dst_rdy_int), + .space(),.occupied() ); + + // Actual f36 to f72 which could deadlock if not connected to shortfifos + reg f72_sof_int, f72_eof_int; + reg [2:0] f72_occ_int; + wire [71:0] f72_data_int; + wire f72_src_rdy_int, f72_dst_rdy_int; + + reg [1:0] state; + reg [31:0] dat0, dat1; + + wire f36_sof_int = f36_data_int[32]; + wire f36_eof_int = f36_data_int[33]; + wire [1:0] f36_occ_int = f36_data_int[35:34]; + + wire xfer_out = f72_src_rdy_int & f72_dst_rdy_int; + + always @(posedge clk) + if(f36_src_rdy_int & ((state==0)|xfer_out)) + f72_sof_int <= f36_sof_int; + + always @(posedge clk) + if(f36_src_rdy_int & ((state != 2)|xfer_out)) + f72_eof_int <= f36_eof_int; + + always @(posedge clk) + if(reset) + begin + state <= 0; + f72_occ_int <= 0; + end + else + if(f36_src_rdy_int) + case(state) + 0 : + begin + dat0 <= f36_data_int; + if(f36_eof_int) + begin + state <= 2; + case (f36_occ_int) + 0 : f72_occ_int <= 3'd4; + 1 : f72_occ_int <= 3'd1; + 2 : f72_occ_int <= 3'd2; + 3 : f72_occ_int <= 3'd3; + endcase // case (f36_occ_int) + end + else + state <= 1; + end + 1 : + begin + dat1 <= f36_data_int; + state <= 2; + if(f36_eof_int) + case (f36_occ_int) + 0 : f72_occ_int <= 3'd0; + 1 : f72_occ_int <= 3'd5; + 2 : f72_occ_int <= 3'd6; + 3 : f72_occ_int <= 3'd7; + endcase // case (f36_occ_int) + end + 2 : + if(xfer_out) + begin + dat0 <= f36_data_int; + if(f36_eof_int) // remain in state 2 if we are at eof + case (f36_occ_int) + 0 : f72_occ_int <= 3'd4; + 1 : f72_occ_int <= 3'd1; + 2 : f72_occ_int <= 3'd2; + 3 : f72_occ_int <= 3'd3; + endcase // case (f36_occ_int) + else + state <= 1; + end + endcase // case(state) + else + if(xfer_out) + begin + state <= 0; + f72_occ_int <= 0; + end + + assign f36_dst_rdy_int = xfer_out | (state != 2); + assign f72_data_int = LE ? {3'b000,f72_occ_int[2:0],f72_eof_int,f72_sof_int,dat1,dat0} : + {3'b000,f72_occ_int[2:0],f72_eof_int,f72_sof_int,dat0,dat1}; + assign f72_src_rdy_int = (state == 2); + + assign debug = state; + + // Shortfifo on output to guarantee no deadlock + fifo_short #(.WIDTH(72)) tail_fifo + (.clk(clk),.reset(reset),.clear(clear), + .datain(f72_data_int), .src_rdy_i(f72_src_rdy_int), .dst_rdy_o(f72_dst_rdy_int), + .dataout(f72_dataout), .src_rdy_o(f72_src_rdy_o), .dst_rdy_i(f72_dst_rdy_i), + .space(),.occupied() ); + +endmodule // fifo36_to_fifo72 diff --git a/fpga/usrp2/fifo/fifo36_to_ll8.v b/fpga/usrp2/fifo/fifo36_to_ll8.v index 9604d0e38..390e49962 100644 --- a/fpga/usrp2/fifo/fifo36_to_ll8.v +++ b/fpga/usrp2/fifo/fifo36_to_ll8.v @@ -5,25 +5,33 @@ module fifo36_to_ll8 input f36_src_rdy_i, output f36_dst_rdy_o, - output reg [7:0] ll_data, - output ll_sof_n, - output ll_eof_n, - output ll_src_rdy_n, - input ll_dst_rdy_n, + output [7:0] ll_data, + output ll_sof, + output ll_eof, + output ll_src_rdy, + input ll_dst_rdy, output [31:0] debug); - wire ll_sof, ll_eof, ll_src_rdy; - assign ll_sof_n = ~ll_sof; - assign ll_eof_n = ~ll_eof; - assign ll_src_rdy_n = ~ll_src_rdy; - wire ll_dst_rdy = ~ll_dst_rdy_n; - - wire f36_sof = f36_data[32]; - wire f36_eof = f36_data[33]; - wire f36_occ = f36_data[35:34]; - wire advance, end_early; - reg [1:0] state; + // Shortfifo on input to guarantee no deadlock + wire [35:0] f36_data_int; + wire f36_src_rdy_int, f36_dst_rdy_int; + reg [7:0] ll_data_int; + wire ll_sof_int, ll_eof_int, ll_src_rdy_int, ll_dst_rdy_int; + + fifo_short #(.WIDTH(36)) head_fifo + (.clk(clk),.reset(reset),.clear(clear), + .datain(f36_data), .src_rdy_i(f36_src_rdy_i), .dst_rdy_o(f36_dst_rdy_o), + .dataout(f36_data_int), .src_rdy_o(f36_src_rdy_int), .dst_rdy_i(f36_dst_rdy_int), + .space(),.occupied() ); + + // Actual fifo36 to ll8, can deadlock if not connected to shortfifo + wire [1:0] f36_occ_int = f36_data_int[35:34]; + wire f36_sof_int = f36_data_int[32]; + wire f36_eof_int = f36_data_int[33]; + wire advance, end_early; + reg [1:0] state; + assign debug = {29'b0,state}; always @(posedge clk) @@ -31,29 +39,37 @@ module fifo36_to_ll8 state <= 0; else if(advance) - if(ll_eof) + if(ll_eof_int) state <= 0; else state <= state + 1; always @* case(state) - 0 : ll_data = f36_data[31:24]; - 1 : ll_data = f36_data[23:16]; - 2 : ll_data = f36_data[15:8]; - 3 : ll_data = f36_data[7:0]; - default : ll_data = f36_data[31:24]; + 0 : ll_data_int = f36_data_int[31:24]; + 1 : ll_data_int = f36_data_int[23:16]; + 2 : ll_data_int = f36_data_int[15:8]; + 3 : ll_data_int = f36_data_int[7:0]; + default : ll_data_int = f36_data_int[31:24]; endcase // case (state) - assign ll_sof = (state==0) & f36_sof; - assign ll_eof = f36_eof & (((state==0)&(f36_occ==1)) | - ((state==1)&(f36_occ==2)) | - ((state==2)&(f36_occ==3)) | - (state==3)); + assign ll_sof_int = (state==0) & f36_sof_int; + assign ll_eof_int = f36_eof_int & (((state==0)&(f36_occ_int==1)) | + ((state==1)&(f36_occ_int==2)) | + ((state==2)&(f36_occ_int==3)) | + (state==3)); - assign ll_src_rdy = f36_src_rdy_i; - - assign advance = ll_src_rdy & ll_dst_rdy; - assign f36_dst_rdy_o = advance & ((state==3)|ll_eof); + assign ll_src_rdy_int = f36_src_rdy_int; -endmodule // ll8_to_fifo36 + assign advance = ll_src_rdy_int & ll_dst_rdy_int; + assign f36_dst_rdy_int= advance & ((state==3)|ll_eof_int); + + // Short FIFO on output to guarantee no deadlock + ll8_shortfifo tail_fifo + (.clk(clk), .reset(reset), .clear(clear), + .datain(ll_data_int), .sof_i(ll_sof_int), .eof_i(ll_eof_int), + .error_i(0), .src_rdy_i(ll_src_rdy_int), .dst_rdy_o(ll_dst_rdy_int), + .dataout(ll_data), .sof_o(ll_sof), .eof_o(ll_eof), + .error_o(), .src_rdy_o(ll_src_rdy), .dst_rdy_i(ll_dst_rdy)); + +endmodule // fifo36_to_ll8 diff --git a/fpga/usrp2/fifo/fifo72_to_fifo36.v b/fpga/usrp2/fifo/fifo72_to_fifo36.v new file mode 100644 index 000000000..1b3bc3ab7 --- /dev/null +++ b/fpga/usrp2/fifo/fifo72_to_fifo36.v @@ -0,0 +1,63 @@ + +// Parameter LE tells us if we are little-endian. +// Little-endian means send lower 16 bits first. +// Default is big endian (network order), send upper bits first. + +module fifo72_to_fifo36 + #(parameter LE=0) + (input clk, input reset, input clear, + input [71:0] f72_datain, + input f72_src_rdy_i, + output f72_dst_rdy_o, + + output [35:0] f36_dataout, + output f36_src_rdy_o, + input f36_dst_rdy_i ); + + wire [35:0] f36_data_int; + wire f36_src_rdy_int, f36_dst_rdy_int; + wire [71:0] f72_data_int; + wire f72_src_rdy_int, f72_dst_rdy_int; + + // Shortfifo on input to guarantee no deadlock + fifo_short #(.WIDTH(72)) head_fifo + (.clk(clk),.reset(reset),.clear(clear), + .datain(f72_datain), .src_rdy_i(f72_src_rdy_i), .dst_rdy_o(f72_dst_rdy_o), + .dataout(f72_data_int), .src_rdy_o(f72_src_rdy_int), .dst_rdy_i(f72_dst_rdy_int), + .space(),.occupied() ); + + // Main fifo72_to_fifo36, needs shortfifos to guarantee no deadlock + wire [2:0] f72_occ_int = f72_data_int[68:66]; + wire f72_sof_int = f72_data_int[64]; + wire f72_eof_int = f72_data_int[65]; + + reg phase; + wire half_line = f72_eof_int & ( (f72_occ_int==1)|(f72_occ_int==2)|(f72_occ_int==3)|(f72_occ_int==4) ); + + assign f36_data_int[31:0] = (LE ^ phase) ? f72_data_int[31:0] : f72_data_int[63:32]; + assign f36_data_int[32] = phase ? 0 : f72_sof_int; + assign f36_data_int[33] = phase ? f72_eof_int : half_line; + assign f36_data_int[35:34] = f36_data_int[33] ? f72_occ_int[1:0] : 2'b00; + + assign f36_src_rdy_int = f72_src_rdy_int; + assign f72_dst_rdy_int = (phase | half_line) & f36_dst_rdy_int; + + wire f36_xfer = f36_src_rdy_int & f36_dst_rdy_int; + wire f72_xfer = f72_src_rdy_int & f72_dst_rdy_int; + + always @(posedge clk) + if(reset) + phase <= 0; + else if(f72_xfer) + phase <= 0; + else if(f36_xfer) + phase <= 1; + + // Shortfifo on output to guarantee no deadlock + fifo_short #(.WIDTH(36)) tail_fifo + (.clk(clk),.reset(reset),.clear(clear), + .datain(f36_data_int), .src_rdy_i(f36_src_rdy_int), .dst_rdy_o(f36_dst_rdy_int), + .dataout(f36_dataout), .src_rdy_o(f36_src_rdy_o), .dst_rdy_i(f36_dst_rdy_i), + .space(),.occupied() ); + +endmodule // fifo72_to_fifo36 diff --git a/fpga/usrp2/fifo/fifo_pacer.v b/fpga/usrp2/fifo/fifo_pacer.v new file mode 100644 index 000000000..1bf03ab6e --- /dev/null +++ b/fpga/usrp2/fifo/fifo_pacer.v @@ -0,0 +1,24 @@ + + +module fifo_pacer + (input clk, + input reset, + input [7:0] rate, + input enable, + input src1_rdy_i, output dst1_rdy_o, + output src2_rdy_o, input dst2_rdy_i, + output underrun, overrun); + + wire strobe; + + cic_strober strober (.clock(clk), .reset(reset), .enable(enable), + .rate(rate), .strobe_fast(1), .strobe_slow(strobe)); + + wire all_ready = src1_rdy_i & dst2_rdy_i; + assign dst1_rdy_o = all_ready & strobe; + assign src2_rdy_o = dst1_rdy_o; + + assign underrun = strobe & ~src1_rdy_i; + assign overrun = strobe & ~dst2_rdy_i; + +endmodule // fifo_pacer diff --git a/fpga/usrp2/fifo/fifo_tb.v b/fpga/usrp2/fifo/fifo_tb.v index 327da4700..3e2862a70 100644 --- a/fpga/usrp2/fifo/fifo_tb.v +++ b/fpga/usrp2/fifo/fifo_tb.v @@ -1,4 +1,4 @@ -module fifo_new_tb(); +module fifo_tb(); reg clk = 0; reg rst = 1; @@ -9,169 +9,47 @@ module fifo_new_tb(); reg [31:0] f36_data = 0; reg [1:0] f36_occ = 0; reg f36_sof = 0, f36_eof = 0; - - wire [35:0] f36_in = {f36_occ,f36_eof,f36_sof,f36_data}; - reg src_rdy_f36i = 0; - wire dst_rdy_f36i; - - wire [35:0] f36_out, f36_out2; - wire src_rdy_f36o; - reg dst_rdy_f36o = 0; - - //fifo_cascade #(.WIDTH(36), .SIZE(4)) fifo_cascade36 - //fifo_long #(.WIDTH(36), .SIZE(4)) fifo_cascade36 - - wire i1_sr, i1_dr; - wire i2_sr, i2_dr; - wire i3_sr, i3_dr; - wire i7_sr, i7_dr; - - reg i4_dr = 0; - wire i4_sr; - - wire [35:0] i1, i4, i7; - wire [18:0] i2, i3; + reg f36_src_rdy; + wire f36_dst_rdy; wire [7:0] ll_data; - wire ll_src_rdy_n, ll_dst_rdy_n, ll_sof_n, ll_eof_n; + wire ll_src_rdy, ll_dst_rdy, ll_sof, ll_eof; wire [35:0] err_dat; wire err_src_rdy, err_dst_rdy; - reg trigger = 0; - initial #10000 trigger = 1; - - fifo_short #(.WIDTH(36)) fifo_short1 + fifo36_to_ll8 fifo36_to_ll8 (.clk(clk),.reset(rst),.clear(clear), - .datain(f36_in),.src_rdy_i(src_rdy_f36i),.dst_rdy_o(dst_rdy_f36i), - .dataout(i7),.src_rdy_o(i7_sr),.dst_rdy_i(i7_dr) ); + .f36_data({f36_occ,f36_eof,f36_sof,f36_data}),.f36_src_rdy_i(f36_src_rdy),.f36_dst_rdy_o(f36_dst_rdy), + .ll_data(ll_data),.ll_sof(ll_sof),.ll_eof(ll_eof), + .ll_src_rdy(ll_src_rdy),.ll_dst_rdy(ll_dst_rdy)); - gen_context_pkt #(.PROT_ENG_FLAGS(1)) gcp - (.clk(clk),.reset(rst),.clear(clear), - .trigger(trigger), .sent(), - .streamid(32'hDEAD_F00D), .vita_time(64'h01234567_89ABCDEF), .message(32'hBEEF_2940), - .data_o(err_dat), .src_rdy_o(err_src_rdy), .dst_rdy_i(err_dst_rdy)); - - fifo36_mux #(.prio(0)) fifo36_mux - (.clk(clk), .reset(rst), .clear(clear), - .data0_i(i7), .src0_rdy_i(i7_sr), .dst0_rdy_o(i7_dr), - .data1_i(err_dat), .src1_rdy_i(err_src_rdy), .dst1_rdy_o(err_dst_rdy), - .data_o(i1), .src_rdy_o(i1_sr), .dst_rdy_i(i1_dr)); + assign ll_dst_rdy = 1; - fifo36_to_fifo19 fifo36_to_fifo19 - (.clk(clk),.reset(rst),.clear(clear), - .f36_datain(i1),.f36_src_rdy_i(i1_sr),.f36_dst_rdy_o(i1_dr), - .f19_dataout(i2),.f19_src_rdy_o(i2_sr),.f19_dst_rdy_i(i2_dr) ); - - fifo19_to_ll8 fifo19_to_ll8 - (.clk(clk),.reset(rst),.clear(clear), - .f19_data(i2),.f19_src_rdy_i(i2_sr),.f19_dst_rdy_o(i2_dr), - .ll_data(ll_data),.ll_sof_n(ll_sof_n),.ll_eof_n(ll_eof_n), - .ll_src_rdy_n(ll_src_rdy_n),.ll_dst_rdy_n(ll_dst_rdy_n)); - - ll8_to_fifo19 ll8_to_fifo19 - (.clk(clk),.reset(rst),.clear(clear), - .ll_data(ll_data),.ll_sof_n(ll_sof_n),.ll_eof_n(ll_eof_n), - .ll_src_rdy_n(ll_src_rdy_n),.ll_dst_rdy_n(ll_dst_rdy_n), - .f19_data(i3),.f19_src_rdy_o(i3_sr),.f19_dst_rdy_i(i3_dr) ); - - fifo19_to_fifo36 fifo19_to_fifo36 - (.clk(clk),.reset(rst),.clear(clear), - .f19_datain(i3),.f19_src_rdy_i(i3_sr),.f19_dst_rdy_o(i3_dr), - .f36_dataout(i4),.f36_src_rdy_o(i4_sr),.f36_dst_rdy_i(i4_dr) ); - - task ReadFromFIFO36; - begin - $display("Read from FIFO36"); - #1 i4_dr <= 1; - while(1) - begin - while(~i4_sr) - @(posedge clk); - $display("Read: %h",i4); - @(posedge clk); - end - end - endtask // ReadFromFIFO36 - - reg [15:0] count; - task PutPacketInFIFO36; - input [31:0] data_start; - input [31:0] data_len; - begin - count <= 4; - src_rdy_f36i <= 1; - f36_data <= data_start; - f36_sof <= 1; - f36_eof <= 0; - f36_occ <= 0; - - $display("Put Packet in FIFO36"); - while(~dst_rdy_f36i) - @(posedge clk); - @(posedge clk); - $display("PPI_FIFO36: Entered First Line"); - f36_sof <= 0; - while(count+4 < data_len) - begin - f36_data <= f36_data + 32'h01010101; - count <= count + 4; - while(~dst_rdy_f36i) - @(posedge clk); - @(posedge clk); - $display("PPI_FIFO36: Entered New Line"); - end - f36_data <= f36_data + 32'h01010101; - f36_eof <= 1; - if(count + 4 == data_len) - f36_occ <= 0; - else if(count + 3 == data_len) - f36_occ <= 3; - else if(count + 2 == data_len) - f36_occ <= 2; - else - f36_occ <= 1; - while(~dst_rdy_f36i) - @(posedge clk); - @(posedge clk); - f36_occ <= 0; - f36_eof <= 0; - f36_data <= 0; - src_rdy_f36i <= 0; - $display("PPI_FIFO36: Entered Last Line"); - end - endtask // PutPacketInFIFO36 + always @(posedge clk) + if(ll_src_rdy) + $display("LL: SOF %d, EOF %d, DAT %x",ll_sof,ll_eof,ll_data); - initial $dumpfile("fifo_new_tb.vcd"); - initial $dumpvars(0,fifo_new_tb); + initial $dumpfile("fifo_tb.vcd"); + initial $dumpvars(0,fifo_tb); initial begin @(negedge rst); - //#10000; @(posedge clk); @(posedge clk); @(posedge clk); @(posedge clk); - ReadFromFIFO36; - end - - initial - begin - @(negedge rst); - @(posedge clk); - @(posedge clk); - PutPacketInFIFO36(32'hA0B0C0D0,12); - @(posedge clk); - @(posedge clk); - #10000; - @(posedge clk); - PutPacketInFIFO36(32'hE0F0A0B0,36); - @(posedge clk); + f36_src_rdy <= 1; + {f36_occ,f36_eof,f36_sof,f36_data} <= { 2'b00,1'b0,1'b1,32'h00010203}; @(posedge clk); + {f36_occ,f36_eof,f36_sof,f36_data} <= { 2'b00,1'b0,1'b0,32'h04050607}; @(posedge clk); + {f36_occ,f36_eof,f36_sof,f36_data} <= { 2'b00,1'b0,1'b0,32'h08090a0b}; @(posedge clk); + {f36_occ,f36_eof,f36_sof,f36_data} <= { 2'b11,1'b1,1'b0,32'h0c0d0e0f}; @(posedge clk); + f36_src_rdy <= 0; end - - initial #20000 $finish; + + initial #4000 $finish; endmodule // longfifo_tb diff --git a/fpga/usrp2/fifo/ll8_to_fifo19.v b/fpga/usrp2/fifo/ll8_to_fifo19.v index af3b91afb..ac8ac19a6 100644 --- a/fpga/usrp2/fifo/ll8_to_fifo19.v +++ b/fpga/usrp2/fifo/ll8_to_fifo19.v @@ -2,41 +2,47 @@ module ll8_to_fifo19 (input clk, input reset, input clear, input [7:0] ll_data, - input ll_sof_n, - input ll_eof_n, - input ll_src_rdy_n, - output ll_dst_rdy_n, + input ll_sof, + input ll_eof, + input ll_src_rdy, + output ll_dst_rdy, output [18:0] f19_data, output f19_src_rdy_o, input f19_dst_rdy_i ); + + // Short FIFO on input to guarantee no deadlock + wire [7:0] ll_data_int; + wire ll_sof_int, ll_eof_int, ll_src_rdy_int, ll_dst_rdy_int; + ll8_shortfifo head_fifo + (.clk(clk), .reset(reset), .clear(clear), + .datain(ll_data), .sof_i(ll_sof), .eof_i(ll_eof), + .error_i(0), .src_rdy_i(ll_src_rdy), .dst_rdy_o(ll_dst_rdy), + .dataout(ll_data_int), .sof_o(ll_sof_int), .eof_o(ll_eof_int), + .error_o(), .src_rdy_o(ll_src_rdy_int), .dst_rdy_i(ll_dst_rdy_int)); + + // Actual ll8_to_fifo19 which could deadlock if not connected to a shortfifo localparam XFER_EMPTY = 0; localparam XFER_HALF = 1; localparam XFER_HALF_WRITE = 3; - // Why anybody would use active low in an FPGA is beyond me... - wire ll_sof = ~ll_sof_n; - wire ll_eof = ~ll_eof_n; - wire ll_src_rdy = ~ll_src_rdy_n; - wire ll_dst_rdy; - assign ll_dst_rdy_n = ~ll_dst_rdy; - - wire xfer_out = f19_src_rdy_o & f19_dst_rdy_i; - wire xfer_in = ll_src_rdy & ll_dst_rdy; - - reg hold_sof; - wire f19_sof, f19_eof, f19_occ; + wire [18:0] f19_data_int; + wire f19_sof_int, f19_eof_int, f19_occ_int, f19_src_rdy_int, f19_dst_rdy_int; + + wire xfer_out = f19_src_rdy_int & f19_dst_rdy_int; + wire xfer_in = ll_src_rdy_int & ll_dst_rdy_int; + reg hold_sof; - reg [1:0] state; - reg [7:0] hold_reg; + reg [1:0] state; + reg [7:0] hold_reg; always @(posedge clk) - if(ll_src_rdy & (state==XFER_EMPTY)) - hold_reg <= ll_data; + if(ll_src_rdy_int & (state==XFER_EMPTY)) + hold_reg <= ll_data_int; always @(posedge clk) - if(ll_sof & (state==XFER_EMPTY)) + if(ll_sof_int & (state==XFER_EMPTY)) hold_sof <= 1; else if(xfer_out) hold_sof <= 0; @@ -47,27 +53,35 @@ module ll8_to_fifo19 else case(state) XFER_EMPTY : - if(ll_src_rdy) - if(ll_eof) + if(ll_src_rdy_int) + if(ll_eof_int) state <= XFER_HALF_WRITE; else state <= XFER_HALF; XFER_HALF : - if(ll_src_rdy & f19_dst_rdy_i) + if(ll_src_rdy_int & f19_dst_rdy_int) state <= XFER_EMPTY; XFER_HALF_WRITE : - if(f19_dst_rdy_i) + if(f19_dst_rdy_int) state <= XFER_EMPTY; endcase // case (state) - assign ll_dst_rdy = (state==XFER_EMPTY) | ((state==XFER_HALF)&f19_dst_rdy_i); - assign f19_src_rdy_o = (state==XFER_HALF_WRITE) | ((state==XFER_HALF)&ll_src_rdy); + assign ll_dst_rdy_int = (state==XFER_EMPTY) | ((state==XFER_HALF)&f19_dst_rdy_int); + assign f19_src_rdy_int= (state==XFER_HALF_WRITE) | ((state==XFER_HALF)&ll_src_rdy_int); - assign f19_sof = hold_sof | (ll_sof & (state==XFER_HALF)); - assign f19_eof = (state == XFER_HALF_WRITE) | ll_eof; - assign f19_occ = (state == XFER_HALF_WRITE); + assign f19_sof_int = hold_sof | (ll_sof_int & (state==XFER_HALF)); + assign f19_eof_int = (state == XFER_HALF_WRITE) | ll_eof_int; + assign f19_occ_int = (state == XFER_HALF_WRITE); - assign f19_data = {f19_occ,f19_eof,f19_sof,hold_reg,ll_data}; + assign f19_data_int = {f19_occ_int,f19_eof_int,f19_sof_int,hold_reg,ll_data_int}; + + // Shortfifo on output to guarantee no deadlock + fifo_short #(.WIDTH(19)) tail_fifo + (.clk(clk),.reset(reset),.clear(clear), + .datain(f19_data_int), .src_rdy_i(f19_src_rdy_int), .dst_rdy_o(f19_dst_rdy_int), + .dataout(f19_data), .src_rdy_o(f19_src_rdy_o), .dst_rdy_i(f19_dst_rdy_i), + .space(),.occupied() ); + endmodule // ll8_to_fifo19 diff --git a/fpga/usrp2/fifo/packet32_tb.v b/fpga/usrp2/fifo/packet32_tb.v new file mode 100644 index 000000000..82bb09c29 --- /dev/null +++ b/fpga/usrp2/fifo/packet32_tb.v @@ -0,0 +1,27 @@ + + +module packet32_tb(); + + wire [35:0] data; + wire src_rdy, dst_rdy; + + wire clear = 0; + reg clk = 0; + reg reset = 1; + + always #10 clk <= ~clk; + initial #1000 reset <= 0; + + initial $dumpfile("packet32_tb.vcd"); + initial $dumpvars(0,packet32_tb); + + wire [31:0] total, crc_err, seq_err, len_err; + + packet_generator32 pkt_gen (.clk(clk), .reset(reset), .clear(clear), + .data_o(data), .src_rdy_o(src_rdy), .dst_rdy_i(dst_rdy)); + + packet_verifier32 pkt_ver (.clk(clk), .reset(reset), .clear(clear), + .data_i(data), .src_rdy_i(src_rdy), .dst_rdy_o(dst_rdy), + .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err)); + +endmodule // packet32_tb diff --git a/fpga/usrp2/fifo/packet_dispatcher36_x3.v b/fpga/usrp2/fifo/packet_dispatcher36_x3.v new file mode 100644 index 000000000..fd762d061 --- /dev/null +++ b/fpga/usrp2/fifo/packet_dispatcher36_x3.v @@ -0,0 +1,270 @@ +// +// Copyright 2011 Ettus Research LLC +// +// Packet dispatcher with fifo36 interface and 3 outputs. +// +// The packet dispatcher expects 2-byte padded ethernet frames. +// The frames will be inspected at ethernet, IPv4, UDP, and VRT layers. +// Packets are dispatched into the following streams: +// * tx dsp stream +// * to cpu stream +// * to external stream +// * to both cpu and external +// +// The following registers are used for dispatcher control: +// * base + 0 = this ipv4 address (32 bits) +// * base + 1 = udp dst port (lower 16 bits) +// + +module packet_dispatcher36_x3 + #( + parameter BASE = 0 + ) + ( + //clocking and reset interface: + input clk, input rst, input clr, + + //setting register interface: + input set_stb, input [7:0] set_addr, input [31:0] set_data, + + //input stream interfaces: + input [35:0] com_inp_data, input com_inp_valid, output com_inp_ready, + + //output stream interfaces: + output [35:0] ext_out_data, output ext_out_valid, input ext_out_ready, + output [35:0] dsp_out_data, output dsp_out_valid, input dsp_out_ready, + output [35:0] cpu_out_data, output cpu_out_valid, input cpu_out_ready + ); + + //setting register to program the IP address + wire [31:0] my_ip_addr; + setting_reg #(.my_addr(BASE+0)) sreg_ip_addr( + .clk(clk),.rst(rst), + .strobe(set_stb),.addr(set_addr),.in(set_data), + .out(my_ip_addr),.changed() + ); + + //setting register to program the UDP DSP port + wire [15:0] dsp_udp_port; + setting_reg #(.my_addr(BASE+1), .width(16)) sreg_data_port( + .clk(clk),.rst(rst), + .strobe(set_stb),.addr(set_addr),.in(set_data), + .out(dsp_udp_port),.changed() + ); + + //////////////////////////////////////////////////////////////////// + // Communication input inspector + // - inspect com input and send it to DSP, EXT, CPU, or BOTH + //////////////////////////////////////////////////////////////////// + localparam PD_STATE_READ_COM_PRE = 0; + localparam PD_STATE_READ_COM = 1; + localparam PD_STATE_WRITE_REGS = 2; + localparam PD_STATE_WRITE_LIVE = 3; + + localparam PD_DEST_DSP = 0; + localparam PD_DEST_EXT = 1; + localparam PD_DEST_CPU = 2; + localparam PD_DEST_BOF = 3; + + localparam PD_MAX_NUM_DREGS = 13; //padded_eth + ip + udp + seq + vrt_hdr + localparam PD_DREGS_DSP_OFFSET = 11; //offset to start dsp at + + //output inspector interfaces + wire [35:0] pd_out_dsp_data; + wire pd_out_dsp_valid; + wire pd_out_dsp_ready; + + wire [35:0] pd_out_ext_data; + wire pd_out_ext_valid; + wire pd_out_ext_ready; + + wire [35:0] pd_out_cpu_data; + wire pd_out_cpu_valid; + wire pd_out_cpu_ready; + + wire [35:0] pd_out_bof_data; + wire pd_out_bof_valid; + wire pd_out_bof_ready; + + reg [1:0] pd_state; + reg [1:0] pd_dest; + reg [3:0] pd_dreg_count; //data registers to buffer headers + wire [3:0] pd_dreg_count_next = pd_dreg_count + 1'b1; + wire pd_dreg_counter_done = (pd_dreg_count_next == PD_MAX_NUM_DREGS)? 1'b1 : 1'b0; + reg [35:0] pd_dregs [PD_MAX_NUM_DREGS-1:0]; + + //extract various packet components: + wire [47:0] pd_dregs_eth_dst_mac = {pd_dregs[0][15:0], pd_dregs[1][31:0]}; + wire [15:0] pd_dregs_eth_type = pd_dregs[3][15:0]; + wire [7:0] pd_dregs_ipv4_proto = pd_dregs[6][23:16]; + wire [31:0] pd_dregs_ipv4_dst_addr = pd_dregs[8][31:0]; + wire [15:0] pd_dregs_udp_dst_port = pd_dregs[9][15:0]; + wire [15:0] pd_dregs_vrt_size = com_inp_data[15:0]; + + //Inspector output flags special case: + //Inject SOF into flags at first DSP line. + wire [3:0] pd_out_flags = ( + (pd_dreg_count == PD_DREGS_DSP_OFFSET) && + (pd_dest == PD_DEST_DSP) + )? 4'b0001 : pd_dregs[pd_dreg_count][35:32]; + + //The communication inspector ouput data and valid signals: + //Mux between com input and data registers based on the state. + wire [35:0] pd_out_data = (pd_state == PD_STATE_WRITE_REGS)? + {pd_out_flags, pd_dregs[pd_dreg_count][31:0]} : com_inp_data + ; + wire pd_out_valid = + (pd_state == PD_STATE_WRITE_REGS)? 1'b1 : ( + (pd_state == PD_STATE_WRITE_LIVE)? com_inp_valid : ( + 1'b0)); + + //The communication inspector ouput ready signal: + //Mux between the various destination ready signals. + wire pd_out_ready = + (pd_dest == PD_DEST_DSP)? pd_out_dsp_ready : ( + (pd_dest == PD_DEST_EXT)? pd_out_ext_ready : ( + (pd_dest == PD_DEST_CPU)? pd_out_cpu_ready : ( + (pd_dest == PD_DEST_BOF)? pd_out_bof_ready : ( + 1'b0)))); + + //Always connected output data lines. + assign pd_out_dsp_data = pd_out_data; + assign pd_out_ext_data = pd_out_data; + assign pd_out_cpu_data = pd_out_data; + assign pd_out_bof_data = pd_out_data; + + //Destination output valid signals: + //Comes from inspector valid when destination is selected, and otherwise low. + assign pd_out_dsp_valid = (pd_dest == PD_DEST_DSP)? pd_out_valid : 1'b0; + assign pd_out_ext_valid = (pd_dest == PD_DEST_EXT)? pd_out_valid : 1'b0; + assign pd_out_cpu_valid = (pd_dest == PD_DEST_CPU)? pd_out_valid : 1'b0; + assign pd_out_bof_valid = (pd_dest == PD_DEST_BOF)? pd_out_valid : 1'b0; + + //The communication inspector ouput ready signal: + //Always ready when storing to data registers, + //comes from inspector ready output when live, + //and otherwise low. + assign com_inp_ready = + (pd_state == PD_STATE_READ_COM_PRE) ? 1'b1 : ( + (pd_state == PD_STATE_READ_COM) ? 1'b1 : ( + (pd_state == PD_STATE_WRITE_LIVE) ? pd_out_ready : ( + 1'b0))); + + always @(posedge clk) + if(rst | clr) begin + pd_state <= PD_STATE_READ_COM_PRE; + pd_dreg_count <= 0; + end + else begin + case(pd_state) + PD_STATE_READ_COM_PRE: begin + if (com_inp_ready & com_inp_valid & com_inp_data[32]) begin + pd_state <= PD_STATE_READ_COM; + pd_dreg_count <= pd_dreg_count_next; + pd_dregs[pd_dreg_count] <= com_inp_data; + end + end + + PD_STATE_READ_COM: begin + if (com_inp_ready & com_inp_valid) begin + pd_dregs[pd_dreg_count] <= com_inp_data; + if (pd_dreg_counter_done | com_inp_data[33]) begin + pd_state <= PD_STATE_WRITE_REGS; + pd_dreg_count <= 0; + + //---------- begin inspection decision -----------// + //EOF or bcast or not IPv4 or not UDP: + if ( + com_inp_data[33] || (pd_dregs_eth_dst_mac == 48'hffffffffffff) || + (pd_dregs_eth_type != 16'h800) || (pd_dregs_ipv4_proto != 8'h11) + ) begin + pd_dest <= PD_DEST_BOF; + end + + //not my IP address: + else if (pd_dregs_ipv4_dst_addr != my_ip_addr) begin + pd_dest <= PD_DEST_EXT; + end + + //UDP data port and VRT: + else if ((pd_dregs_udp_dst_port == dsp_udp_port) && (pd_dregs_vrt_size != 16'h0)) begin + pd_dest <= PD_DEST_DSP; + pd_dreg_count <= PD_DREGS_DSP_OFFSET; + end + + //other: + else begin + pd_dest <= PD_DEST_CPU; + end + //---------- end inspection decision -------------// + + end + else begin + pd_dreg_count <= pd_dreg_count_next; + end + end + end + + PD_STATE_WRITE_REGS: begin + if (pd_out_ready & pd_out_valid) begin + if (pd_out_data[33]) begin + pd_state <= PD_STATE_READ_COM_PRE; + pd_dreg_count <= 0; + end + else if (pd_dreg_counter_done) begin + pd_state <= PD_STATE_WRITE_LIVE; + pd_dreg_count <= 0; + end + else begin + pd_dreg_count <= pd_dreg_count_next; + end + end + end + + PD_STATE_WRITE_LIVE: begin + if (pd_out_ready & pd_out_valid & pd_out_data[33]) begin + pd_state <= PD_STATE_READ_COM_PRE; + end + end + + endcase //pd_state + end + + //connect this fast-path signals directly to the DSP out + assign dsp_out_data = pd_out_dsp_data; + assign dsp_out_valid = pd_out_dsp_valid; + assign pd_out_dsp_ready = dsp_out_ready; + + //////////////////////////////////////////////////////////////////// + // Splitter and output muxes for the bof packets + // - split the bof packets into two streams + // - mux split packets into cpu out and ext out + //////////////////////////////////////////////////////////////////// + + //dummy signals to join the the splitter and muxes below + wire [35:0] _split_to_ext_data, _split_to_cpu_data; + wire _split_to_ext_valid, _split_to_cpu_valid; + wire _split_to_ext_ready, _split_to_cpu_ready; + + splitter36 bof_out_splitter( + .clk(clk), .rst(rst), .clr(clr), + .inp_data(pd_out_bof_data), .inp_valid(pd_out_bof_valid), .inp_ready(pd_out_bof_ready), + .out0_data(_split_to_ext_data), .out0_valid(_split_to_ext_valid), .out0_ready(_split_to_ext_ready), + .out1_data(_split_to_cpu_data), .out1_valid(_split_to_cpu_valid), .out1_ready(_split_to_cpu_ready) + ); + + fifo36_mux ext_out_mux( + .clk(clk), .reset(rst), .clear(clr), + .data0_i(pd_out_ext_data), .src0_rdy_i(pd_out_ext_valid), .dst0_rdy_o(pd_out_ext_ready), + .data1_i(_split_to_ext_data), .src1_rdy_i(_split_to_ext_valid), .dst1_rdy_o(_split_to_ext_ready), + .data_o(ext_out_data), .src_rdy_o(ext_out_valid), .dst_rdy_i(ext_out_ready) + ); + + fifo36_mux cpu_out_mux( + .clk(clk), .reset(rst), .clear(clr), + .data0_i(pd_out_cpu_data), .src0_rdy_i(pd_out_cpu_valid), .dst0_rdy_o(pd_out_cpu_ready), + .data1_i(_split_to_cpu_data), .src1_rdy_i(_split_to_cpu_valid), .dst1_rdy_o(_split_to_cpu_ready), + .data_o(cpu_out_data), .src_rdy_o(cpu_out_valid), .dst_rdy_i(cpu_out_ready) + ); + +endmodule // packet_dispatcher36_x3 diff --git a/fpga/usrp2/fifo/packet_generator.v b/fpga/usrp2/fifo/packet_generator.v new file mode 100644 index 000000000..2ae911e24 --- /dev/null +++ b/fpga/usrp2/fifo/packet_generator.v @@ -0,0 +1,83 @@ + + +module packet_generator + (input clk, input reset, input clear, + output reg [7:0] data_o, output sof_o, output eof_o, + input [127:0] header, + output src_rdy_o, input dst_rdy_i); + + localparam len = 32'd2000; + + reg [31:0] state; + reg [31:0] seq; + reg [31:0] crc_out; + wire calc_crc = src_rdy_o & dst_rdy_i & ~(state[31:2] == 30'h3FFF_FFFF); + + + always @(posedge clk) + if(reset | clear) + seq <= 0; + else + if(eof_o & src_rdy_o & dst_rdy_i) + seq <= seq + 1; + + always @(posedge clk) + if(reset | clear) + state <= 0; + else + if(src_rdy_o & dst_rdy_i) + if(state == (len - 1)) + state <= 32'hFFFF_FFFC; + else + state <= state + 1; + + always @* + case(state) + 0 : data_o <= len[31:24]; + 1 : data_o <= len[23:16]; + 2 : data_o <= len[15:8]; + 3 : data_o <= len[7:0]; + 4 : data_o <= seq[31:24]; + 5 : data_o <= seq[23:16]; + 6 : data_o <= seq[15:8]; + 7 : data_o <= seq[7:0]; + 8 : data_o <= header[7:0]; + 9 : data_o <= header[15:8]; + 10 : data_o <= header[23:16]; + 11 : data_o <= header[31:24]; + 12 : data_o <= header[39:32]; + 13 : data_o <= header[47:40]; + 14 : data_o <= header[55:48]; + 15 : data_o <= header[63:56]; + 16 : data_o <= header[71:64]; + 17 : data_o <= header[79:72]; + 18 : data_o <= header[87:80]; + 19 : data_o <= header[95:88]; + 20 : data_o <= header[103:96]; + 21 : data_o <= header[111:104]; + 22 : data_o <= header[119:112]; + 23 : data_o <= header[127:120]; + + 32'hFFFF_FFFC : data_o <= crc_out[31:24]; + 32'hFFFF_FFFD : data_o <= crc_out[23:16]; + 32'hFFFF_FFFE : data_o <= crc_out[15:8]; + 32'hFFFF_FFFF : data_o <= crc_out[7:0]; + default : data_o <= state[7:0]; + endcase // case (state) + + assign src_rdy_o = 1; + assign sof_o = (state == 0); + assign eof_o = (state == 32'hFFFF_FFFF); + + wire clear_crc = eof_o & src_rdy_o & dst_rdy_i; + +// crc crc(.clk(clk), .reset(reset), .clear(clear_crc), .data(data_o), +// .calc(calc_crc), .crc_out(crc_out), .match()); + always @(posedge clk) + if(reset | clear | clear_crc) + crc_out <= 0; + else + if(calc_crc) + crc_out <= crc_out + data_o; + +endmodule // packet_generator diff --git a/fpga/usrp2/fifo/packet_generator32.v b/fpga/usrp2/fifo/packet_generator32.v new file mode 100644 index 000000000..1dc57191d --- /dev/null +++ b/fpga/usrp2/fifo/packet_generator32.v @@ -0,0 +1,23 @@ + + +module packet_generator32 + (input clk, input reset, input clear, + input [127:0] header, + output [35:0] data_o, output src_rdy_o, input dst_rdy_i); + + wire [7:0] ll_data; + wire ll_sof, ll_eof, ll_src_rdy, ll_dst_rdy_n; + + packet_generator pkt_gen + (.clk(clk), .reset(reset), .clear(clear), + .data_o(ll_data), .sof_o(ll_sof), .eof_o(ll_eof), + .header(header), + .src_rdy_o(ll_src_rdy), .dst_rdy_i(~ll_dst_rdy_n)); + + ll8_to_fifo36 ll8_to_f36 + (.clk(clk), .reset(reset), .clear(clear), + .ll_data(ll_data), .ll_sof_n(~ll_sof), .ll_eof_n(~ll_eof), + .ll_src_rdy_n(~ll_src_rdy), .ll_dst_rdy_n(ll_dst_rdy_n), + .f36_data(data_o), .f36_src_rdy_o(src_rdy_o), .f36_dst_rdy_i(dst_rdy_i)); + +endmodule // packet_generator32 diff --git a/fpga/usrp2/fifo/packet_router.v b/fpga/usrp2/fifo/packet_router.v index bad8fb7fc..7774ff076 100644 --- a/fpga/usrp2/fifo/packet_router.v +++ b/fpga/usrp2/fifo/packet_router.v @@ -69,28 +69,14 @@ module packet_router //setting register for mode control wire [31:0] _sreg_mode_ctrl; + wire master_mode_flag; + setting_reg #(.my_addr(CTRL_BASE+0), .width(1)) sreg_mode_ctrl( .clk(stream_clk),.rst(stream_rst), .strobe(set_stb),.addr(set_addr),.in(set_data), .out(master_mode_flag),.changed() ); - //setting register to program the IP address - wire [31:0] my_ip_addr; - setting_reg #(.my_addr(CTRL_BASE+1)) sreg_ip_addr( - .clk(stream_clk),.rst(stream_rst), - .strobe(set_stb),.addr(set_addr),.in(set_data), - .out(my_ip_addr),.changed() - ); - - //setting register to program the UDP data ports - wire [15:0] dsp_udp_port; - setting_reg #(.my_addr(CTRL_BASE+2), .width(16)) sreg_data_ports( - .clk(stream_clk),.rst(stream_rst), - .strobe(set_stb),.addr(set_addr),.in(set_data), - .out(dsp_udp_port),.changed() - ); - //assign status output signals wire [31:0] cpu_iface_status; assign status = { @@ -118,8 +104,8 @@ module packet_router wire _eth_inp_ready; // dummy signals to connect fifo_short - wire [35:0] _com_inp_data; - wire _com_inp_valid; + wire [35:0] _com_inp_data; + wire _com_inp_valid; wire _com_inp_ready; valve36 eth_inp_valve ( @@ -179,36 +165,34 @@ module packet_router //////////////////////////////////////////////////////////////////// // Communication output source combiner (feeds UDP proto machine) - // - DSP framer + // - DSP input // - CPU input // - ERR input //////////////////////////////////////////////////////////////////// - //streaming signals from the dsp framer to the combiner - wire [35:0] dsp0_frm_data, dsp1_frm_data; - wire dsp0_frm_valid, dsp1_frm_valid; - wire dsp0_frm_ready, dsp1_frm_ready; - //dummy signals to join the the muxes below wire [35:0] _combiner0_data, _combiner1_data; wire _combiner0_valid, _combiner1_valid; wire _combiner0_ready, _combiner1_ready; - fifo36_mux _com_output_combiner0( + fifo36_mux #(.prio(0)) // No priority, fair sharing + _com_output_combiner0( .clk(stream_clk), .reset(stream_rst), .clear(stream_clr), - .data0_i(dsp0_frm_data), .src0_rdy_i(dsp0_frm_valid), .dst0_rdy_o(dsp0_frm_ready), - .data1_i(err_inp_data), .src1_rdy_i(err_inp_valid), .dst1_rdy_o(err_inp_ready), + .data0_i(err_inp_data), .src0_rdy_i(err_inp_valid), .dst0_rdy_o(err_inp_ready), + .data1_i(cpu_inp_data), .src1_rdy_i(cpu_inp_valid), .dst1_rdy_o(cpu_inp_ready), .data_o(_combiner0_data), .src_rdy_o(_combiner0_valid), .dst_rdy_i(_combiner0_ready) ); - fifo36_mux _com_output_combiner1( + fifo36_mux #(.prio(0)) // No priority, fair sharing + _com_output_combiner1( .clk(stream_clk), .reset(stream_rst), .clear(stream_clr), - .data0_i(dsp1_frm_data), .src0_rdy_i(dsp1_frm_valid), .dst0_rdy_o(dsp1_frm_ready), - .data1_i(cpu_inp_data), .src1_rdy_i(cpu_inp_valid), .dst1_rdy_o(cpu_inp_ready), + .data0_i(dsp0_inp_data), .src0_rdy_i(dsp0_inp_valid), .dst0_rdy_o(dsp0_inp_ready), + .data1_i(dsp1_inp_data), .src1_rdy_i(dsp1_inp_valid), .dst1_rdy_o(dsp1_inp_ready), .data_o(_combiner1_data), .src_rdy_o(_combiner1_valid), .dst_rdy_i(_combiner1_ready) ); - fifo36_mux com_output_source( + fifo36_mux #(.prio(1)) // Give priority to err/cpu over dsp + com_output_source( .clk(stream_clk), .reset(stream_rst), .clear(stream_clr), .data0_i(_combiner0_data), .src0_rdy_i(_combiner0_valid), .dst0_rdy_o(_combiner0_ready), .data1_i(_combiner1_data), .src1_rdy_i(_combiner1_valid), .dst1_rdy_o(_combiner1_ready), @@ -217,6 +201,7 @@ module packet_router //////////////////////////////////////////////////////////////////// // Interface CPU to memory mapped wishbone + // - Uses 1 setting register //////////////////////////////////////////////////////////////////// buffer_int2 #(.BASE(CTRL_BASE+3), .BUF_SIZE(BUF_SIZE)) cpu_to_wb( .clk(stream_clk), .rst(stream_rst | stream_clr), @@ -238,218 +223,21 @@ module packet_router ); //////////////////////////////////////////////////////////////////// - // Communication input inspector - // - inspect com input and send it to DSP, EXT, CPU, or BOTH - //////////////////////////////////////////////////////////////////// - localparam COM_INSP_STATE_READ_COM_PRE = 0; - localparam COM_INSP_STATE_READ_COM = 1; - localparam COM_INSP_STATE_WRITE_REGS = 2; - localparam COM_INSP_STATE_WRITE_LIVE = 3; - - localparam COM_INSP_DEST_DSP = 0; - localparam COM_INSP_DEST_EXT = 1; - localparam COM_INSP_DEST_CPU = 2; - localparam COM_INSP_DEST_BOF = 3; - - localparam COM_INSP_MAX_NUM_DREGS = 13; //padded_eth + ip + udp + seq + vrt_hdr - localparam COM_INSP_DREGS_DSP_OFFSET = 11; //offset to start dsp at - - //output inspector interfaces - wire [35:0] com_insp_out_dsp_data; - wire com_insp_out_dsp_valid; - wire com_insp_out_dsp_ready; - - wire [35:0] com_insp_out_ext_data; - wire com_insp_out_ext_valid; - wire com_insp_out_ext_ready; - - wire [35:0] com_insp_out_cpu_data; - wire com_insp_out_cpu_valid; - wire com_insp_out_cpu_ready; - - wire [35:0] com_insp_out_bof_data; - wire com_insp_out_bof_valid; - wire com_insp_out_bof_ready; - - //connect this fast-path signals directly to the DSP out - assign dsp_out_data = com_insp_out_dsp_data; - assign dsp_out_valid = com_insp_out_dsp_valid; - assign com_insp_out_dsp_ready = dsp_out_ready; - - reg [1:0] com_insp_state; - reg [1:0] com_insp_dest; - reg [3:0] com_insp_dreg_count; //data registers to buffer headers - wire [3:0] com_insp_dreg_count_next = com_insp_dreg_count + 1'b1; - wire com_insp_dreg_counter_done = (com_insp_dreg_count_next == COM_INSP_MAX_NUM_DREGS)? 1'b1 : 1'b0; - reg [35:0] com_insp_dregs [COM_INSP_MAX_NUM_DREGS-1:0]; - - //extract various packet components: - wire [47:0] com_insp_dregs_eth_dst_mac = {com_insp_dregs[0][15:0], com_insp_dregs[1][31:0]}; - wire [15:0] com_insp_dregs_eth_type = com_insp_dregs[3][15:0]; - wire [7:0] com_insp_dregs_ipv4_proto = com_insp_dregs[6][23:16]; - wire [31:0] com_insp_dregs_ipv4_dst_addr = com_insp_dregs[8][31:0]; - wire [15:0] com_insp_dregs_udp_dst_port = com_insp_dregs[9][15:0]; - wire [15:0] com_insp_dregs_vrt_size = com_inp_data[15:0]; - - //Inspector output flags special case: - //Inject SOF into flags at first DSP line. - wire [3:0] com_insp_out_flags = ( - (com_insp_dreg_count == COM_INSP_DREGS_DSP_OFFSET) && - (com_insp_dest == COM_INSP_DEST_DSP) - )? 4'b0001 : com_insp_dregs[com_insp_dreg_count][35:32]; - - //The communication inspector ouput data and valid signals: - //Mux between com input and data registers based on the state. - wire [35:0] com_insp_out_data = (com_insp_state == COM_INSP_STATE_WRITE_REGS)? - {com_insp_out_flags, com_insp_dregs[com_insp_dreg_count][31:0]} : com_inp_data - ; - wire com_insp_out_valid = - (com_insp_state == COM_INSP_STATE_WRITE_REGS)? 1'b1 : ( - (com_insp_state == COM_INSP_STATE_WRITE_LIVE)? com_inp_valid : ( - 1'b0)); - - //The communication inspector ouput ready signal: - //Mux between the various destination ready signals. - wire com_insp_out_ready = - (com_insp_dest == COM_INSP_DEST_DSP)? com_insp_out_dsp_ready : ( - (com_insp_dest == COM_INSP_DEST_EXT)? com_insp_out_ext_ready : ( - (com_insp_dest == COM_INSP_DEST_CPU)? com_insp_out_cpu_ready : ( - (com_insp_dest == COM_INSP_DEST_BOF)? com_insp_out_bof_ready : ( - 1'b0)))); - - //Always connected output data lines. - assign com_insp_out_dsp_data = com_insp_out_data; - assign com_insp_out_ext_data = com_insp_out_data; - assign com_insp_out_cpu_data = com_insp_out_data; - assign com_insp_out_bof_data = com_insp_out_data; - - //Destination output valid signals: - //Comes from inspector valid when destination is selected, and otherwise low. - assign com_insp_out_dsp_valid = (com_insp_dest == COM_INSP_DEST_DSP)? com_insp_out_valid : 1'b0; - assign com_insp_out_ext_valid = (com_insp_dest == COM_INSP_DEST_EXT)? com_insp_out_valid : 1'b0; - assign com_insp_out_cpu_valid = (com_insp_dest == COM_INSP_DEST_CPU)? com_insp_out_valid : 1'b0; - assign com_insp_out_bof_valid = (com_insp_dest == COM_INSP_DEST_BOF)? com_insp_out_valid : 1'b0; - - //The communication inspector ouput ready signal: - //Always ready when storing to data registers, - //comes from inspector ready output when live, - //and otherwise low. - assign com_inp_ready = - (com_insp_state == COM_INSP_STATE_READ_COM_PRE) ? 1'b1 : ( - (com_insp_state == COM_INSP_STATE_READ_COM) ? 1'b1 : ( - (com_insp_state == COM_INSP_STATE_WRITE_LIVE) ? com_insp_out_ready : ( - 1'b0))); - - always @(posedge stream_clk) - if(stream_rst | stream_clr) begin - com_insp_state <= COM_INSP_STATE_READ_COM_PRE; - com_insp_dreg_count <= 0; - end - else begin - case(com_insp_state) - COM_INSP_STATE_READ_COM_PRE: begin - if (com_inp_ready & com_inp_valid & com_inp_data[32]) begin - com_insp_state <= COM_INSP_STATE_READ_COM; - com_insp_dreg_count <= com_insp_dreg_count_next; - com_insp_dregs[com_insp_dreg_count] <= com_inp_data; - end - end - - COM_INSP_STATE_READ_COM: begin - if (com_inp_ready & com_inp_valid) begin - com_insp_dregs[com_insp_dreg_count] <= com_inp_data; - if (com_insp_dreg_counter_done | com_inp_data[33]) begin - com_insp_state <= COM_INSP_STATE_WRITE_REGS; - com_insp_dreg_count <= 0; - - //---------- begin inspection decision -----------// - //EOF or bcast or not IPv4 or not UDP: - if ( - com_inp_data[33] || (com_insp_dregs_eth_dst_mac == 48'hffffffffffff) || - (com_insp_dregs_eth_type != 16'h800) || (com_insp_dregs_ipv4_proto != 8'h11) - ) begin - com_insp_dest <= COM_INSP_DEST_BOF; - end - - //not my IP address: - else if (com_insp_dregs_ipv4_dst_addr != my_ip_addr) begin - com_insp_dest <= COM_INSP_DEST_EXT; - end - - //UDP data port and VRT: - else if ((com_insp_dregs_udp_dst_port == dsp_udp_port) && (com_insp_dregs_vrt_size != 16'h0)) begin - com_insp_dest <= COM_INSP_DEST_DSP; - com_insp_dreg_count <= COM_INSP_DREGS_DSP_OFFSET; - end - - //other: - else begin - com_insp_dest <= COM_INSP_DEST_CPU; - end - //---------- end inspection decision -------------// - - end - else begin - com_insp_dreg_count <= com_insp_dreg_count_next; - end - end - end - - COM_INSP_STATE_WRITE_REGS: begin - if (com_insp_out_ready & com_insp_out_valid) begin - if (com_insp_out_data[33]) begin - com_insp_state <= COM_INSP_STATE_READ_COM_PRE; - com_insp_dreg_count <= 0; - end - else if (com_insp_dreg_counter_done) begin - com_insp_state <= COM_INSP_STATE_WRITE_LIVE; - com_insp_dreg_count <= 0; - end - else begin - com_insp_dreg_count <= com_insp_dreg_count_next; - end - end - end - - COM_INSP_STATE_WRITE_LIVE: begin - if (com_insp_out_ready & com_insp_out_valid & com_insp_out_data[33]) begin - com_insp_state <= COM_INSP_STATE_READ_COM_PRE; - end - end - - endcase //com_insp_state - end - + // Packet Dispatcher + // - Uses 2 setting registers + // - provide buffering before cpu for random + small packet bursts //////////////////////////////////////////////////////////////////// - // Splitter and output muxes for the bof packets - // - split the bof packets into two streams - // - mux split packets into cpu out and ext out - //////////////////////////////////////////////////////////////////// - - //dummy signals to join the the splitter and muxes below - wire [35:0] _split_to_ext_data, _split_to_cpu_data, _cpu_out_data; - wire _split_to_ext_valid, _split_to_cpu_valid, _cpu_out_valid; - wire _split_to_ext_ready, _split_to_cpu_ready, _cpu_out_ready; + wire [35:0] _cpu_out_data; + wire _cpu_out_valid; + wire _cpu_out_ready; - splitter36 bof_out_splitter( + packet_dispatcher36_x3 #(.BASE(CTRL_BASE+1)) packet_dispatcher( .clk(stream_clk), .rst(stream_rst), .clr(stream_clr), - .inp_data(com_insp_out_bof_data), .inp_valid(com_insp_out_bof_valid), .inp_ready(com_insp_out_bof_ready), - .out0_data(_split_to_ext_data), .out0_valid(_split_to_ext_valid), .out0_ready(_split_to_ext_ready), - .out1_data(_split_to_cpu_data), .out1_valid(_split_to_cpu_valid), .out1_ready(_split_to_cpu_ready) - ); - - fifo36_mux ext_out_mux( - .clk(stream_clk), .reset(stream_rst), .clear(stream_clr), - .data0_i(com_insp_out_ext_data), .src0_rdy_i(com_insp_out_ext_valid), .dst0_rdy_o(com_insp_out_ext_ready), - .data1_i(_split_to_ext_data), .src1_rdy_i(_split_to_ext_valid), .dst1_rdy_o(_split_to_ext_ready), - .data_o(ext_out_data), .src_rdy_o(ext_out_valid), .dst_rdy_i(ext_out_ready) - ); - - fifo36_mux cpu_out_mux( - .clk(stream_clk), .reset(stream_rst), .clear(stream_clr), - .data0_i(com_insp_out_cpu_data), .src0_rdy_i(com_insp_out_cpu_valid), .dst0_rdy_o(com_insp_out_cpu_ready), - .data1_i(_split_to_cpu_data), .src1_rdy_i(_split_to_cpu_valid), .dst1_rdy_o(_split_to_cpu_ready), - .data_o(_cpu_out_data), .src_rdy_o(_cpu_out_valid), .dst_rdy_i(_cpu_out_ready) + .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), + .com_inp_data(com_inp_data), .com_inp_valid(com_inp_valid), .com_inp_ready(com_inp_ready), + .ext_out_data(ext_out_data), .ext_out_valid(ext_out_valid), .ext_out_ready(ext_out_ready), + .dsp_out_data(dsp_out_data), .dsp_out_valid(dsp_out_valid), .dsp_out_ready(dsp_out_ready), + .cpu_out_data(_cpu_out_data), .cpu_out_valid(_cpu_out_valid), .cpu_out_ready(_cpu_out_ready) ); fifo_cascade #(.WIDTH(36), .SIZE(9/*512 lines plenty for short pkts*/)) cpu_out_fifo ( @@ -459,28 +247,13 @@ module packet_router ); //////////////////////////////////////////////////////////////////// - // DSP input framer - //////////////////////////////////////////////////////////////////// - dsp_framer36 #(.BUF_SIZE(BUF_SIZE), .PORT_SEL(0)) dsp0_framer36( - .clk(stream_clk), .rst(stream_rst), .clr(stream_clr), - .inp_data(dsp0_inp_data), .inp_valid(dsp0_inp_valid), .inp_ready(dsp0_inp_ready), - .out_data(dsp0_frm_data), .out_valid(dsp0_frm_valid), .out_ready(dsp0_frm_ready) - ); - - dsp_framer36 #(.BUF_SIZE(BUF_SIZE), .PORT_SEL(2)) dsp1_framer36( - .clk(stream_clk), .rst(stream_rst), .clr(stream_clr), - .inp_data(dsp1_inp_data), .inp_valid(dsp1_inp_valid), .inp_ready(dsp1_inp_ready), - .out_data(dsp1_frm_data), .out_valid(dsp1_frm_valid), .out_ready(dsp1_frm_ready) - ); - - //////////////////////////////////////////////////////////////////// // UDP TX Protocol machine //////////////////////////////////////////////////////////////////// //dummy signals to connect the components below - wire [18:0] _udp_r2s_data, _udp_s2p_data, _udp_p2s_data, _udp_s2r_data; - wire _udp_r2s_valid, _udp_s2p_valid, _udp_p2s_valid, _udp_s2r_valid; - wire _udp_r2s_ready, _udp_s2p_ready, _udp_p2s_ready, _udp_s2r_ready; + wire [18:0] _udp_r2s_data, _udp_s2r_data; + wire _udp_r2s_valid, _udp_s2r_valid; + wire _udp_r2s_ready, _udp_s2r_ready; wire [35:0] _com_out_data; wire _com_out_valid, _com_out_ready; @@ -490,23 +263,11 @@ module packet_router .f36_datain(udp_out_data), .f36_src_rdy_i(udp_out_valid), .f36_dst_rdy_o(udp_out_ready), .f19_dataout(_udp_r2s_data), .f19_src_rdy_o(_udp_r2s_valid), .f19_dst_rdy_i(_udp_r2s_ready) ); - fifo_short #(.WIDTH(19)) udp_shortfifo19_inp - (.clk(stream_clk), .reset(stream_rst), .clear(stream_clr), - .datain(_udp_r2s_data), .src_rdy_i(_udp_r2s_valid), .dst_rdy_o(_udp_r2s_ready), - .dataout(_udp_s2p_data), .src_rdy_o(_udp_s2p_valid), .dst_rdy_i(_udp_s2p_ready), - .space(), .occupied() ); - prot_eng_tx #(.BASE(UDP_BASE)) udp_prot_eng_tx (.clk(stream_clk), .reset(stream_rst), .clear(stream_clr), .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), - .datain(_udp_s2p_data), .src_rdy_i(_udp_s2p_valid), .dst_rdy_o(_udp_s2p_ready), - .dataout(_udp_p2s_data), .src_rdy_o(_udp_p2s_valid), .dst_rdy_i(_udp_p2s_ready) ); - - fifo_short #(.WIDTH(19)) udp_shortfifo19_out - (.clk(stream_clk), .reset(stream_rst), .clear(stream_clr), - .datain(_udp_p2s_data), .src_rdy_i(_udp_p2s_valid), .dst_rdy_o(_udp_p2s_ready), - .dataout(_udp_s2r_data), .src_rdy_o(_udp_s2r_valid), .dst_rdy_i(_udp_s2r_ready), - .space(), .occupied() ); + .datain(_udp_r2s_data), .src_rdy_i(_udp_r2s_valid), .dst_rdy_o(_udp_r2s_ready), + .dataout(_udp_s2r_data), .src_rdy_o(_udp_s2r_valid), .dst_rdy_i(_udp_s2r_ready) ); fifo19_to_fifo36 udp_fifo19_to_fifo36 (.clk(stream_clk), .reset(stream_rst), .clear(stream_clr), @@ -525,8 +286,10 @@ module packet_router //////////////////////////////////////////////////////////////////// assign debug = { - //inputs to the router (8) + //inputs to the router (12) dsp0_inp_ready, dsp0_inp_valid, + dsp1_inp_ready, dsp1_inp_valid, + err_inp_ready, err_inp_valid, ser_inp_ready, ser_inp_valid, eth_inp_ready, eth_inp_valid, cpu_inp_ready, cpu_inp_valid, @@ -537,17 +300,13 @@ module packet_router eth_out_ready, eth_out_valid, cpu_out_ready, cpu_out_valid, - //inspector interfaces (8) - com_insp_out_dsp_ready, com_insp_out_dsp_valid, - com_insp_out_ext_ready, com_insp_out_ext_valid, - com_insp_out_cpu_ready, com_insp_out_cpu_valid, - com_insp_out_bof_ready, com_insp_out_bof_valid, - //other interfaces (8) ext_inp_ready, ext_inp_valid, com_out_ready, com_out_valid, ext_out_ready, ext_out_valid, - com_inp_ready, com_inp_valid + com_inp_ready, com_inp_valid, + + 4'b0 }; endmodule // packet_router diff --git a/fpga/usrp2/fifo/packet_tb.v b/fpga/usrp2/fifo/packet_tb.v new file mode 100644 index 000000000..3c423d2ba --- /dev/null +++ b/fpga/usrp2/fifo/packet_tb.v @@ -0,0 +1,29 @@ + + +module packet_tb(); + + wire [7:0] data; + wire sof, eof, src_rdy, dst_rdy; + + wire clear = 0; + reg clk = 0; + reg reset = 1; + + always #10 clk <= ~clk; + initial #1000 reset <= 0; + + initial $dumpfile("packet_tb.vcd"); + initial $dumpvars(0,packet_tb); + + wire [31:0] total, crc_err, seq_err, len_err; + + packet_generator pkt_gen (.clk(clk), .reset(reset), .clear(clear), + .data_o(data), .sof_o(sof), .eof_o(eof), + .src_rdy_o(src_rdy), .dst_rdy_i(dst_rdy)); + + packet_verifier pkt_ver (.clk(clk), .reset(reset), .clear(clear), + .data_i(data), .sof_i(sof), .eof_i(eof), + .src_rdy_i(src_rdy), .dst_rdy_o(dst_rdy), + .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err)); + +endmodule // packet_tb diff --git a/fpga/usrp2/fifo/packet_verifier.v b/fpga/usrp2/fifo/packet_verifier.v new file mode 100644 index 000000000..21a4c136e --- /dev/null +++ b/fpga/usrp2/fifo/packet_verifier.v @@ -0,0 +1,61 @@ + + +// Packet format -- +// Line 1 -- Length, 32 bits +// Line 2 -- Sequence number, 32 bits +// Last line -- CRC, 32 bits + +module packet_verifier + (input clk, input reset, input clear, + input [7:0] data_i, input sof_i, input eof_i, input src_rdy_i, output dst_rdy_o, + + output reg [31:0] total, + output reg [31:0] crc_err, + output reg [31:0] seq_err, + output reg [31:0] len_err); + + reg [31:0] seq_num; + reg [31:0] length; + wire first_byte, last_byte; + reg second_byte, last_byte_d1; + wire match_crc; + wire calc_crc = src_rdy_i & dst_rdy_o; + + crc crc(.clk(clk), .reset(reset), .clear(last_byte_d1), .data(data_i), + .calc(calc_crc), .crc_out(), .match(match_crc)); + + assign first_byte = src_rdy_i & dst_rdy_o & sof_i; + assign last_byte = src_rdy_i & dst_rdy_o & eof_i; + assign dst_rdy_o = ~last_byte_d1; + + // stubs for now + wire match_seq = 1; + wire match_len = 1; + + always @(posedge clk) + if(reset | clear) + last_byte_d1 <= 0; + else + last_byte_d1 <= last_byte; + + always @(posedge clk) + if(reset | clear) + begin + total <= 0; + crc_err <= 0; + seq_err <= 0; + len_err <= 0; + end + else + if(last_byte_d1) + begin + total <= total + 1; + if(~match_crc) + crc_err <= crc_err + 1; + else if(~match_seq) + seq_err <= seq_err + 1; + else if(~match_len) + seq_err <= len_err + 1; + end + +endmodule // packet_verifier diff --git a/fpga/usrp2/fifo/packet_verifier32.v b/fpga/usrp2/fifo/packet_verifier32.v new file mode 100644 index 000000000..06a13d242 --- /dev/null +++ b/fpga/usrp2/fifo/packet_verifier32.v @@ -0,0 +1,30 @@ + + +module packet_verifier32 + (input clk, input reset, input clear, + input [35:0] data_i, input src_rdy_i, output dst_rdy_o, + output [31:0] total, output [31:0] crc_err, output [31:0] seq_err, output [31:0] len_err); + + wire [7:0] ll_data; + wire ll_sof_n, ll_eof_n, ll_src_rdy_n, ll_dst_rdy; + wire [35:0] data_int; + wire src_rdy_int, dst_rdy_int; + + fifo_short #(.WIDTH(36)) fifo_short + (.clk(clk), .reset(reset), .clear(clear), + .datain(data_i), .src_rdy_i(src_rdy_i), .dst_rdy_o(dst_rdy_o), + .dataout(data_int), .src_rdy_o(src_rdy_int), .dst_rdy_i(dst_rdy_int)); + + fifo36_to_ll8 f36_to_ll8 + (.clk(clk), .reset(reset), .clear(clear), + .f36_data(data_int), .f36_src_rdy_i(src_rdy_int), .f36_dst_rdy_o(dst_rdy_int), + .ll_data(ll_data), .ll_sof_n(ll_sof_n), .ll_eof_n(ll_eof_n), + .ll_src_rdy_n(ll_src_rdy_n), .ll_dst_rdy_n(~ll_dst_rdy)); + + packet_verifier pkt_ver + (.clk(clk), .reset(reset), .clear(clear), + .data_i(ll_data), .sof_i(~ll_sof_n), .eof_i(~ll_eof_n), + .src_rdy_i(~ll_src_rdy_n), .dst_rdy_o(ll_dst_rdy), + .total(total), .crc_err(crc_err), .seq_err(seq_err), .len_err(len_err)); + +endmodule // packet_verifier32 |