diff options
Diffstat (limited to 'fpga/usrp2/vrt/vita_tx_deframer.v')
-rw-r--r-- | fpga/usrp2/vrt/vita_tx_deframer.v | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/fpga/usrp2/vrt/vita_tx_deframer.v b/fpga/usrp2/vrt/vita_tx_deframer.v new file mode 100644 index 000000000..06ca27767 --- /dev/null +++ b/fpga/usrp2/vrt/vita_tx_deframer.v @@ -0,0 +1,249 @@ +// +// 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 <http://www.gnu.org/licenses/>. +// + + +module vita_tx_deframer + #(parameter BASE=0, + parameter MAXCHAN=1, + parameter USE_TRANS_HEADER=0) + (input clk, input reset, input clear, input clear_seqnum, + input set_stb, input [7:0] set_addr, input [31:0] set_data, + + // To FIFO interface of Buffer Pool + input [35:0] data_i, + input src_rdy_i, + output dst_rdy_o, + + output [5+64+16+(32*MAXCHAN)-1:0] sample_fifo_o, + output sample_fifo_src_rdy_o, + input sample_fifo_dst_rdy_i, + + output [31:0] current_seqnum, + + // FIFO Levels + output [15:0] fifo_occupied, + output fifo_full, + output fifo_empty, + output [31:0] debug + ); + + localparam FIFOWIDTH = 5+64+16+(32*MAXCHAN); + + wire [1:0] numchan; + setting_reg #(.my_addr(BASE), .at_reset(0), .width(2)) sr_numchan + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(numchan),.changed()); + + reg [3:0] vita_state; + wire has_streamid, has_classid, has_secs, has_tics, has_trailer; + assign has_streamid = (data_i[31:28]==4'b0001); + assign has_classid = data_i[27]; + assign has_secs = ~(data_i[23:22]==2'b00); + assign has_tics = ~(data_i[21:20]==2'b00); + assign has_trailer = data_i[26]; + wire is_sob = data_i[25]; + wire is_eob = data_i[24]; + wire eof = data_i[33]; + reg has_streamid_reg, has_classid_reg, has_secs_reg, has_tics_reg; + reg has_trailer_reg, is_sob_reg, is_eob_reg; + + reg [15:0] pkt_len; + reg [1:0] vector_phase; + wire line_done; + + wire [31:0] seqnum = data_i; + reg [31:0] seqnum_reg; + wire [31:0] next_seqnum = seqnum_reg + 32'd1; + wire [3:0] vita_seqnum = data_i[19:16]; + reg [3:0] vita_seqnum_reg; + wire [3:0] next_vita_seqnum = vita_seqnum_reg[3:0] + 4'd1; + reg seqnum_err; + + assign current_seqnum = seqnum_reg; + + // Output FIFO for packetized data + localparam VITA_TRANS_HEADER = 0; + localparam VITA_HEADER = 1; + localparam VITA_STREAMID = 2; + localparam VITA_CLASSID = 3; + localparam VITA_CLASSID2 = 4; + localparam VITA_SECS = 5; + localparam VITA_TICS = 6; + localparam VITA_TICS2 = 7; + localparam VITA_PAYLOAD = 8; + localparam VITA_STORE = 9; + localparam VITA_TRAILER = 10; + localparam VITA_DUMP = 11; + + wire [15:0] hdr_len = 2 + has_streamid_reg + has_classid_reg + has_classid_reg + has_secs_reg + + has_tics_reg + has_tics_reg + has_trailer_reg; + + wire vita_eof = (pkt_len==hdr_len); + wire eop = eof | vita_eof; // FIXME would ignoring eof allow larger VITA packets? + wire fifo_space; + + always @(posedge clk) + if(reset | clear | clear_seqnum) + begin + seqnum_reg <= 32'hFFFF_FFFF; + vita_seqnum_reg <= 4'hF; + end + else + begin + if((vita_state==VITA_TRANS_HEADER) & src_rdy_i) + seqnum_reg <= seqnum; + if((vita_state==VITA_HEADER) & src_rdy_i) + vita_seqnum_reg <= vita_seqnum; + end // else: !if(reset | clear_seqnum) + + always @(posedge clk) + if(reset | clear) + begin + vita_state <= (USE_TRANS_HEADER==1) ? VITA_TRANS_HEADER : VITA_HEADER; + {has_streamid_reg, has_classid_reg, has_secs_reg, has_tics_reg, has_trailer_reg, is_sob_reg, is_eob_reg} + <= 0; + seqnum_err <= 0; + end + else + if((vita_state == VITA_STORE) & fifo_space) + if(vita_eof) + if(eof) + vita_state <= (USE_TRANS_HEADER==1) ? VITA_TRANS_HEADER : VITA_HEADER; + else if(has_trailer_reg) + vita_state <= VITA_TRAILER; + else + vita_state <= VITA_DUMP; + else + begin + vita_state <= VITA_PAYLOAD; + pkt_len <= pkt_len - 1; + end + else if(src_rdy_i) + case(vita_state) + VITA_TRANS_HEADER : + begin + seqnum_err <= ~(seqnum == next_seqnum); + vita_state <= VITA_HEADER; + end + VITA_HEADER : + begin + {has_streamid_reg, has_classid_reg, has_secs_reg, has_tics_reg, has_trailer_reg, is_sob_reg, is_eob_reg} + <= {has_streamid, has_classid, has_secs, has_tics, has_trailer, is_sob, is_eob}; + pkt_len <= data_i[15:0]; + vector_phase <= 0; + if(has_streamid) + vita_state <= VITA_STREAMID; + else if(has_classid) + vita_state <= VITA_CLASSID; + else if(has_secs) + vita_state <= VITA_SECS; + else if(has_tics) + vita_state <= VITA_TICS; + else + vita_state <= VITA_PAYLOAD; + seqnum_err <= seqnum_err | ~(vita_seqnum == next_vita_seqnum); + end // case: VITA_HEADER + VITA_STREAMID : + if(has_classid_reg) + vita_state <= VITA_CLASSID; + else if(has_secs_reg) + vita_state <= VITA_SECS; + else if(has_tics_reg) + vita_state <= VITA_TICS; + else + vita_state <= VITA_PAYLOAD; + VITA_CLASSID : + vita_state <= VITA_CLASSID2; + VITA_CLASSID2 : + if(has_secs_reg) + vita_state <= VITA_SECS; + else if(has_tics_reg) + vita_state <= VITA_TICS; + else + vita_state <= VITA_PAYLOAD; + VITA_SECS : + if(has_tics_reg) + vita_state <= VITA_TICS; + else + vita_state <= VITA_PAYLOAD; + VITA_TICS : + vita_state <= VITA_TICS2; + VITA_TICS2 : + vita_state <= VITA_PAYLOAD; + VITA_PAYLOAD : + if(line_done) + begin + vector_phase <= 0; + vita_state <= VITA_STORE; + end + else + vector_phase <= vector_phase + 1; + VITA_TRAILER : + if(eof) + vita_state <= (USE_TRANS_HEADER==1) ? VITA_TRANS_HEADER : VITA_HEADER; + else + vita_state <= VITA_DUMP; + VITA_DUMP : + if(eof) + vita_state <= (USE_TRANS_HEADER==1) ? VITA_TRANS_HEADER : VITA_HEADER; + VITA_STORE : + ; + default : + vita_state <= (USE_TRANS_HEADER==1) ? VITA_TRANS_HEADER : VITA_HEADER; + endcase // case (vita_state) + + assign line_done = (vector_phase == numchan); + + wire [FIFOWIDTH-1:0] fifo_i; + reg [63:0] send_time; + reg [31:0] sample_a, sample_b, sample_c, sample_d; + + always @(posedge clk) + case(vita_state) + VITA_SECS : + send_time[63:32] <= data_i[31:0]; + VITA_TICS2 : + send_time[31:0] <= data_i[31:0]; + endcase // case (vita_state) + + always @(posedge clk) + if(vita_state == VITA_PAYLOAD) + case(vector_phase) + 0: sample_a <= data_i[31:0]; + 1: sample_b <= data_i[31:0]; + 2: sample_c <= data_i[31:0]; + 3: sample_d <= data_i[31:0]; + endcase // case (vector_phase) + + wire store = (vita_state == VITA_STORE); + fifo_short #(.WIDTH(FIFOWIDTH)) short_tx_q + (.clk(clk), .reset(reset), .clear(clear), + .datain(fifo_i), .src_rdy_i(store), .dst_rdy_o(fifo_space), + .dataout(sample_fifo_o), .src_rdy_o(sample_fifo_src_rdy_o), .dst_rdy_i(sample_fifo_dst_rdy_i) ); + + // sob, eob, has_secs (send_at) ignored on all lines except first + assign fifo_i = {sample_d,sample_c,sample_b,sample_a,seqnum_err,has_secs_reg,is_sob_reg,is_eob_reg,eop, + 12'd0,seqnum_reg[3:0],send_time}; + + assign dst_rdy_o = ~(vita_state == VITA_PAYLOAD) & ~((vita_state==VITA_STORE)& ~fifo_space) ; + + assign debug = { { 8'b0 }, + { 8'b0 }, + { eof, line_done, store, fifo_space, src_rdy_i, dst_rdy_o, vector_phase[1:0] }, + { has_secs_reg, is_sob_reg, is_eob_reg, eop, vita_state[3:0] } }; + +endmodule // vita_tx_deframer |