// // Copyright 2014 Ettus Research LLC // Copyright 2018 Ettus Research, a National Instruments Company // // SPDX-License-Identifier: LGPL-3.0-or-later // module new_rx_framer #( parameter BASE=0, parameter CHIPSCOPE=0, parameter SAMPLE_FIFO_SIZE=10 ) (input clk, input reset, input clear, input set_stb, input [7:0] set_addr, input [31:0] set_data, input [63:0] vita_time, input strobe, input [31:0] sample, input run, input eob, output full, output reg [11:0] seqnum, output [31:0] sid, output [63:0] o_tdata, output o_tlast, output o_tvalid, input o_tready, output [31:0] debug ); reg [15:0] len; reg [63:0] hold_time; wire [63:0] dfifo_tdata; wire dfifo_tlast, dfifo_tvalid, dfifo_tready; wire [80:0] hfifo_tdata; wire hfifo_tvalid, hfifo_tready; wire [63:0] o_tdata_int; wire o_tlast_int, o_tvalid_int, o_tready_int; wire [15:0] sample_space; wire [15:0] maxlen; reg [31:0] holding; // FIXME need to handle case where hdr fifo is full (i.e. too many tiny packets) assign full = (sample_space == 16'd0) | (sample_space == 16'd1) | ~hdr_tready; setting_reg #(.my_addr(BASE), .width(16)) sr_maxlen (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),.out(maxlen),.changed()); wire sid_changed; setting_reg #(.my_addr(BASE+1), .width(32)) sr_sid (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),.out(sid),.changed(sid_changed)); localparam START = 0; localparam SECOND = 1; localparam FIRST = 2; reg [1:0] instate; reg [15:0] numsamps; reg nearly_eop; always @(posedge clk) if(reset | clear) begin instate <= START; numsamps <= 0; nearly_eop <= 0; end else if (run) case(instate) // // Start a new packet in this state // START : if(strobe) if(eop) begin instate <= START; numsamps <= 0; nearly_eop <= 0; end else begin instate <= SECOND; numsamps <= numsamps + 1; nearly_eop <= (numsamps >= (maxlen-2)); end // else: !if(eop) // // Second 32 bit sample in a 64bit word // SECOND : if(strobe) if(eop) begin instate <= START; numsamps <= 0; nearly_eop <= 0; end else begin instate <= FIRST; numsamps <= numsamps + 1; nearly_eop <= (numsamps >= (maxlen-2)); end // else: !if(eop) // // First 32bit sample in a 64bit word. // FIRST : if(strobe) if(eop) begin instate <= START; numsamps <= 0; nearly_eop <= 0; end else begin instate <= SECOND; numsamps <= numsamps + 1; nearly_eop <= (numsamps >= (maxlen-2)); end endcase // case (instate) else begin instate <= START; numsamps <= 0; nearly_eop <= 0; end always @(posedge clk) if(strobe && run) begin holding <= sample; if(instate == START) hold_time <= vita_time; end always @(posedge clk) if(reset | clear) len <= 5; else if(strobe && run) if(sample_tlast) len <= 5; else len <= len + 1; always @(posedge clk) if(reset | clear | sid_changed) seqnum <= 12'd0; else if(o_tlast_int & o_tvalid_int & o_tready_int) seqnum <= seqnum + 12'd1; wire eop = eob | nearly_eop | full; wire [63:0] sample_tdata = (instate == SECOND) ? {holding, sample} : {sample, 32'h0}; wire sample_tlast = eop; wire sample_tvalid = run & strobe & ( (instate == SECOND) | eop ); wire sample_tready; wire [80:0] hdr_tdata = {eob,len[13:0],2'b0,(instate == START) ? vita_time : hold_time}; wire hdr_tvalid = sample_tlast && sample_tvalid && sample_tready; wire hdr_tready; wire [80:0] hfifo_tdata_tmp; wire hfifo_tvalid_tmp, hfifo_tready_tmp; axi_fifo #(.WIDTH(65), .SIZE(SAMPLE_FIFO_SIZE)) datafifo (.clk(clk), .reset(reset), .clear(clear), .i_tdata({sample_tlast,sample_tdata}), .i_tvalid(sample_tvalid), .i_tready(sample_tready), .o_tdata({dfifo_tlast,dfifo_tdata}), .o_tvalid(dfifo_tvalid), .o_tready(dfifo_tready), .space(sample_space), .occupied()); axi_fifo_short #(.WIDTH(81)) hdrfifo (.clk(clk), .reset(reset), .clear(clear), .i_tdata(hdr_tdata), .i_tvalid(hdr_tvalid), .i_tready(hdr_tready), .o_tdata(hfifo_tdata_tmp), .o_tvalid(hfifo_tvalid_tmp), .o_tready(hfifo_tready_tmp), .space(), .occupied()); axi_fifo_short #(.WIDTH(81)) hdrfifo2 (.clk(clk), .reset(reset), .clear(clear), .i_tdata(hfifo_tdata_tmp), .i_tvalid(hfifo_tvalid_tmp), .i_tready(hfifo_tready_tmp), .o_tdata(hfifo_tdata), .o_tvalid(hfifo_tvalid), .o_tready(hfifo_tready), .space(), .occupied()); // The output state machine is responsible for forming output packets. // Output packets are formed by combining the entries in the header fifo, // and the samples in the data fifo. A single entry in the header fifo // contains both the compressed header and the 64 bit time stamp. reg [1:0] outstate; localparam OUT_IDLE = 2'd0; localparam OUT_HEAD = 2'd1; localparam OUT_TIME = 2'd2; localparam OUT_BODY = 2'd3; always @(posedge clk) if(reset | clear) outstate <= OUT_IDLE; else case(outstate) OUT_IDLE : if(hfifo_tvalid) //having a header signals a complete packet outstate <= OUT_HEAD; OUT_HEAD : if(o_tvalid_int && o_tready_int) outstate <= OUT_TIME; OUT_TIME : if(o_tvalid_int && o_tready_int) outstate <= OUT_BODY; OUT_BODY : if(o_tvalid_int && o_tready_int && o_tlast_int) outstate <= OUT_IDLE; endcase // case (outstate) //output data mux feeds from single line of header fifo or the data fifo assign o_tdata_int = (outstate == OUT_HEAD) ? { 3'b001, hfifo_tdata[80], seqnum, hfifo_tdata[79:64], sid} : (outstate == OUT_TIME) ? hfifo_tdata[63:0] : dfifo_tdata; //output the last signal from the data fifo assign o_tlast_int = (outstate == OUT_BODY) ? dfifo_tlast : 1'b0; //output valid connected to data valid in non-IDLE states assign o_tvalid_int = (outstate != OUT_IDLE) & dfifo_tvalid; //only pop from header fifo on the very last transaction assign hfifo_tready = o_tvalid_int && o_tready_int && o_tlast_int; //connect data fifo ready with out ready in the BODY state assign dfifo_tready = (outstate == OUT_BODY) ? o_tready_int : 1'b0; axi_fifo_short #(.WIDTH(65)) output_fifo (.clk(clk), .reset(reset), .clear(clear), .i_tdata({o_tlast_int, o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int), .o_tdata({o_tlast, o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready), .space(), .occupied()); /* -----\/----- EXCLUDED -----\/----- assign debug[3:0] = {instate, outstate}; assign debug[7:4] = {1'b0, sample_tlast, sample_tvalid, sample_tready}; assign debug[11:8] = {1'b0, 1'b0, hfifo_tvalid, hfifo_tready}; assign debug[15:12] = {1'b0, dfifo_tlast, dfifo_tvalid, dfifo_tready}; assign debug[19:16] = {1'b0, o_tlast_int, o_tvalid_int, o_tready_int}; -----/\----- EXCLUDED -----/\----- */ assign debug = { sample_tlast, //15 sample_tvalid,//14 sample_tready,//13 dfifo_tvalid, //12 dfifo_tready, //11 hdr_tvalid, //10 hdr_tready, //9 hfifo_tvalid, //8 hfifo_tready, //7 eob, //6 nearly_eop, //5 full, //4 outstate[1:0], //3:2 instate[1:0] //1:0 }; endmodule // new_rx_framer