// // Copyright 2012 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // A settings and readback bus controlled via fifo36 interface module settings_fifo_ctrl #( parameter XPORT_HDR = 1, //extra transport hdr line parameter PROT_DEST = 0, //protocol framer destination parameter PROT_HDR = 1, //needs a protocol header? parameter ACK_SID = 0 //stream ID for packet ACK ) ( //clock and synchronous reset for all interfaces input clock, input reset, input clear, //current system time input [63:0] vita_time, //ready signal for multiple peripherals input perfs_ready, //input fifo36 interface control input [35:0] in_data, input in_valid, output in_ready, //output fifo36 interface status output [35:0] out_data, output out_valid, input out_ready, //32-bit settings bus outputs output strobe, output [7:0] addr, output [31:0] data, //16X 32-bit inputs for readback input [31:0] word00, input [31:0] word01, input [31:0] word02, input [31:0] word03, input [31:0] word04, input [31:0] word05, input [31:0] word06, input [31:0] word07, input [31:0] word08, input [31:0] word09, input [31:0] word10, input [31:0] word11, input [31:0] word12, input [31:0] word13, input [31:0] word14, input [31:0] word15, //debug output output [31:0] debug ); wire reading = in_valid && in_ready; wire writing = out_valid && out_ready; //------------------------------------------------------------------ //-- The command fifo: //-- Stores an individual register access command per line. //------------------------------------------------------------------ wire [63:0] in_command_ticks, out_command_ticks; wire [31:0] in_command_hdr, out_command_hdr; wire [31:0] in_command_data, out_command_data; wire in_command_has_time, out_command_has_time; wire command_fifo_full, command_fifo_empty; wire command_fifo_read, command_fifo_write; shortfifo #(.WIDTH(129)) command_fifo ( .clk(clock), .rst(reset), .clear(clear), .datain({in_command_ticks, in_command_hdr, in_command_data, in_command_has_time}), .dataout({out_command_ticks, out_command_hdr, out_command_data, out_command_has_time}), .write(command_fifo_write), .full(command_fifo_full), //input interface .empty(command_fifo_empty), .read(command_fifo_read) //output interface ); //------------------------------------------------------------------ //-- The result fifo: //-- Stores an individual result of a command per line. //------------------------------------------------------------------ wire [31:0] in_result_hdr, out_result_hdr; wire [31:0] in_result_data, out_result_data; wire result_fifo_full, result_fifo_empty; wire result_fifo_read, result_fifo_write; shortfifo #(.WIDTH(64)) result_fifo ( .clk(clock), .rst(reset), .clear(clear), .datain({in_result_hdr, in_result_data}), .dataout({out_result_hdr, out_result_data}), .write(result_fifo_write), .full(result_fifo_full), //input interface .empty(result_fifo_empty), .read(result_fifo_read) //output interface ); //------------------------------------------------------------------ //-- Input state machine: //-- Read input packet and fill a command fifo entry. //------------------------------------------------------------------ localparam READ_LINE0 = 0; localparam VITA_HDR = 1; localparam VITA_SID = 2; localparam VITA_CID0 = 3; localparam VITA_CID1 = 4; localparam VITA_TSI = 5; localparam VITA_TSF0 = 6; localparam VITA_TSF1 = 7; localparam READ_HDR = 8; localparam READ_DATA = 9; localparam WAIT_EOF = 10; localparam STORE_CMD = 11; localparam START_STATE = (XPORT_HDR)? READ_LINE0 : VITA_HDR; reg [4:0] in_state; //holdover from current read inputs reg [31:0] in_data_reg, in_hdr_reg; reg [63:0] in_ticks_reg; wire has_sid = in_data[28]; wire has_cid = in_data[27]; wire has_tsi = in_data[23:22] != 0; wire has_tsf = in_data[21:20] != 0; reg has_sid_reg, has_cid_reg, has_tsi_reg, has_tsf_reg; assign in_ready = (in_state < STORE_CMD); assign command_fifo_write = (in_state == STORE_CMD); assign in_command_ticks = in_ticks_reg; assign in_command_data = in_data_reg; assign in_command_hdr = in_hdr_reg; assign in_command_has_time = has_tsf_reg; always @(posedge clock) begin if (reset) begin in_state <= START_STATE; end else begin case (in_state) READ_LINE0: begin if (reading) in_state <= VITA_HDR; end VITA_HDR: begin if (reading) begin if (has_sid) in_state <= VITA_SID; else if (has_cid) in_state <= VITA_CID0; else if (has_tsi) in_state <= VITA_TSI; else if (has_tsf) in_state <= VITA_TSF0; else in_state <= READ_HDR; end has_sid_reg <= has_sid; has_cid_reg <= has_cid; has_tsi_reg <= has_tsi; has_tsf_reg <= has_tsf; end VITA_SID: begin if (reading) begin if (has_cid_reg) in_state <= VITA_CID0; else if (has_tsi_reg) in_state <= VITA_TSI; else if (has_tsf_reg) in_state <= VITA_TSF0; else in_state <= READ_HDR; end end VITA_CID0: begin if (reading) in_state <= VITA_CID1; end VITA_CID1: begin if (reading) begin if (has_tsi_reg) in_state <= VITA_TSI; else if (has_tsf_reg) in_state <= VITA_TSF0; else in_state <= READ_HDR; end end VITA_TSI: begin if (reading) begin if (has_tsf_reg) in_state <= VITA_TSF0; else in_state <= READ_HDR; end end VITA_TSF0: begin if (reading) in_state <= VITA_TSF1; in_ticks_reg[63:32] <= in_data; end VITA_TSF1: begin if (reading) in_state <= READ_HDR; in_ticks_reg[31:0] <= in_data; end READ_HDR: begin if (reading) in_state <= READ_DATA; in_hdr_reg <= in_data[31:0]; end READ_DATA: begin if (reading) in_state <= (in_data[33])? STORE_CMD : WAIT_EOF; in_data_reg <= in_data[31:0]; end WAIT_EOF: begin if (reading && in_data[33]) in_state <= STORE_CMD; end STORE_CMD: begin if (~command_fifo_full) in_state <= START_STATE; end endcase //in_state end end //------------------------------------------------------------------ //-- Command state machine: //-- Read a command fifo entry, act on it, produce result. //------------------------------------------------------------------ localparam LOAD_CMD = 0; localparam EVENT_CMD = 1; reg cmd_state; reg [31:0] rb_data; reg [63:0] command_ticks_reg; reg [31:0] command_hdr_reg; reg [31:0] command_data_reg; reg [63:0] vita_time_reg; always @(posedge clock) vita_time_reg <= vita_time; wire late; `ifndef FIFO_CTRL_NO_TIME time_compare time_compare( .time_now(vita_time_reg), .trigger_time(command_ticks_reg), .late(late)); `else assign late = 1; `endif //action occurs in the event state and when there is fifo space (should always be true) //the third condition is that all peripherals in the perfs signal are ready/active high //the fourth condition is that is an event time has been set, action is delayed until that time wire time_ready = (out_command_has_time)? late : 1; wire action = (cmd_state == EVENT_CMD) && ~result_fifo_full && perfs_ready && time_ready; assign command_fifo_read = action; assign result_fifo_write = action; assign in_result_hdr = command_hdr_reg; assign in_result_data = rb_data; always @(posedge clock) begin if (reset) begin cmd_state <= LOAD_CMD; end else begin case (cmd_state) LOAD_CMD: begin if (~command_fifo_empty) cmd_state <= EVENT_CMD; command_ticks_reg <= out_command_ticks; command_hdr_reg <= out_command_hdr; command_data_reg <= out_command_data; end EVENT_CMD: begin // poking and peeking happens here! if (action || clear) cmd_state <= LOAD_CMD; end endcase //cmd_state end end //------------------------------------------------------------------ //-- assign to settings bus interface //------------------------------------------------------------------ reg strobe_reg; assign strobe = strobe_reg; assign data = command_data_reg; assign addr = command_hdr_reg[7:0]; wire poke = command_hdr_reg[8]; always @(posedge clock) begin if (reset || clear) strobe_reg <= 0; else strobe_reg <= action && poke; end //------------------------------------------------------------------ //-- readback mux //------------------------------------------------------------------ always @(posedge clock) begin case (out_command_hdr[3:0]) 0 : rb_data <= word00; 1 : rb_data <= word01; 2 : rb_data <= word02; 3 : rb_data <= word03; 4 : rb_data <= word04; 5 : rb_data <= word05; 6 : rb_data <= word06; 7 : rb_data <= word07; 8 : rb_data <= word08; 9 : rb_data <= word09; 10: rb_data <= word10; 11: rb_data <= word11; 12: rb_data <= word12; 13: rb_data <= word13; 14: rb_data <= word14; 15: rb_data <= word15; endcase // case(addr_reg[3:0]) end //------------------------------------------------------------------ //-- Output state machine: //-- Read a command fifo entry, act on it, produce ack packet. //------------------------------------------------------------------ localparam WRITE_PROT_HDR = 0; localparam WRITE_VRT_HDR = 1; localparam WRITE_VRT_SID = 2; localparam WRITE_RB_HDR = 3; localparam WRITE_RB_DATA = 4; //the state for the start of packet condition localparam WRITE_PKT_HDR = (PROT_HDR)? WRITE_PROT_HDR : WRITE_VRT_HDR; reg [2:0] out_state; assign out_valid = ~result_fifo_empty; assign result_fifo_read = out_data[33] && writing; always @(posedge clock) begin if (reset) begin out_state <= WRITE_PKT_HDR; end else if (writing && out_data[33]) begin out_state <= WRITE_PKT_HDR; end else if (writing) begin out_state <= out_state + 1; end end //------------------------------------------------------------------ //-- assign to output fifo interface //------------------------------------------------------------------ wire [31:0] prot_hdr; assign prot_hdr[15:0] = 16; //bytes in proceeding vita packet assign prot_hdr[16] = 1; //yes frame assign prot_hdr[18:17] = PROT_DEST; assign prot_hdr[31:19] = 0; //nothing reg [31:0] out_data_int; always @* begin case (out_state) WRITE_PROT_HDR: out_data_int <= prot_hdr; WRITE_VRT_HDR: out_data_int <= {12'b010100000000, out_result_hdr[19:16], 2'b0, prot_hdr[15:2]}; WRITE_VRT_SID: out_data_int <= ACK_SID; WRITE_RB_HDR: out_data_int <= out_result_hdr; WRITE_RB_DATA: out_data_int <= out_result_data; default: out_data_int <= 0; endcase //state end assign out_data[35:34] = 2'b0; assign out_data[33] = (out_state == WRITE_RB_DATA); assign out_data[32] = (out_state == WRITE_PKT_HDR); assign out_data[31:0] = out_data_int; //------------------------------------------------------------------ //-- debug outputs //------------------------------------------------------------------ assign debug = { in_state, out_state, //8 in_valid, in_ready, in_data[33:32], //4 out_valid, out_ready, out_data[33:32], //4 command_fifo_empty, command_fifo_full, //2 command_fifo_read, command_fifo_write, //2 addr, //8 strobe_reg, strobe, poke, out_command_has_time //4 }; endmodule //settings_fifo_ctrl