diff options
Diffstat (limited to 'fpga/usrp3/lib/control/radio_ctrl_proc.v')
-rw-r--r-- | fpga/usrp3/lib/control/radio_ctrl_proc.v | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/control/radio_ctrl_proc.v b/fpga/usrp3/lib/control/radio_ctrl_proc.v new file mode 100644 index 000000000..723ba69ff --- /dev/null +++ b/fpga/usrp3/lib/control/radio_ctrl_proc.v @@ -0,0 +1,143 @@ + + +// Radio Control Processor +// Accepts compressed vita extension context packets of the following form: +// { VITA Compressed Header, Stream ID } +// { Optional 64 bit time } +// { 16'h0, setting bus address [15:0], setting [31:0] } +// +// If there is a timestamp, packet is held until that time comes. +// Goes immediately if there is no timestamp or if time has passed. +// Sends out setting to setting bus, and then generates a response packet +// with the same sequence number, the src/dest swapped streamid, and the actual time +// the setting was sent. +// +// Note -- if t0 is the requested time, the actual send time on the setting bus is t0 + 1 cycle. +// Note 2 -- if t1 is the actual time the setting bus, t1+2 is the reported time. + +module radio_ctrl_proc + (input clk, input reset, input clear, + + input [63:0] ctrl_tdata, input ctrl_tlast, input ctrl_tvalid, output reg ctrl_tready, + output reg [63:0] resp_tdata, output reg resp_tlast, output resp_tvalid, input resp_tready, + + input [63:0] vita_time, + + output set_stb, output [7:0] set_addr, output [31:0] set_data, + input ready, + + input [63:0] readback, + + output [31:0] debug); + + localparam RC_HEAD = 4'd0; + localparam RC_TIME = 4'd1; + localparam RC_DATA = 4'd2; + localparam RC_DUMP = 4'd3; + localparam RC_RESP_HEAD = 4'd4; + localparam RC_RESP_TIME = 4'd5; + localparam RC_RESP_DATA = 4'd6; + + wire IS_EC = ctrl_tdata[63]; + wire HAS_TIME = ctrl_tdata[61]; + reg HAS_TIME_reg; + + reg [3:0] rc_state; + reg [63:0] cmd_time; + + wire now, late, go; + reg [11:0] seqnum; + reg [31:0] sid; + + always @(posedge clk) + if(reset) + begin + rc_state <= RC_HEAD; + HAS_TIME_reg <= 1'b0; + sid <= 32'd0; + seqnum <= 12'd0; + end + else + case(rc_state) + RC_HEAD : + if(ctrl_tvalid) + begin + sid <= ctrl_tdata[31:0]; + seqnum <= ctrl_tdata[59:48]; + HAS_TIME_reg <= HAS_TIME; + if(IS_EC) + if(HAS_TIME) + rc_state <= RC_TIME; + else + rc_state <= RC_DATA; + else + if(~ctrl_tlast) + rc_state <= RC_DUMP; + end + + RC_TIME : + if(ctrl_tvalid) + if(ctrl_tlast) + rc_state <= RC_RESP_HEAD; + else if(go) + rc_state <= RC_DATA; + + RC_DATA : + if(ctrl_tvalid) + if(ready) + if(ctrl_tlast) + rc_state <= RC_RESP_HEAD; + else + rc_state <= RC_DUMP; + + RC_DUMP : + if(ctrl_tvalid) + if(ctrl_tlast) + rc_state <= RC_RESP_HEAD; + + RC_RESP_HEAD : + if(resp_tready) + rc_state <= RC_RESP_TIME; + + RC_RESP_TIME : + if(resp_tready) + rc_state <= RC_RESP_DATA; + + RC_RESP_DATA: + if(resp_tready) + rc_state <= RC_HEAD; + + default : + rc_state <= RC_HEAD; + endcase // case (rc_state) + + always @* + case (rc_state) + RC_HEAD : ctrl_tready <= 1'b1; + RC_TIME : ctrl_tready <= ctrl_tlast | go; + RC_DATA : ctrl_tready <= ready; + RC_DUMP : ctrl_tready <= 1'b1; + default : ctrl_tready <= 1'b0; + endcase // case (rc_state) + + time_compare time_compare + (.clk(clk), .reset(reset), .time_now(vita_time), .trigger_time(ctrl_tdata), .now(now), .early(), .late(late), .too_early()); + + assign go = now | late; + + assign set_stb = (rc_state == RC_DATA) & ready & ctrl_tvalid; + assign set_addr = ctrl_tdata[39:32]; + assign set_data = ctrl_tdata[31:0]; + + always @* + case (rc_state) + RC_RESP_HEAD : { resp_tlast, resp_tdata } <= {1'b0, 4'hA, seqnum, 16'd24, sid[15:0], sid[31:16] }; + RC_RESP_TIME : { resp_tlast, resp_tdata } <= {1'b0, vita_time}; + RC_RESP_DATA : { resp_tlast, resp_tdata } <= {1'b1, readback}; + default : { resp_tlast, resp_tdata } <= 65'h0; + endcase // case (rc_state) + + assign resp_tvalid = (rc_state == RC_RESP_HEAD) | (rc_state == RC_RESP_TIME) | (rc_state == RC_RESP_DATA); + +endmodule // radio_ctrl_proc + |