// // Copyright 2011 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // module vita_rx_framer #(parameter BASE=0, parameter MAXCHAN=1) (input clk, input reset, input clear, input set_stb, input [7:0] set_addr, input [31:0] set_data, // To FIFO interface of Buffer Pool output [35:0] data_o, input dst_rdy_i, output src_rdy_o, // From vita_rx_control input [5+64+(32*MAXCHAN)-1:0] sample_fifo_i, input sample_fifo_src_rdy_i, output sample_fifo_dst_rdy_o, output [31:0] debug_rx ); localparam SAMP_WIDTH = 5+64+(32*MAXCHAN); reg [3:0] sample_phase; wire [3:0] numchan; wire [4:0] flags_fifo_o = sample_fifo_i[SAMP_WIDTH-1:SAMP_WIDTH-5]; wire [63:0] vita_time_fifo_o = sample_fifo_i[SAMP_WIDTH-6:SAMP_WIDTH-69]; reg [31:0] data_fifo_o; // The tools won't synthesize properly without this kludge because of the variable // parameter length wire [127:0] FIXED_WIDTH_KLUDGE = sample_fifo_i; always @* case(sample_phase) 4'd0 : data_fifo_o = FIXED_WIDTH_KLUDGE[31:0]; 4'd1 : data_fifo_o = FIXED_WIDTH_KLUDGE[63:32]; 4'd2 : data_fifo_o = FIXED_WIDTH_KLUDGE[95:64]; 4'd3 : data_fifo_o = FIXED_WIDTH_KLUDGE[127:96]; default : data_fifo_o = 32'hDEADBEEF; endcase // case (sample_phase) wire clear_pkt_count, pkt_fifo_rdy, sample_fifo_in_rdy; wire [31:0] vita_header, vita_streamid, vita_trailer; wire [15:0] samples_per_packet; reg [33:0] pkt_fifo_line; reg [3:0] vita_state; reg [15:0] sample_ctr; reg [3:0] pkt_count; wire [15:0] vita_pkt_len = samples_per_packet + 6; //wire [4:0] flags = {signal_zerolen,signal_overrun,signal_brokenchain,signal_latecmd,signal_cmd_done}; setting_reg #(.my_addr(BASE+4)) sr_header (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),.out(vita_header),.changed()); setting_reg #(.my_addr(BASE+5)) sr_streamid (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),.out(vita_streamid),.changed(clear_pkt_count)); setting_reg #(.my_addr(BASE+6)) sr_trailer (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),.out(vita_trailer),.changed()); setting_reg #(.my_addr(BASE+7),.width(16)) sr_samples_per_pkt (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),.out(samples_per_packet),.changed()); setting_reg #(.my_addr(BASE+8),.width(4), .at_reset(1)) sr_numchan (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), .in(set_data),.out(numchan),.changed()); // Output FIFO for packetized data localparam VITA_IDLE = 0; localparam VITA_HEADER = 1; localparam VITA_STREAMID = 2; localparam VITA_SECS = 3; localparam VITA_TICS = 4; localparam VITA_TICS2 = 5; localparam VITA_PAYLOAD = 6; localparam VITA_TRAILER = 7; localparam VITA_ERR_HEADER = 9; // All ERR at 4'b1000 or'ed with base localparam VITA_ERR_STREAMID = 10; localparam VITA_ERR_SECS = 11; localparam VITA_ERR_TICS = 12; localparam VITA_ERR_TICS2 = 13; localparam VITA_ERR_PAYLOAD = 14; localparam VITA_ERR_TRAILER = 15; // Extension context packets have no trailer always @(posedge clk) if(reset | clear | clear_pkt_count) pkt_count <= 0; else if((vita_state == VITA_TRAILER) & pkt_fifo_rdy) pkt_count <= pkt_count + 1; wire has_streamid = vita_header[28]; wire has_trailer = vita_header[26]; reg trl_eob; always @* case(vita_state) // Data packets are IF Data packets with or w/o streamid, no classid, with trailer VITA_HEADER : pkt_fifo_line <= {2'b01,3'b000,vita_header[28],2'b01,vita_header[25:24], vita_header[23:20],pkt_count[3:0],vita_pkt_len[15:0]}; VITA_STREAMID : pkt_fifo_line <= {2'b00,vita_streamid}; VITA_SECS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]}; VITA_TICS : pkt_fifo_line <= {2'b00,32'd0}; VITA_TICS2 : pkt_fifo_line <= {2'b00,vita_time_fifo_o[31:0]}; VITA_PAYLOAD : pkt_fifo_line <= {2'b00,data_fifo_o}; VITA_TRAILER : pkt_fifo_line <= {2'b10,vita_trailer[31:21],1'b1,vita_trailer[19:9],trl_eob,8'd0}; // Error packets are Extension Context packets, which have no trailer VITA_ERR_HEADER : pkt_fifo_line <= {2'b01,4'b0101,4'b0000,vita_header[23:20],pkt_count,16'd6}; VITA_ERR_STREAMID : pkt_fifo_line <= {2'b00,vita_streamid}; VITA_ERR_SECS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]}; VITA_ERR_TICS : pkt_fifo_line <= {2'b00,32'd0}; VITA_ERR_TICS2 : pkt_fifo_line <= {2'b00,vita_time_fifo_o[31:0]}; VITA_ERR_PAYLOAD : pkt_fifo_line <= {2'b10,27'd0,flags_fifo_o}; //VITA_ERR_TRAILER : pkt_fifo_line <= {2'b11,vita_trailer}; default : pkt_fifo_line <= 34'h0_FFFF_FFFF; endcase // case (vita_state) always @(posedge clk) if(reset | clear) begin vita_state <= VITA_IDLE; sample_ctr <= 0; sample_phase <= 0; end else if(vita_state==VITA_IDLE) begin sample_ctr <= 1; sample_phase <= 0; if(sample_fifo_src_rdy_i) if(|flags_fifo_o[4:1]) vita_state <= VITA_ERR_HEADER; else vita_state <= VITA_HEADER; end else if(pkt_fifo_rdy) case(vita_state) VITA_HEADER : if(has_streamid) vita_state <= VITA_STREAMID; else vita_state <= VITA_SECS; VITA_PAYLOAD : if(sample_fifo_src_rdy_i) begin if(sample_phase == (numchan-4'd1)) begin sample_phase <= 0; sample_ctr <= sample_ctr + 1; trl_eob <= flags_fifo_o[0]; if(sample_ctr == samples_per_packet) vita_state <= VITA_TRAILER; if(|flags_fifo_o) // end early if any flag is set vita_state <= VITA_TRAILER; end else sample_phase <= sample_phase + 1; end // if (sample_fifo_src_rdy_i) VITA_ERR_PAYLOAD : vita_state <= VITA_IDLE; VITA_TRAILER : vita_state <= VITA_IDLE; default : vita_state <= vita_state + 1; endcase // case (vita_state) reg req_write_pkt_fifo; always @* case(vita_state) VITA_IDLE : req_write_pkt_fifo <= 0; VITA_HEADER, VITA_STREAMID, VITA_SECS, VITA_TICS, VITA_TICS2, VITA_TRAILER : req_write_pkt_fifo <= 1; VITA_PAYLOAD : // Write if sample ready and no error flags req_write_pkt_fifo <= (sample_fifo_src_rdy_i & ~|flags_fifo_o[4:1]); VITA_ERR_HEADER, VITA_ERR_STREAMID, VITA_ERR_SECS, VITA_ERR_TICS, VITA_ERR_TICS2, VITA_ERR_PAYLOAD : req_write_pkt_fifo <= 1; default : req_write_pkt_fifo <= 0; endcase // case (vita_state) //wire req_write_pkt_fifo = (vita_state != VITA_IDLE) & (sample_fifo_src_rdy_i | (vita_state != VITA_PAYLOAD)); // Short FIFO to buffer between us and the FIFOs outside fifo_short #(.WIDTH(34)) rx_pkt_fifo (.clk(clk), .reset(reset), .clear(clear), .datain(pkt_fifo_line), .src_rdy_i(req_write_pkt_fifo), .dst_rdy_o(pkt_fifo_rdy), .dataout(data_o[33:0]), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i), .space(),.occupied() ); assign data_o[35:34] = 2'b00; // Always write full lines assign sample_fifo_dst_rdy_o = pkt_fifo_rdy & ( ((vita_state==VITA_PAYLOAD) & (sample_phase == (numchan-4'd1)) & ~|flags_fifo_o[4:1]) | (vita_state==VITA_ERR_PAYLOAD)); assign debug_rx = vita_state; endmodule // vita_rx_framer