diff options
-rwxr-xr-x | vrt/vita_tx.build | 2 | ||||
-rw-r--r-- | vrt/vita_tx_deframer.v | 320 | ||||
-rw-r--r-- | vrt/vita_tx_tb.v | 99 |
3 files changed, 182 insertions, 239 deletions
diff --git a/vrt/vita_tx.build b/vrt/vita_tx.build index 2d65537d5..902929c08 100755 --- a/vrt/vita_tx.build +++ b/vrt/vita_tx.build @@ -1 +1 @@ -iverilog -Wimplict -Wportbind -y ../models -y . -y ../control_lib/ -y ../coregen -y /opt/Xilinx/10.1/ISE/verilog/src/XilinxCoreLib -y /opt/Xilinx/10.1/ISE/verilog/src/unisims/ -y ../timing -o vita_tx_tb vita_tx_tb.v +iverilog -Wimplict -Wportbind -y ../sdr_lib -y ../models -y . -y ../control_lib/ -y ../control_lib/newfifo -y ../coregen -y /opt/Xilinx/10.1/ISE/verilog/src/XilinxCoreLib -y /opt/Xilinx/10.1/ISE/verilog/src/unisims/ -y ../timing -o vita_tx_tb vita_tx_tb.v diff --git a/vrt/vita_tx_deframer.v b/vrt/vita_tx_deframer.v index 4a3430b0f..3df88d7f4 100644 --- a/vrt/vita_tx_deframer.v +++ b/vrt/vita_tx_deframer.v @@ -20,17 +20,27 @@ module vita_tx_deframer output fifo_empty ); + wire [1:0] numchan; + setting_reg #(.my_addr(BASE+8), .at_reset(0)) 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'b001); assign has_classid = data_i[27]; - assign has_secs = ~(data[23:22]==2'b00); - assign has_tics = ~(data[21:20]==2'b00); - assign has_trailer = data[26]; + assign has_secs = ~(data_i[23:22]==2'b00); + assign has_tics = ~(data_i[21:20]==2'b00); + assign has_trailer = data_i[26]; + assign is_sob = data_i[25]; + assign 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 [1:0] vector_phase; + wire line_done; - - reg has_streamid_reg, has_classid_reg, has_secs_reg, has_tics_reg, has_trailer_reg; // Output FIFO for packetized data localparam VITA_HEADER = 0; localparam VITA_STREAMID = 1; @@ -40,230 +50,120 @@ module vita_tx_deframer localparam VITA_TICS = 5; localparam VITA_TICS2 = 6; localparam VITA_PAYLOAD = 7; - localparam VITA_TRAILER = 8; - 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; - + localparam VITA_WAIT = 8; + localparam VITA_TRAILER = 9; always @(posedge clk) if(reset | clear) begin vita_state <= VITA_HEADER; - {has_streamid_reg, has_classid_reg, has_secs_reg, has_tics_reg, has_trailer_reg} + {has_streamid_reg, has_classid_reg, has_secs_reg, has_tics_reg, has_trailer_reg, is_sob_reg, is_eob_reg} <= 0; - else if(src_rdy_i & sample_fifo_dst_rdy_i) - case(vita_state) - VITA_HEADER : - begin - {has_streamid_reg, has_classid_reg, has_secs_reg, has_tics_reg, has_trailer_reg} - <= {has_streamid, has_classid, has_secs, has_tics, has_trailer}; - 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; - 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 : - else 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 : + end + else + if((vita_state == VITA_WAIT) & fifo_space) + if(eof) // FIXME if(has_trailer_reg) vita_state <= VITA_TRAILER; else vita_state <= VITA_HEADER; - VITA_TRAILER : - vita_state <= VITA_HEADER; - endcase // case (vita_state) - - - always @* - case(vita_state) - VITA_HEADER, VITA_ERR_HEADER : pkt_fifo_line <= {2'b01,vita_header[31:20],pkt_count,vita_pkt_len}; - VITA_STREAMID, VITA_ERR_STREAMID : pkt_fifo_line <= {2'b00,vita_streamid}; - VITA_SECS, VITA_ERR_SECS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]}; - VITA_TICS, VITA_ERR_TICS : pkt_fifo_line <= {2'b00,32'd0}; - VITA_TICS2, VITA_ERR_TICS2 : pkt_fifo_line <= {2'b00,vita_time_fifo_o[31:0]}; - VITA_PAYLOAD : pkt_fifo_line <= {2'b00,data_fifo_o}; - VITA_ERR_PAYLOAD : pkt_fifo_line <= {2'b00,28'd0,flags_fifo_o}; - VITA_TRAILER : pkt_fifo_line <= {2'b10,vita_trailer}; - VITA_ERR_TRAILER : pkt_fifo_line <= {2'b11,vita_trailer}; - default : pkt_fifo_line <= 34'h0_FFFF_FFFF; - endcase // case (vita_state) - - - - - - localparam SAMP_WIDTH = 4+64+(32*MAXCHAN); - reg [3:0] sample_phase; - wire [3:0] numchan; - wire [3:0] flags_fifo_o = sample_fifo_i[SAMP_WIDTH-1:SAMP_WIDTH-4]; - wire [63:0] vita_time_fifo_o = sample_fifo_i[SAMP_WIDTH-5:SAMP_WIDTH-68]; - - reg [31:0] data_fifo_o; - wire [127:0] XILINX_SUCKS = sample_fifo_i; - always @* - case(sample_phase) - 4'd0 : data_fifo_o = XILINX_SUCKS[31:0]; - 4'd1 : data_fifo_o = XILINX_SUCKS[63:32]; - 4'd2 : data_fifo_o = XILINX_SUCKS[95:64]; - 4'd3 : data_fifo_o = XILINX_SUCKS[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 [3:0] flags = {signal_overrun,signal_brokenchain,signal_latecmd,signal_cmd_done}; - - wire clear_reg; - wire clear_int = clear | clear_reg; - - setting_reg #(.my_addr(BASE+3)) sr_clear - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out(),.changed(clear_reg)); - - 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)) 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), .at_reset(1)) sr_numchan - (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out(numchan),.changed()); - - always @(posedge clk) - if(reset | clear_pkt_count) - pkt_count <= 0; - else if((vita_state == VITA_TRAILER) & pkt_fifo_rdy) - pkt_count <= pkt_count + 1; - - always @(posedge clk) - if(reset) - 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[3:1]) - vita_state <= VITA_ERR_HEADER; - else - vita_state <= VITA_HEADER; - end - else if(pkt_fifo_rdy) + else + vita_state <= VITA_PAYLOAD; + else if(src_rdy_i) case(vita_state) + 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}; + 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; + 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(sample_fifo_src_rdy_i) + if(line_done) begin - if(sample_phase == (numchan-4'd1)) - begin - sample_phase <= 0; - sample_ctr <= sample_ctr + 1; - 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; + vector_phase <= 0; + vita_state <= VITA_WAIT; end - VITA_TRAILER, VITA_ERR_TRAILER : - vita_state <= VITA_IDLE; + else + vector_phase <= vector_phase + 1; + VITA_TRAILER : + vita_state <= VITA_HEADER; + VITA_WAIT : + ; default : - vita_state <= vita_state + 1; + vita_state <= VITA_HEADER; endcase // case (vita_state) - reg req_write_pkt_fifo; - always @* + assign line_done = (vector_phase == numchan); + + wire [4+64+32*MAXCHAN-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_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[3:1]); - VITA_ERR_HEADER, VITA_ERR_STREAMID, VITA_ERR_SECS, VITA_ERR_TICS, VITA_ERR_TICS2, VITA_ERR_PAYLOAD, VITA_ERR_TRAILER : - req_write_pkt_fifo <= 1; - default : - req_write_pkt_fifo <= 0; + VITA_SECS : + send_time[63:32] <= data_i[31:0]; + VITA_TICS2 : + send_time[31:0] <= data_i[31:0]; + VITA_WAIT, VITA_HEADER : + send_time[63:0] <= 64'd0; 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_int), - .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(fifo_occupied[4:0]) ); - assign fifo_occupied[15:5] = 0; - 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[3:1]) | - (vita_state==VITA_ERR_TRAILER)); + 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) - assign debug_rx = 0; + + fifo_short #(.WIDTH(4+64+32*MAXCHAN)) short_tx_q + (.clk(clk), .reset(reset), .clear(clear), + .datain(fifo_i), .src_rdy_i(vita_state == VITA_IDLE), .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,has_secs_reg,is_sob_reg,is_eob_reg,eof,send_time}; + + assign dst_rdy_o = (vita_state != VITA_PAYLOAD); -endmodule // rx_control +endmodule // vita_tx_deframer diff --git a/vrt/vita_tx_tb.v b/vrt/vita_tx_tb.v index 94b7bdd0b..62532c07c 100644 --- a/vrt/vita_tx_tb.v +++ b/vrt/vita_tx_tb.v @@ -2,9 +2,11 @@ module vita_tx_tb; - localparam INTERP = 8'd4; + localparam DECIM = 8'd4; + localparam INTERP = 8'd4; + localparam MAXCHAN=4; - localparam NUMCHAN=4; + localparam NUMCHAN=1; reg clk = 0; reg reset = 1; @@ -12,14 +14,15 @@ module vita_tx_tb; initial #1000 reset = 0; always #50 clk = ~clk; - initial $dumpfile("vita_rx_tb.vcd"); - initial $dumpvars(0,vita_rx_tb); + initial $dumpfile("vita_tx_tb.vcd"); + initial $dumpvars(0,vita_tx_tb); wire [(MAXCHAN*32)-1:0] sample; wire strobe, run; wire [35:0] data_o; wire src_rdy; - reg dst_rdy = 1; + wire dst_rdy; + wire [63:0] vita_time; reg set_stb = 0; @@ -29,41 +32,63 @@ module vita_tx_tb; wire [7:0] set_addr_dsp; wire [31:0] set_data_dsp; + /* settings_bus_crossclock settings_bus_xclk_dsp (.clk_i(clk), .rst_i(reset), .set_stb_i(set_stb), .set_addr_i(set_addr), .set_data_i(set_data), .clk_o(clk), .rst_o(reset), .set_stb_o(set_stb_dsp), .set_addr_o(set_addr_dsp), .set_data_o(set_data_dsp)); - + */ + wire sample_dst_rdy, sample_src_rdy; //wire [99:0] sample_data_o; - wire [64+4+(MAXCHAN*32)-1:0] sample_data_o; + wire [64+4+(MAXCHAN*32)-1:0] sample_data_o, sample_data_tx; + + time_64bit #(.TICKS_PER_SEC(120000000), .BASE(0)) time_64bit + (.clk(clk), .rst(reset), + .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), + .pps(0), .vita_time(vita_time)); + + rx_dsp_model rx_dsp_model + (.clk(clk), .reset(reset), .run(run), .decim(DECIM), .strobe(strobe), .sample(sample[31:0])); + generate + if(MAXCHAN>1) + assign sample[(MAXCHAN*32)-1:32] = 0; + endgenerate + vita_rx_control #(.BASE(0), .WIDTH(32*MAXCHAN)) vita_rx_control (.clk(clk), .reset(reset), .clear(0), - .set_stb(set_stb_dsp), .set_addr(set_addr_dsp), .set_data(set_data_dsp), + .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), .vita_time(vita_time), .overrun(overrun), .sample_fifo_o(sample_data_o), .sample_fifo_dst_rdy_i(sample_dst_rdy), .sample_fifo_src_rdy_o(sample_src_rdy), .sample(sample), .run(run), .strobe(strobe)); vita_rx_framer #(.BASE(0), .MAXCHAN(MAXCHAN)) vita_rx_framer (.clk(clk), .reset(reset), .clear(0), - .set_stb(set_stb_dsp), .set_addr(set_addr_dsp), .set_data(set_data_dsp), + .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), .data_o(data_o), .dst_rdy_i(dst_rdy), .src_rdy_o(src_rdy), .sample_fifo_i(sample_data_o), .sample_fifo_dst_rdy_o(sample_dst_rdy), .sample_fifo_src_rdy_i(sample_src_rdy), .fifo_occupied(), .fifo_full(), .fifo_empty() ); - - rx_dsp_model rx_dsp_model - (.clk(clk), .reset(reset), .run(run), .decim(DECIM), .strobe(strobe), .sample(sample[31:0])); - generate - if(MAXCHAN>1) - assign sample[(MAXCHAN*32)-1:32] = 0; - endgenerate + wire [35:0] data_tx; + wire src_rdy_tx, dst_rdy_tx; + wire sample_dst_rdy_tx, sample_src_rdy_tx; - time_64bit #(.TICKS_PER_SEC(120000000), .BASE(0)) time_64bit - (.clk(clk), .rst(reset), - .set_stb(set_stb_dsp), .set_addr(set_addr_dsp), .set_data(set_data_dsp), - .pps(0), .vita_time(vita_time)); + fifo_long #(.WIDTH(36)) fifo_short + (.clk(clk), .reset(reset), .clear(0), + .datain(data_o), .src_rdy_i(src_rdy), .dst_rdy_o(dst_rdy), + .dataout(data_tx), .src_rdy_o(src_rdy_tx), .dst_rdy_i(dst_rdy_tx)); + vita_tx_deframer #(.BASE(16), .MAXCHAN(MAXCHAN)) vita_tx_deframer + (.clk(clk), .reset(reset), .clear(0), + .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), + .data_i(data_tx), .dst_rdy_o(dst_rdy_tx), .src_rdy_i(src_rdy_tx), + .sample_fifo_o(sample_data_tx), + .sample_fifo_dst_rdy_i(sample_dst_rdy_tx), .sample_fifo_src_rdy_o(sample_src_rdy_tx), + .fifo_occupied(), .fifo_full(), .fifo_empty() ); + + tx_dsp_model tx_dsp_model + (.clk(clk), .reset(reset), .run(run), .interp(INTERP), .strobe(strobe), .sample(sample[31:0] )); + always @(posedge clk) if(src_rdy & dst_rdy) begin @@ -90,13 +115,14 @@ module vita_tx_tb; begin @(negedge reset); @(posedge clk); - write_setting(4,32'hDEADBEEF); // VITA header + write_setting(4,32'h14900008); // VITA header write_setting(5,32'hF00D1234); // VITA streamid write_setting(6,32'h98765432); // VITA trailer write_setting(7,8); // Samples per VITA packet write_setting(8,NUMCHAN); // Samples per VITA packet queue_rx_cmd(1,0,8,32'h0,32'h0); // send imm, single packet - queue_rx_cmd(1,0,16,32'h0,32'h0); // send imm, 2 packets worth +/* + queue_rx_cmd(1,0,16,32'h0,32'h0); // send imm, 2 packets worth queue_rx_cmd(1,0,7,32'h0,32'h0); // send imm, 1 short packet worth queue_rx_cmd(1,0,9,32'h0,32'h0); // send imm, just longer than 1 packet @@ -124,19 +150,19 @@ module vita_tx_tb; queue_rx_cmd(1,1,9,32'h0,32'h0); // chained, but break chain, odd length #100000; - dst_rdy <= 0; // stop pulling out of fifo so we can get an overrun + //dst_rdy <= 0; // stop pulling out of fifo so we can get an overrun queue_rx_cmd(1,0,100,32'h0,32'h0); // long enough to fill the fifos queue_rx_cmd(1,0,5,32'h0,32'h0); // this command waits until the previous error packet is sent #100000; - dst_rdy <= 1; // restart the reads so we can see what we got + //dst_rdy <= 1; // restart the reads so we can see what we got #100000; - dst_rdy <= 0; // stop pulling out of fifo so we can get an overrun + //dst_rdy <= 0; // stop pulling out of fifo so we can get an overrun queue_rx_cmd(1,1,100,32'h0,32'h0); // long enough to fill the fifos //queue_rx_cmd(1,0,5,32'h0,32'h0); // this command waits until the previous error packet is sent #100000; @(posedge clk); - dst_rdy <= 1; - + //dst_rdy <= 1; + */ #100000 $finish; end @@ -167,7 +193,8 @@ module vita_tx_tb; end endtask // queue_rx_cmd -endmodule // rx_control_tb +endmodule // vita_tx_tb + module rx_dsp_model (input clk, input reset, @@ -209,3 +236,19 @@ module rx_dsp_model assign strobe = stb_ctr == decim-1; endmodule // rx_dsp_model + +module tx_dsp_model + (input clk, input reset, + input run, + input [7:0] interp, + output strobe, + input [31:0] sample); + + cic_strober strober(.clock(clk), .reset(reset), .enable(run), .rate(interp), .strobe_fast(1), .strobe_slow(strobe)); + + always @(posedge clk) + if(strobe) + $display("Time %d, Sent Sample %x",$time,sample); + + +endmodule // tx_dsp_model |