Files
b210-k7-fpga/lib/control/radio_ctrl_proc.v
T
Ben Hilburn c91b74de33 Squashed B200 FPGA Source. Code from Josh Blum, Ian Buckley, and Matt Ettus.
Original-commit: 0df4b801a34697f2058b4a7b95e08d2a0576c9db
2013-10-10 10:17:27 -07:00

144 lines
3.8 KiB
Verilog

// 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