diff options
Diffstat (limited to 'fpga/usrp2/vrt/vita_rx_control.v')
-rw-r--r-- | fpga/usrp2/vrt/vita_rx_control.v | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/fpga/usrp2/vrt/vita_rx_control.v b/fpga/usrp2/vrt/vita_rx_control.v new file mode 100644 index 000000000..93673d292 --- /dev/null +++ b/fpga/usrp2/vrt/vita_rx_control.v @@ -0,0 +1,191 @@ + +module vita_rx_control + #(parameter BASE=0, + parameter WIDTH=32) + (input clk, input reset, input clear, + input set_stb, input [7:0] set_addr, input [31:0] set_data, + + input [63:0] vita_time, + output overrun, + + // To vita_rx_framer + output [4+64+WIDTH-1:0] sample_fifo_o, + output sample_fifo_src_rdy_o, + input sample_fifo_dst_rdy_i, + + // From DSP Core + input [WIDTH-1:0] sample, + output run, + input strobe, + + output [31:0] debug_rx + ); + + // FIXME add TX Interruption (halt, pause, continue) functionality + + wire [63:0] new_time; + wire [31:0] new_command; + wire sc_pre1, clear_int, clear_reg; + + assign clear_int = clear | clear_reg; + + wire [63:0] rcvtime_pre; + reg [63:0] rcvtime; + wire [28:0] numlines_pre; + wire send_imm_pre, chain_pre, reload_pre; + reg send_imm, chain, reload; + wire full_ctrl, read_ctrl, empty_ctrl, write_ctrl; + reg sc_pre2; + wire [33:0] fifo_line; + reg [28:0] lines_left, lines_total; + reg [2:0] ibs_state; + wire now, early, late; + wire sample_fifo_in_rdy; + + setting_reg #(.my_addr(BASE)) sr_cmd + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(new_command),.changed()); + + setting_reg #(.my_addr(BASE+1)) sr_time_h + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(new_time[63:32]),.changed()); + + setting_reg #(.my_addr(BASE+2)) sr_time_l + (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(new_time[31:0]),.changed(sc_pre1)); + + 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)); + + // FIFO to store commands sent from the settings bus + always @(posedge clk) + sc_pre2 <= sc_pre1; + assign write_ctrl = sc_pre1 & ~sc_pre2; + + wire [4:0] command_queue_len; + shortfifo #(.WIDTH(96)) commandfifo + (.clk(clk),.rst(reset),.clear(clear_int), + .datain({new_command,new_time}), .write(write_ctrl&~full_ctrl), .full(full_ctrl), + .dataout({send_imm_pre,chain_pre,reload_pre,numlines_pre,rcvtime_pre}), + .read(read_ctrl), .empty(empty_ctrl), + .occupied(command_queue_len), .space() ); + + reg [33:0] pkt_fifo_line; + + localparam IBS_IDLE = 0; + localparam IBS_WAITING = 1; + localparam IBS_RUNNING = 2; + localparam IBS_OVERRUN = 4; + localparam IBS_BROKENCHAIN = 5; + localparam IBS_LATECMD = 6; + + wire signal_cmd_done = (lines_left == 1) & (~chain | (~empty_ctrl & (numlines_pre==0))); + wire signal_overrun = (ibs_state == IBS_OVERRUN); + wire signal_brokenchain = (ibs_state == IBS_BROKENCHAIN); + wire signal_latecmd = (ibs_state == IBS_LATECMD); + + // Buffer of samples for while we're writing the packet headers + wire [3:0] flags = {signal_overrun,signal_brokenchain,signal_latecmd,signal_cmd_done}; + + wire attempt_sample_write = ((run & strobe) | (ibs_state==IBS_OVERRUN) | + (ibs_state==IBS_BROKENCHAIN) | (ibs_state==IBS_LATECMD)); + + fifo_short #(.WIDTH(4+64+WIDTH)) rx_sample_fifo + (.clk(clk),.reset(reset),.clear(clear_int), + .datain({flags,vita_time,sample}), .src_rdy_i(attempt_sample_write), .dst_rdy_o(sample_fifo_in_rdy), + .dataout(sample_fifo_o), + .src_rdy_o(sample_fifo_src_rdy_o), .dst_rdy_i(sample_fifo_dst_rdy_i), + .space(), .occupied() ); + + // Inband Signalling State Machine + time_compare + time_compare (.time_now(vita_time), .trigger_time(rcvtime), .now(now), .early(early), .late(late)); + + wire too_late = late & ~send_imm; + wire go_now = now | send_imm; + wire full = ~sample_fifo_in_rdy; + + always @(posedge clk) + if(reset | clear_int) + begin + ibs_state <= IBS_IDLE; + lines_left <= 0; + lines_total <= 0; + rcvtime <= 0; + send_imm <= 0; + chain <= 0; + reload <= 0; + end + else + case(ibs_state) + IBS_IDLE : + if(~empty_ctrl) + begin + lines_left <= numlines_pre; + lines_total <= numlines_pre; + rcvtime <= rcvtime_pre; + ibs_state <= IBS_WAITING; + send_imm <= send_imm_pre; + chain <= chain_pre; + reload <= reload_pre; + end + IBS_WAITING : + if(go_now) + ibs_state <= IBS_RUNNING; + else if(too_late) + ibs_state <= IBS_LATECMD; + IBS_RUNNING : + if(strobe) + if(full) + ibs_state <= IBS_OVERRUN; + else + begin + lines_left <= lines_left - 1; + if(lines_left == 1) + if(~chain) + ibs_state <= IBS_IDLE; + else if(empty_ctrl & reload) + begin + ibs_state <= IBS_RUNNING; + lines_left <= lines_total; + end + else if(empty_ctrl) + ibs_state <= IBS_BROKENCHAIN; + else + begin + lines_left <= numlines_pre; + lines_total <= numlines_pre; + rcvtime <= rcvtime_pre; + send_imm <= send_imm_pre; + chain <= chain_pre; + reload <= reload_pre; + if(numlines_pre == 0) // If we are told to stop here + ibs_state <= IBS_IDLE; + else + ibs_state <= IBS_RUNNING; + end + end // else: !if(full) + IBS_OVERRUN : + if(sample_fifo_in_rdy) + ibs_state <= IBS_IDLE; + IBS_LATECMD : + if(sample_fifo_in_rdy) + ibs_state <= IBS_IDLE; + IBS_BROKENCHAIN : + if(sample_fifo_in_rdy) + ibs_state <= IBS_IDLE; + endcase // case(ibs_state) + + assign overrun = (ibs_state == IBS_OVERRUN); + assign run = (ibs_state == IBS_RUNNING); + + assign read_ctrl = ( (ibs_state == IBS_IDLE) | ((ibs_state == IBS_RUNNING) & strobe & ~full & (lines_left==1) & chain) ) + & ~empty_ctrl; + + assign debug_rx = { { ibs_state[2:0], command_queue_len }, + { 8'd0 }, + { go_now, too_late, run, strobe, read_ctrl, write_ctrl, full_ctrl, empty_ctrl }, + { 2'b0, overrun, chain_pre, sample_fifo_in_rdy, attempt_sample_write, sample_fifo_src_rdy_o,sample_fifo_dst_rdy_i} }; + +endmodule // rx_control |