1// 2// Copyright 2012 Ettus Research LLC 3// 4// This program is free software: you can redistribute it and/or modify 5// it under the terms of the GNU General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// This program is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU General Public License for more details. 13// 14// You should have received a copy of the GNU General Public License 15// along with this program. If not, see <http://www.gnu.org/licenses/>. 16// 17 18// A settings and readback bus controlled via fifo36 interface 19 20module settings_fifo_ctrl 21 #( 22 parameter XPORT_HDR = 1, //extra transport hdr line 23 parameter PROT_DEST = 0, //protocol framer destination 24 parameter PROT_HDR = 1, //needs a protocol header? 25 parameter ACK_SID = 0 //stream ID for packet ACK 26 ) 27 ( 28 //clock and synchronous reset for all interfaces 29 input clock, input reset, input clear, 30 31 //current system time 32 input [63:0] vita_time, 33 34 //ready signal for multiple peripherals 35 input perfs_ready, 36 37 //input fifo36 interface control 38 input [35:0] in_data, input in_valid, output in_ready, 39 40 //output fifo36 interface status 41 output [35:0] out_data, output out_valid, input out_ready, 42 43 //32-bit settings bus outputs 44 output strobe, output [7:0] addr, output [31:0] data, 45 46 //16X 32-bit inputs for readback 47 input [31:0] word00, 48 input [31:0] word01, 49 input [31:0] word02, 50 input [31:0] word03, 51 input [31:0] word04, 52 input [31:0] word05, 53 input [31:0] word06, 54 input [31:0] word07, 55 input [31:0] word08, 56 input [31:0] word09, 57 input [31:0] word10, 58 input [31:0] word11, 59 input [31:0] word12, 60 input [31:0] word13, 61 input [31:0] word14, 62 input [31:0] word15, 63 64 //debug output 65 output [31:0] debug 66 ); 67 68 wire reading = in_valid && in_ready; 69 wire writing = out_valid && out_ready; 70 71 //------------------------------------------------------------------ 72 //-- The command fifo: 73 //-- Stores an individual register access command per line. 74 //------------------------------------------------------------------ 75 wire [63:0] in_command_ticks, out_command_ticks; 76 wire [31:0] in_command_hdr, out_command_hdr; 77 wire [31:0] in_command_data, out_command_data; 78 wire in_command_has_time, out_command_has_time; 79 wire command_fifo_full, command_fifo_empty; 80 wire command_fifo_read, command_fifo_write; 81 82 wire [128:0] fifo2_datain, fifo3_datain, fifo4_datain; 83 wire fifo1_empty, fifo2_empty, fifo3_empty; 84 wire fifo2_full, fifo3_full, fifo4_full; 85 wire fifo1_to_fifo2, fifo2_to_fifo3, fifo3_to_fifo4; 86 87 shortfifo #(.WIDTH(129)) command_fifo ( 88 .clk(clock), .rst(reset), .clear(clear), 89 .datain({in_command_ticks, in_command_hdr, in_command_data, in_command_has_time}), 90 .dataout(fifo2_datain), 91 .write(command_fifo_write), .full(command_fifo_full), //input interface 92 .empty(fifo1_empty), .read(fifo1_to_fifo2) //output interface 93 ); 94 95 shortfifo #(.WIDTH(129)) command_fifo2 ( 96 .clk(clock), .rst(reset), .clear(clear), 97 .datain(fifo2_datain), 98 .dataout(fifo3_datain), 99 .write(fifo1_to_fifo2), .full(fifo2_full), //input interface 100 .empty(fifo2_empty), .read(fifo2_to_fifo3) //output interface 101 ); 102 103 shortfifo #(.WIDTH(129)) command_fifo3 ( 104 .clk(clock), .rst(reset), .clear(clear), 105 .datain(fifo3_datain), 106 .dataout(fifo4_datain), 107 .write(fifo2_to_fifo3), .full(fifo3_full), //input interface 108 .empty(fifo3_empty), .read(fifo3_to_fifo4) //output interface 109 ); 110 111 shortfifo #(.WIDTH(129)) command_fifo4 ( 112 .clk(clock), .rst(reset), .clear(clear), 113 .datain(fifo4_datain), 114 .dataout({out_command_ticks, out_command_hdr, out_command_data, out_command_has_time}), 115 .write(fifo3_to_fifo4), .full(fifo4_full), //input interface 116 .empty(command_fifo_empty), .read(command_fifo_read) //output interface 117 ); 118 119 assign fifo1_to_fifo2 = ~fifo2_full & ~fifo1_empty; 120 assign fifo2_to_fifo3 = ~fifo3_full & ~fifo2_empty; 121 assign fifo3_to_fifo4 = ~fifo4_full & ~fifo3_empty; 122 123 //------------------------------------------------------------------ 124 //-- The result fifo: 125 //-- Stores an individual result of a command per line. 126 //------------------------------------------------------------------ 127 wire [31:0] in_result_hdr, out_result_hdr; 128 wire [31:0] in_result_data, out_result_data; 129 wire result_fifo_full, result_fifo_empty; 130 wire result_fifo_read, result_fifo_write; 131 132 shortfifo #(.WIDTH(64)) result_fifo ( 133 .clk(clock), .rst(reset), .clear(clear), 134 .datain({in_result_hdr, in_result_data}), 135 .dataout({out_result_hdr, out_result_data}), 136 .write(result_fifo_write), .full(result_fifo_full), //input interface 137 .empty(result_fifo_empty), .read(result_fifo_read) //output interface 138 ); 139 140 //------------------------------------------------------------------ 141 //-- Input state machine: 142 //-- Read input packet and fill a command fifo entry. 143 //------------------------------------------------------------------ 144 localparam READ_LINE0 = 0; 145 localparam VITA_HDR = 1; 146 localparam VITA_SID = 2; 147 localparam VITA_CID0 = 3; 148 localparam VITA_CID1 = 4; 149 localparam VITA_TSI = 5; 150 localparam VITA_TSF0 = 6; 151 localparam VITA_TSF1 = 7; 152 localparam READ_HDR = 8; 153 localparam READ_DATA = 9; 154 localparam WAIT_EOF = 10; 155 localparam STORE_CMD = 11; 156 157 localparam START_STATE = (XPORT_HDR)? READ_LINE0 : VITA_HDR; 158 159 reg [4:0] in_state; 160 161 //holdover from current read inputs 162 reg [31:0] in_data_reg, in_hdr_reg; 163 reg [63:0] in_ticks_reg; 164 wire has_sid = in_data[28]; 165 wire has_cid = in_data[27]; 166 wire has_tsi = in_data[23:22] != 0; 167 wire has_tsf = in_data[21:20] != 0; 168 reg has_sid_reg, has_cid_reg, has_tsi_reg, has_tsf_reg; 169 170 assign in_ready = (in_state < STORE_CMD); 171 assign command_fifo_write = (in_state == STORE_CMD); 172 assign in_command_ticks = in_ticks_reg; 173 assign in_command_data = in_data_reg; 174 assign in_command_hdr = in_hdr_reg; 175 assign in_command_has_time = has_tsf_reg; 176 177 always @(posedge clock) begin 178 if (reset) begin 179 in_state <= START_STATE; 180 end 181 else begin 182 case (in_state) 183 184 READ_LINE0: begin 185 if (reading) in_state <= VITA_HDR; 186 end 187 188 VITA_HDR: begin 189 if (reading) begin 190 if (has_sid) in_state <= VITA_SID; 191 else if (has_cid) in_state <= VITA_CID0; 192 else if (has_tsi) in_state <= VITA_TSI; 193 else if (has_tsf) in_state <= VITA_TSF0; 194 else in_state <= READ_HDR; 195 end 196 has_sid_reg <= has_sid; 197 has_cid_reg <= has_cid; 198 has_tsi_reg <= has_tsi; 199 has_tsf_reg <= has_tsf; 200 end 201 202 VITA_SID: begin 203 if (reading) begin 204 if (has_cid_reg) in_state <= VITA_CID0; 205 else if (has_tsi_reg) in_state <= VITA_TSI; 206 else if (has_tsf_reg) in_state <= VITA_TSF0; 207 else in_state <= READ_HDR; 208 end 209 end 210 211 VITA_CID0: begin 212 if (reading) in_state <= VITA_CID1; 213 end 214 215 VITA_CID1: begin 216 if (reading) begin 217 if (has_tsi_reg) in_state <= VITA_TSI; 218 else if (has_tsf_reg) in_state <= VITA_TSF0; 219 else in_state <= READ_HDR; 220 end 221 end 222 223 VITA_TSI: begin 224 if (reading) begin 225 if (has_tsf_reg) in_state <= VITA_TSF0; 226 else in_state <= READ_HDR; 227 end 228 end 229 230 VITA_TSF0: begin 231 if (reading) in_state <= VITA_TSF1; 232 in_ticks_reg[63:32] <= in_data; 233 end 234 235 VITA_TSF1: begin 236 if (reading) in_state <= READ_HDR; 237 in_ticks_reg[31:0] <= in_data; 238 end 239 240 READ_HDR: begin 241 if (reading) in_state <= READ_DATA; 242 in_hdr_reg <= in_data[31:0]; 243 end 244 245 READ_DATA: begin 246 if (reading) in_state <= (in_data[33])? STORE_CMD : WAIT_EOF; 247 in_data_reg <= in_data[31:0]; 248 end 249 250 WAIT_EOF: begin 251 if (reading && in_data[33]) in_state <= STORE_CMD; 252 end 253 254 STORE_CMD: begin 255 if (~command_fifo_full) in_state <= START_STATE; 256 end 257 258 endcase //in_state 259 end 260 end 261 262 //------------------------------------------------------------------ 263 //-- Command state machine: 264 //-- Read a command fifo entry, act on it, produce result. 265 //------------------------------------------------------------------ 266 localparam LOAD_CMD = 0; 267 localparam EVENT_CMD = 1; 268 269 reg cmd_state; 270 reg [31:0] rb_data; 271 272 reg [63:0] command_ticks_reg; 273 reg [31:0] command_hdr_reg; 274 reg [31:0] command_data_reg; 275 276 reg [63:0] vita_time_reg; 277 always @(posedge clock) 278 vita_time_reg <= vita_time; 279 280 wire late; 281 `ifndef FIFO_CTRL_NO_TIME 282 time_compare time_compare( 283 .time_now(vita_time_reg), .trigger_time(command_ticks_reg), .late(late)); 284 `else 285 assign late = 1; 286 `endif 287 288 //action occurs in the event state and when there is fifo space (should always be true) 289 //the third condition is that all peripherals in the perfs signal are ready/active high 290 //the fourth condition is that is an event time has been set, action is delayed until that time 291 wire time_ready = (out_command_has_time)? late : 1; 292 wire action = (cmd_state == EVENT_CMD) && ~result_fifo_full && perfs_ready && time_ready; 293 294 assign command_fifo_read = action; 295 assign result_fifo_write = action; 296 assign in_result_hdr = command_hdr_reg; 297 assign in_result_data = rb_data; 298 299 always @(posedge clock) begin 300 if (reset) begin 301 cmd_state <= LOAD_CMD; 302 end 303 else begin 304 case (cmd_state) 305 306 LOAD_CMD: begin 307 if (~command_fifo_empty) cmd_state <= EVENT_CMD; 308 command_ticks_reg <= out_command_ticks; 309 command_hdr_reg <= out_command_hdr; 310 command_data_reg <= out_command_data; 311 end 312 313 EVENT_CMD: begin // poking and peeking happens here! 314 if (action || clear) cmd_state <= LOAD_CMD; 315 end 316 317 endcase //cmd_state 318 end 319 end 320 321 //------------------------------------------------------------------ 322 //-- assign to settings bus interface 323 //------------------------------------------------------------------ 324 reg strobe_reg; 325 assign strobe = strobe_reg; 326 assign data = command_data_reg; 327 assign addr = command_hdr_reg[7:0]; 328 wire poke = command_hdr_reg[8]; 329 330 always @(posedge clock) begin 331 if (reset || clear) strobe_reg <= 0; 332 else strobe_reg <= action && poke; 333 end 334 335 //------------------------------------------------------------------ 336 //-- readback mux 337 //------------------------------------------------------------------ 338 always @(posedge clock) begin 339 case (out_command_hdr[3:0]) 340 0 : rb_data <= word00; 341 1 : rb_data <= word01; 342 2 : rb_data <= word02; 343 3 : rb_data <= word03; 344 4 : rb_data <= word04; 345 5 : rb_data <= word05; 346 6 : rb_data <= word06; 347 7 : rb_data <= word07; 348 8 : rb_data <= word08; 349 9 : rb_data <= word09; 350 10: rb_data <= word10; 351 11: rb_data <= word11; 352 12: rb_data <= word12; 353 13: rb_data <= word13; 354 14: rb_data <= word14; 355 15: rb_data <= word15; 356 endcase // case(addr_reg[3:0]) 357 end 358 359 //------------------------------------------------------------------ 360 //-- Output state machine: 361 //-- Read a command fifo entry, act on it, produce ack packet. 362 //------------------------------------------------------------------ 363 localparam WRITE_PROT_HDR = 0; 364 localparam WRITE_VRT_HDR = 1; 365 localparam WRITE_VRT_SID = 2; 366 localparam WRITE_RB_HDR = 3; 367 localparam WRITE_RB_DATA = 4; 368 369 //the state for the start of packet condition 370 localparam WRITE_PKT_HDR = (PROT_HDR)? WRITE_PROT_HDR : WRITE_VRT_HDR; 371 372 reg [2:0] out_state; 373 374 assign out_valid = ~result_fifo_empty; 375 assign result_fifo_read = out_data[33] && writing; 376 377 always @(posedge clock) begin 378 if (reset) begin 379 out_state <= WRITE_PKT_HDR; 380 end 381 else if (writing && out_data[33]) begin 382 out_state <= WRITE_PKT_HDR; 383 end 384 else if (writing) begin 385 out_state <= out_state + 1; 386 end 387 end 388 389 //------------------------------------------------------------------ 390 //-- assign to output fifo interface 391 //------------------------------------------------------------------ 392 wire [31:0] prot_hdr; 393 assign prot_hdr[15:0] = 16; //bytes in proceeding vita packet 394 assign prot_hdr[16] = 1; //yes frame 395 assign prot_hdr[18:17] = PROT_DEST; 396 assign prot_hdr[31:19] = 0; //nothing 397 398 reg [31:0] out_data_int; 399 always @* begin 400 case (out_state) 401 WRITE_PROT_HDR: out_data_int <= prot_hdr; 402 WRITE_VRT_HDR: out_data_int <= {12'b010100000000, out_result_hdr[19:16], 2'b0, prot_hdr[15:2]}; 403 WRITE_VRT_SID: out_data_int <= ACK_SID; 404 WRITE_RB_HDR: out_data_int <= out_result_hdr; 405 WRITE_RB_DATA: out_data_int <= out_result_data; 406 default: out_data_int <= 0; 407 endcase //state 408 end 409 410 assign out_data[35:34] = 2'b0; 411 assign out_data[33] = (out_state == WRITE_RB_DATA); 412 assign out_data[32] = (out_state == WRITE_PKT_HDR); 413 assign out_data[31:0] = out_data_int; 414 415 //------------------------------------------------------------------ 416 //-- debug outputs 417 //------------------------------------------------------------------ 418 assign debug = { 419 in_state, out_state, //8 420 in_valid, in_ready, in_data[33:32], //4 421 out_valid, out_ready, out_data[33:32], //4 422 command_fifo_empty, command_fifo_full, //2 423 command_fifo_read, command_fifo_write, //2 424 addr, //8 425 strobe_reg, strobe, poke, out_command_has_time //4 426 }; 427 428endmodule //settings_fifo_ctrl 429