diff options
Diffstat (limited to 'usrp/fpga/inband_lib/cmd_reader.v')
-rwxr-xr-x | usrp/fpga/inband_lib/cmd_reader.v | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/usrp/fpga/inband_lib/cmd_reader.v b/usrp/fpga/inband_lib/cmd_reader.v new file mode 100755 index 000000000..7604321e4 --- /dev/null +++ b/usrp/fpga/inband_lib/cmd_reader.v @@ -0,0 +1,292 @@ +module cmd_reader( + //System + input reset, + input txclk, + input [31:0] adc_time, + //FX2 Side + output reg skip, + output reg rdreq, + input [31:0] fifodata, + input pkt_waiting, + //Rx side + input rx_WR_enabled, + output reg [15:0] rx_databus, + output reg rx_WR, + output reg rx_WR_done, + //register io + input wire [31:0] reg_data_out, + output reg [31:0] reg_data_in, + output reg [6:0] reg_addr, + output reg [1:0] reg_io_enable, + output wire [14:0] debug + ); + + // States + parameter IDLE = 4'd0; + parameter HEADER = 4'd1; + parameter TIMESTAMP = 4'd2; + parameter WAIT = 4'd3; + parameter TEST = 4'd4; + parameter SEND = 4'd5; + parameter PING = 4'd6; + parameter WRITE_REG = 4'd7; + parameter WRITE_REG_MASKED = 4'd8; + parameter READ_REG = 4'd9; + parameter DELAY = 4'd14; + + `define OP_PING_FIXED 8'd0 + `define OP_PING_FIXED_REPLY 8'd1 + `define OP_WRITE_REG 8'd2 + `define OP_WRITE_REG_MASKED 8'd3 + `define OP_READ_REG 8'd4 + `define OP_READ_REG_REPLY 8'd5 + `define OP_DELAY 8'd12 + + reg [6:0] payload; + reg [6:0] payload_read; + reg [3:0] state; + reg [15:0] high; + reg [15:0] low; + reg pending; + reg [31:0] value0; + reg [31:0] value1; + reg [31:0] value2; + reg [1:0] lines_in; + reg [1:0] lines_out; + reg [1:0] lines_out_total; + + `define JITTER 5 + `define OP_CODE 31:24 + `define PAYLOAD 8:2 + + wire [7:0] ops; + assign ops = value0[`OP_CODE]; + assign debug = {state[3:0], lines_out[1:0], pending, rx_WR, rx_WR_enabled, value0[2:0], ops[2:0]}; + + always @(posedge txclk) + if (reset) + begin + pending <= 0; + state <= IDLE; + skip <= 0; + rdreq <= 0; + rx_WR <= 0; + reg_io_enable <= 0; + reg_data_in <= 0; + reg_addr <= 0; + end + else case (state) + IDLE : begin + payload_read <= 0; + skip <= 0; + lines_in <= 0; + if (pkt_waiting) + begin + state <= HEADER; + rdreq <= 1; + end + end + + HEADER : begin + payload <= fifodata[`PAYLOAD]; + state <= TIMESTAMP; + end + + TIMESTAMP : begin + value0 <= fifodata; + state <= WAIT; + rdreq <= 0; + end + + WAIT : begin + // Let's send it + if ((value0 <= adc_time + `JITTER + && value0 > adc_time) + || value0 == 32'hFFFFFFFF) + state <= TEST; + // Wait a little bit more + else if (value0 > adc_time + `JITTER) + state <= WAIT; + // Outdated + else if (value0 < adc_time) + begin + state <= IDLE; + skip <= 1; + end + end + + TEST : begin + reg_io_enable <= 0; + rx_WR <= 0; + rx_WR_done <= 1; + if (payload_read == payload) + begin + skip <= 1; + state <= IDLE; + rdreq <= 0; + end + else + begin + value0 <= fifodata; + lines_in <= 2'd1; + rdreq <= 1; + payload_read <= payload_read + 7'd1; + lines_out <= 0; + case (fifodata[`OP_CODE]) + `OP_PING_FIXED: begin + state <= PING; + end + `OP_WRITE_REG: begin + state <= WRITE_REG; + pending <= 1; + end + `OP_WRITE_REG_MASKED: begin + state <= WRITE_REG_MASKED; + pending <= 1; + end + `OP_READ_REG: begin + state <= READ_REG; + end + `OP_DELAY: begin + state <= DELAY; + end + default: begin + //error, skip this packet + skip <= 1; + state <= IDLE; + end + endcase + end + end + + SEND: begin + rdreq <= 0; + rx_WR_done <= 0; + if (pending) + begin + rx_WR <= 1; + rx_databus <= high; + pending <= 0; + if (lines_out == lines_out_total) + state <= TEST; + else case (ops) + `OP_READ_REG: begin + state <= READ_REG; + end + default: begin + state <= TEST; + end + endcase + end + else + begin + if (rx_WR_enabled) + begin + rx_WR <= 1; + rx_databus <= low; + pending <= 1; + lines_out <= lines_out + 2'd1; + end + else + rx_WR <= 0; + end + end + + PING: begin + rx_WR <= 0; + rdreq <= 0; + rx_WR_done <= 0; + lines_out_total <= 2'd1; + pending <= 0; + state <= SEND; + high <= {`OP_PING_FIXED_REPLY, 8'd2}; + low <= value0[15:0]; + end + + READ_REG: begin + rx_WR <= 0; + rx_WR_done <= 0; + rdreq <= 0; + lines_out_total <= 2'd2; + pending <= 0; + state <= SEND; + if (lines_out == 0) + begin + high <= {`OP_READ_REG_REPLY, 8'd6}; + low <= value0[15:0]; + reg_io_enable <= 2'd3; + reg_addr <= value0[6:0]; + end + else + begin + high <= reg_data_out[31:16]; + low <= reg_data_out[15:0]; + end + end + + WRITE_REG: begin + rx_WR <= 0; + if (pending) + pending <= 0; + else + begin + if (lines_in == 2'd1) + begin + payload_read <= payload_read + 7'd1; + lines_in <= lines_in + 2'd1; + value1 <= fifodata; + rdreq <= 0; + end + else + begin + reg_io_enable <= 2'd2; + reg_data_in <= value1; + reg_addr <= value0[6:0]; + state <= TEST; + end + end + end + + WRITE_REG_MASKED: begin + rx_WR <= 0; + if (pending) + pending <= 0; + else + begin + if (lines_in == 2'd1) + begin + rdreq <= 1; + payload_read <= payload_read + 7'd1; + lines_in <= lines_in + 2'd1; + value1 <= fifodata; + end + else if (lines_in == 2'd2) + begin + rdreq <= 0; + payload_read <= payload_read + 7'd1; + lines_in <= lines_in + 2'd1; + value2 <= fifodata; + end + else + begin + reg_io_enable <= 2'd2; + reg_data_in <= (value1 & value2); + reg_addr <= value0[6:0]; + state <= TEST; + end + end + end + + DELAY : begin + rdreq <= 0; + value1 <= value1 + 32'd1; + if (value0[15:0] == value1[15:0]) + state <= TEST; + end + + default : begin + //error state handling + state <= IDLE; + end + endcase +endmodule
\ No newline at end of file |