usb_data_interface.v
1 module usb_data_interface ( 2 input wire clk, // Main clock (100MHz recommended) 3 input wire reset_n, 4 input wire ft601_reset_n, // FT601-domain synchronized reset 5 6 // Radar data inputs 7 input wire [31:0] range_profile, 8 input wire range_valid, 9 input wire [15:0] doppler_real, 10 input wire [15:0] doppler_imag, 11 input wire doppler_valid, 12 input wire cfar_detection, 13 input wire cfar_valid, 14 15 // FT601 Interface (Slave FIFO mode) 16 // Data bus 17 inout wire [31:0] ft601_data, // 32-bit bidirectional data bus 18 output reg [3:0] ft601_be, // Byte enable (4 lanes for 32-bit mode) 19 20 // Control signals 21 output reg ft601_txe_n, // Transmit enable (active low) 22 output reg ft601_rxf_n, // Receive enable (active low) 23 input wire ft601_txe, // Transmit FIFO empty 24 input wire ft601_rxf, // Receive FIFO full 25 output reg ft601_wr_n, // Write strobe (active low) 26 output reg ft601_rd_n, // Read strobe (active low) 27 output reg ft601_oe_n, // Output enable (active low) 28 output reg ft601_siwu_n, // Send immediate / Wakeup 29 30 // FIFO flags 31 input wire [1:0] ft601_srb, // Selected read buffer 32 input wire [1:0] ft601_swb, // Selected write buffer 33 34 // Clock 35 output wire ft601_clk_out, // Output clock to FT601 (forwarded via ODDR) 36 input wire ft601_clk_in, // Clock from FT601 (60/100MHz) 37 38 // ========== HOST COMMAND OUTPUTS (Gap 4: USB Read Path) ========== 39 // These outputs are registered in the ft601_clk domain and must be 40 // CDC-synchronized by the consumer (radar_system_top.v) before use 41 // in the clk_100m domain. 42 // 43 // Command word format: {opcode[7:0], addr[7:0], value[15:0]} 44 // 0x01 = Set radar mode (value[1:0] -> mode_controller mode) 45 // 0x02 = Single chirp trigger (value ignored, pulse cmd_valid) 46 // 0x03 = Set CFAR threshold (value[15:0] -> threshold) 47 // 0x04 = Set stream control (value[2:0] -> enable range/doppler/cfar) 48 // 0x10-0x15 = Chirp timing configuration (Gap 2) 49 // 0xFF = Status request (triggers status response packet) 50 output reg [31:0] cmd_data, // Last received command word 51 output reg cmd_valid, // Pulse: new command received (ft601_clk domain) 52 output reg [7:0] cmd_opcode, // Decoded opcode for convenience 53 output reg [7:0] cmd_addr, // Decoded register address 54 output reg [15:0] cmd_value, // Decoded value 55 56 // Gap 2: Stream control input (clk_100m domain, CDC'd internally) 57 // Bit 0 = range stream enable 58 // Bit 1 = doppler stream enable 59 // Bit 2 = cfar/detection stream enable 60 input wire [2:0] stream_control, 61 62 // Gap 2: Status readback inputs (clk_100m domain, CDC'd internally) 63 // When status_request pulses, the write FSM sends a status response 64 // packet containing the current register values. 65 input wire status_request, // 1-cycle pulse in clk_100m when 0xFF received 66 input wire [15:0] status_cfar_threshold, // Current CFAR threshold 67 input wire [2:0] status_stream_ctrl, // Current stream control 68 input wire [1:0] status_radar_mode, // Current radar mode 69 input wire [15:0] status_long_chirp, // Current long chirp cycles 70 input wire [15:0] status_long_listen, // Current long listen cycles 71 input wire [15:0] status_guard, // Current guard cycles 72 input wire [15:0] status_short_chirp, // Current short chirp cycles 73 input wire [15:0] status_short_listen, // Current short listen cycles 74 input wire [5:0] status_chirps_per_elev, // Current chirps per elevation 75 input wire [1:0] status_range_mode, // Fix 7: Current range mode (0x20) 76 77 // Self-test status readback (opcode 0x31 / included in 0xFF status packet) 78 input wire [4:0] status_self_test_flags, // Per-test PASS(1)/FAIL(0) latched 79 input wire [7:0] status_self_test_detail, // Diagnostic detail byte latched 80 input wire status_self_test_busy // Self-test FSM still running 81 ); 82 83 // USB packet structure (same as before) 84 localparam HEADER = 8'hAA; 85 localparam FOOTER = 8'h55; 86 87 // FT601 configuration 88 localparam FT601_DATA_WIDTH = 32; 89 localparam FT601_BURST_SIZE = 512; // Max burst size in bytes 90 91 // ============================================================================ 92 // WRITE FSM State definitions (Verilog-2001 compatible) 93 // ============================================================================ 94 localparam [2:0] IDLE = 3'd0, 95 SEND_HEADER = 3'd1, 96 SEND_RANGE_DATA = 3'd2, 97 SEND_DOPPLER_DATA = 3'd3, 98 SEND_DETECTION_DATA = 3'd4, 99 SEND_FOOTER = 3'd5, 100 WAIT_ACK = 3'd6, 101 SEND_STATUS = 3'd7; // Gap 2: status readback 102 103 reg [2:0] current_state; 104 reg [7:0] byte_counter; 105 reg [31:0] data_buffer; 106 reg [31:0] ft601_data_out; 107 reg ft601_data_oe; // Output enable for bidirectional data bus 108 109 // ============================================================================ 110 // READ FSM State definitions (Gap 4: USB Read Path) 111 // ============================================================================ 112 // FT601 245 synchronous FIFO read protocol: 113 // 1. Host has data available: RXF_N = 0 (active low) 114 // 2. FPGA asserts OE_N = 0 (bus turnaround: FT601 starts driving data bus) 115 // 3. Wait 1 cycle for bus turnaround settling 116 // 4. FPGA asserts RD_N = 0 (start reading: data valid on each posedge) 117 // 5. Sample ft601_data[31:0] while RD_N = 0 and RXF_N = 0 118 // 6. Deassert RD_N = 1, then OE_N = 1 119 // 120 // The read FSM only activates when the write FSM is IDLE and RXF indicates 121 // data is available. This prevents bus contention between TX and RX. 122 localparam [2:0] RD_IDLE = 3'd0, // Waiting for RXF 123 RD_OE_ASSERT = 3'd1, // Assert OE_N=0, wait turnaround 124 RD_READING = 3'd2, // Assert RD_N=0, sample data 125 RD_DEASSERT = 3'd3, // Deassert RD_N, then OE_N 126 RD_PROCESS = 3'd4; // Process received command word 127 128 reg [2:0] read_state; 129 reg [31:0] rx_data_captured; // Data word read from host 130 131 // ========== CDC INPUT SYNCHRONIZERS (clk domain -> ft601_clk_in domain) ========== 132 // The valid signals arrive from clk_100m but the state machine runs on ft601_clk_in. 133 // Even though both are 100 MHz, they are asynchronous clocks and need synchronization. 134 135 // 2-stage synchronizers for valid signals 136 (* ASYNC_REG = "TRUE" *) reg [1:0] range_valid_sync; 137 (* ASYNC_REG = "TRUE" *) reg [1:0] doppler_valid_sync; 138 (* ASYNC_REG = "TRUE" *) reg [1:0] cfar_valid_sync; 139 140 // Delayed versions of sync[1] for proper edge detection 141 reg range_valid_sync_d; 142 reg doppler_valid_sync_d; 143 reg cfar_valid_sync_d; 144 145 // Holding registers: data captured in SOURCE domain (clk_100m) when valid 146 // asserts, then read by ft601 domain after synchronized valid edge. 147 // This is safe because the data is stable for the entire time the valid 148 // pulse is being synchronized (2+ ft601_clk cycles). 149 reg [31:0] range_profile_hold; 150 reg [15:0] doppler_real_hold; 151 reg [15:0] doppler_imag_hold; 152 reg cfar_detection_hold; 153 154 // Gap 2: Status request toggle register (clk_100m domain). 155 // Declared here (before the always block) to satisfy iverilog forward-ref rules. 156 reg status_req_toggle_100m; 157 158 // Source-domain holding registers (clk domain) 159 always @(posedge clk or negedge reset_n) begin 160 if (!reset_n) begin 161 range_profile_hold <= 32'd0; 162 doppler_real_hold <= 16'd0; 163 doppler_imag_hold <= 16'd0; 164 cfar_detection_hold <= 1'b0; 165 status_req_toggle_100m <= 1'b0; 166 end else begin 167 if (range_valid) 168 range_profile_hold <= range_profile; 169 if (doppler_valid) begin 170 doppler_real_hold <= doppler_real; 171 doppler_imag_hold <= doppler_imag; 172 end 173 if (cfar_valid) 174 cfar_detection_hold <= cfar_detection; 175 // Gap 2: Toggle on status request pulse (CDC to ft601_clk) 176 if (status_request) 177 status_req_toggle_100m <= ~status_req_toggle_100m; 178 end 179 end 180 181 // FT601-domain captured data (sampled from holding regs on sync'd edge) 182 reg [31:0] range_profile_cap; 183 reg [15:0] doppler_real_cap; 184 reg [15:0] doppler_imag_cap; 185 reg cfar_detection_cap; 186 187 // Data-pending flags (ft601_clk domain). 188 // Set when a valid edge is detected, cleared when the write FSM consumes 189 // or skips the data. Prevents the write FSM from blocking forever when 190 // a stream's valid hasn't fired yet (e.g., Doppler needs 32 chirps). 191 reg doppler_data_pending; 192 reg cfar_data_pending; 193 194 // Gap 2: CDC for stream_control (clk_100m -> ft601_clk_in) 195 // stream_control changes infrequently (only on host USB command), so 196 // per-bit 2-stage synchronizers are sufficient. No Gray coding needed 197 // because the bits are independent enables. 198 // Fix #5: Default to range-only (3'b001) on reset to prevent write FSM 199 // deadlock before host configures streams. With all streams enabled on 200 // reset, the first range_valid triggers the write FSM which then blocks 201 // forever on SEND_DOPPLER_DATA (Doppler hasn't produced data yet). 202 (* ASYNC_REG = "TRUE" *) reg [2:0] stream_ctrl_sync_0; 203 (* ASYNC_REG = "TRUE" *) reg [2:0] stream_ctrl_sync_1; 204 wire stream_range_en = stream_ctrl_sync_1[0]; 205 wire stream_doppler_en = stream_ctrl_sync_1[1]; 206 wire stream_cfar_en = stream_ctrl_sync_1[2]; 207 208 // Gap 2: Status request CDC (toggle CDC, same pattern as cmd_valid) 209 // status_request is a 1-cycle pulse in clk_100m. Toggle→sync→edge-detect. 210 // NOTE: status_req_toggle_100m declared above (before source-domain always block) 211 (* ASYNC_REG = "TRUE" *) reg [1:0] status_req_sync; 212 reg status_req_sync_prev; 213 wire status_req_ft601 = status_req_sync[1] ^ status_req_sync_prev; 214 215 // Status snapshot: captured in ft601_clk domain when status request arrives. 216 // The clk_100m-domain status inputs are stable for many cycles after the 217 // command decode, so sampling them a few ft601_clk cycles later is safe. 218 reg [31:0] status_words [0:5]; // 6 status words (word 5 = self-test) 219 reg [2:0] status_word_idx; 220 221 wire range_valid_ft; 222 wire doppler_valid_ft; 223 wire cfar_valid_ft; 224 225 always @(posedge ft601_clk_in or negedge ft601_reset_n) begin 226 if (!ft601_reset_n) begin 227 range_valid_sync <= 2'b00; 228 doppler_valid_sync <= 2'b00; 229 cfar_valid_sync <= 2'b00; 230 range_valid_sync_d <= 1'b0; 231 doppler_valid_sync_d <= 1'b0; 232 cfar_valid_sync_d <= 1'b0; 233 range_profile_cap <= 32'd0; 234 doppler_real_cap <= 16'd0; 235 doppler_imag_cap <= 16'd0; 236 cfar_detection_cap <= 1'b0; 237 // Fix #5: Default to range-only on reset (prevents write FSM deadlock) 238 stream_ctrl_sync_0 <= 3'b001; 239 stream_ctrl_sync_1 <= 3'b001; 240 // Gap 2: status request CDC reset 241 status_req_sync <= 2'b00; 242 status_req_sync_prev <= 1'b0; 243 status_word_idx <= 3'd0; 244 end else begin 245 // Synchronize valid strobes (2-stage sync chain) 246 range_valid_sync <= {range_valid_sync[0], range_valid}; 247 doppler_valid_sync <= {doppler_valid_sync[0], doppler_valid}; 248 cfar_valid_sync <= {cfar_valid_sync[0], cfar_valid}; 249 250 // Gap 2: stream control CDC (2-stage) 251 stream_ctrl_sync_0 <= stream_control; 252 stream_ctrl_sync_1 <= stream_ctrl_sync_0; 253 254 // Gap 2: status request CDC (toggle sync + edge detect) 255 status_req_sync <= {status_req_sync[0], status_req_toggle_100m}; 256 status_req_sync_prev <= status_req_sync[1]; 257 258 // Gap 2: Capture status snapshot when request arrives in ft601 domain 259 if (status_req_ft601) begin 260 // Pack register values into 5x 32-bit status words 261 // Word 0: {0xFF, mode[1:0], stream_ctrl[2:0], cfar_threshold[15:0]} 262 status_words[0] <= {8'hFF, 3'b000, status_radar_mode, 263 5'b00000, status_stream_ctrl, 264 status_cfar_threshold}; 265 // Word 1: {long_chirp_cycles[15:0], long_listen_cycles[15:0]} 266 status_words[1] <= {status_long_chirp, status_long_listen}; 267 // Word 2: {guard_cycles[15:0], short_chirp_cycles[15:0]} 268 status_words[2] <= {status_guard, status_short_chirp}; 269 // Word 3: {short_listen_cycles[15:0], chirps_per_elev[5:0], 10'b0} 270 status_words[3] <= {status_short_listen, 10'd0, status_chirps_per_elev}; 271 // Word 4: Fix 7 — range_mode in bits [1:0], rest reserved 272 status_words[4] <= {30'd0, status_range_mode}; 273 // Word 5: Self-test results {reserved[6:0], busy, reserved[7:0], detail[7:0], reserved[2:0], flags[4:0]} 274 status_words[5] <= {7'd0, status_self_test_busy, 275 8'd0, status_self_test_detail, 276 3'd0, status_self_test_flags}; 277 end 278 279 // Delayed version of sync[1] for edge detection 280 range_valid_sync_d <= range_valid_sync[1]; 281 doppler_valid_sync_d <= doppler_valid_sync[1]; 282 cfar_valid_sync_d <= cfar_valid_sync[1]; 283 284 // Capture data on rising edge of FULLY SYNCHRONIZED valid (sync[1]) 285 // Data in holding regs is stable by the time sync[1] rises (2+ cycles) 286 if (range_valid_sync[1] && !range_valid_sync_d) 287 range_profile_cap <= range_profile_hold; 288 if (doppler_valid_sync[1] && !doppler_valid_sync_d) begin 289 doppler_real_cap <= doppler_real_hold; 290 doppler_imag_cap <= doppler_imag_hold; 291 end 292 if (cfar_valid_sync[1] && !cfar_valid_sync_d) begin 293 cfar_detection_cap <= cfar_detection_hold; 294 end 295 end 296 end 297 298 // Rising-edge detect on FULLY SYNCHRONIZED valid (sync[1], not sync[0]) 299 // This provides full 2-stage metastability protection before use. 300 assign range_valid_ft = range_valid_sync[1] && !range_valid_sync_d; 301 assign doppler_valid_ft = doppler_valid_sync[1] && !doppler_valid_sync_d; 302 assign cfar_valid_ft = cfar_valid_sync[1] && !cfar_valid_sync_d; 303 304 // FT601 data bus direction control 305 assign ft601_data = ft601_data_oe ? ft601_data_out : 32'hzzzz_zzzz; 306 307 always @(posedge ft601_clk_in or negedge ft601_reset_n) begin 308 if (!ft601_reset_n) begin 309 current_state <= IDLE; 310 read_state <= RD_IDLE; 311 byte_counter <= 0; 312 ft601_data_out <= 0; 313 ft601_data_oe <= 0; 314 ft601_be <= 4'b1111; // All bytes enabled for 32-bit mode 315 ft601_txe_n <= 1; 316 ft601_rxf_n <= 1; 317 ft601_wr_n <= 1; 318 ft601_rd_n <= 1; 319 ft601_oe_n <= 1; 320 ft601_siwu_n <= 1; 321 rx_data_captured <= 32'd0; 322 cmd_data <= 32'd0; 323 cmd_valid <= 1'b0; 324 cmd_opcode <= 8'd0; 325 cmd_addr <= 8'd0; 326 cmd_value <= 16'd0; 327 doppler_data_pending <= 1'b0; 328 cfar_data_pending <= 1'b0; 329 // NOTE: ft601_clk_out is driven by the clk-domain always block below. 330 // Do NOT assign it here (ft601_clk_in domain) — causes multi-driven net. 331 end else begin 332 // Default: clear one-shot signals 333 cmd_valid <= 1'b0; 334 335 // Data-pending flag management: set on valid edge, cleared when 336 // consumed or skipped by write FSM. Must be in this always block 337 // (not the CDC sync block) to avoid Vivado multiple-driver DRC error. 338 if (doppler_valid_ft) 339 doppler_data_pending <= 1'b1; 340 if (cfar_valid_ft) 341 cfar_data_pending <= 1'b1; 342 343 // ================================================================ 344 // READ FSM — host-to-FPGA command path (Gap 4) 345 // 346 // The read FSM takes priority over write when both could activate. 347 // It only starts when the write FSM is IDLE and ft601_rxf 348 // indicates data from host is available. 349 // ================================================================ 350 case (read_state) 351 RD_IDLE: begin 352 // Only start reading if write FSM is idle and host has data. 353 // ft601_rxf active-low: 0 means data available from host. 354 if (current_state == IDLE && !ft601_rxf) begin 355 ft601_oe_n <= 1'b0; // Assert OE: tell FT601 to drive bus 356 ft601_data_oe <= 1'b0; // FPGA releases bus (FT601 drives) 357 read_state <= RD_OE_ASSERT; 358 end 359 end 360 361 RD_OE_ASSERT: begin 362 // 1-cycle turnaround: OE_N asserted, bus settling. 363 // FT601 spec requires 1 clock of OE_N before RD_N assertion. 364 if (!ft601_rxf) begin 365 ft601_rd_n <= 1'b0; // Assert RD: start reading 366 read_state <= RD_READING; 367 end else begin 368 // Host withdrew data — abort 369 ft601_oe_n <= 1'b1; 370 read_state <= RD_IDLE; 371 end 372 end 373 374 RD_READING: begin 375 // Data is valid on ft601_data. Sample it. 376 // For now we read a single 32-bit command word per transaction. 377 rx_data_captured <= ft601_data; 378 ft601_rd_n <= 1'b1; // Deassert RD 379 read_state <= RD_DEASSERT; 380 end 381 382 RD_DEASSERT: begin 383 // Deassert OE_N (1 cycle after RD_N deasserted) 384 ft601_oe_n <= 1'b1; 385 read_state <= RD_PROCESS; 386 end 387 388 RD_PROCESS: begin 389 // Decode the received command word and pulse cmd_valid. 390 // Format: {opcode[31:24], addr[23:16], value[15:0]} 391 cmd_data <= rx_data_captured; 392 cmd_opcode <= rx_data_captured[31:24]; 393 cmd_addr <= rx_data_captured[23:16]; 394 cmd_value <= rx_data_captured[15:0]; 395 cmd_valid <= 1'b1; 396 read_state <= RD_IDLE; 397 end 398 399 default: read_state <= RD_IDLE; 400 endcase 401 402 // ================================================================ 403 // WRITE FSM — FPGA-to-host data streaming (existing) 404 // 405 // Only operates when read FSM is idle (no bus contention). 406 // ================================================================ 407 if (read_state == RD_IDLE) begin 408 case (current_state) 409 IDLE: begin 410 ft601_wr_n <= 1; 411 ft601_data_oe <= 0; // Release data bus 412 // Gap 2: Status readback takes priority 413 if (status_req_ft601 && ft601_rxf) begin 414 current_state <= SEND_STATUS; 415 status_word_idx <= 3'd0; 416 end 417 // Trigger write FSM on range_valid edge (primary data source). 418 // Doppler/cfar data_pending flags are checked inside 419 // SEND_DOPPLER_DATA and SEND_DETECTION_DATA to skip or send. 420 // Do NOT trigger on pending flags alone — they're sticky and 421 // would cause repeated packet starts without new range data. 422 else if (range_valid_ft && stream_range_en) begin 423 // Don't start write if a read is about to begin 424 if (ft601_rxf) begin // rxf=1 means no host data pending 425 current_state <= SEND_HEADER; 426 byte_counter <= 0; 427 end 428 end 429 end 430 431 SEND_HEADER: begin 432 if (!ft601_txe) begin // FT601 TX FIFO not empty 433 ft601_data_oe <= 1; 434 ft601_data_out <= {24'b0, HEADER}; 435 ft601_be <= 4'b0001; // Only lower byte valid 436 ft601_wr_n <= 0; // Assert write strobe 437 // Gap 2: skip to first enabled stream 438 if (stream_range_en) 439 current_state <= SEND_RANGE_DATA; 440 else if (stream_doppler_en) 441 current_state <= SEND_DOPPLER_DATA; 442 else if (stream_cfar_en) 443 current_state <= SEND_DETECTION_DATA; 444 else 445 current_state <= SEND_FOOTER; // No streams — send footer only 446 end 447 end 448 449 SEND_RANGE_DATA: begin 450 if (!ft601_txe) begin 451 ft601_data_oe <= 1; 452 ft601_be <= 4'b1111; // All bytes valid for 32-bit word 453 454 case (byte_counter) 455 0: ft601_data_out <= range_profile_cap; 456 1: ft601_data_out <= {range_profile_cap[23:0], 8'h00}; 457 2: ft601_data_out <= {range_profile_cap[15:0], 16'h0000}; 458 3: ft601_data_out <= {range_profile_cap[7:0], 24'h000000}; 459 endcase 460 461 ft601_wr_n <= 0; 462 463 if (byte_counter == 3) begin 464 byte_counter <= 0; 465 // Gap 2: skip disabled streams 466 if (stream_doppler_en) 467 current_state <= SEND_DOPPLER_DATA; 468 else if (stream_cfar_en) 469 current_state <= SEND_DETECTION_DATA; 470 else 471 current_state <= SEND_FOOTER; 472 end else begin 473 byte_counter <= byte_counter + 1; 474 end 475 end 476 end 477 478 SEND_DOPPLER_DATA: begin 479 if (!ft601_txe && doppler_data_pending) begin 480 ft601_data_oe <= 1; 481 ft601_be <= 4'b1111; 482 483 case (byte_counter) 484 0: ft601_data_out <= {doppler_real_cap, doppler_imag_cap}; 485 1: ft601_data_out <= {doppler_imag_cap, doppler_real_cap[15:8], 8'h00}; 486 2: ft601_data_out <= {doppler_real_cap[7:0], doppler_imag_cap[15:8], 16'h0000}; 487 3: ft601_data_out <= {doppler_imag_cap[7:0], 24'h000000}; 488 endcase 489 490 ft601_wr_n <= 0; 491 492 if (byte_counter == 3) begin 493 byte_counter <= 0; 494 doppler_data_pending <= 1'b0; 495 if (stream_cfar_en) 496 current_state <= SEND_DETECTION_DATA; 497 else 498 current_state <= SEND_FOOTER; 499 end else begin 500 byte_counter <= byte_counter + 1; 501 end 502 end else if (!doppler_data_pending) begin 503 // No doppler data available yet — skip to next stream 504 byte_counter <= 0; 505 if (stream_cfar_en) 506 current_state <= SEND_DETECTION_DATA; 507 else 508 current_state <= SEND_FOOTER; 509 end 510 end 511 512 SEND_DETECTION_DATA: begin 513 if (!ft601_txe && cfar_data_pending) begin 514 ft601_data_oe <= 1; 515 ft601_be <= 4'b0001; 516 ft601_data_out <= {24'b0, 7'b0, cfar_detection_cap}; 517 ft601_wr_n <= 0; 518 cfar_data_pending <= 1'b0; 519 current_state <= SEND_FOOTER; 520 end else if (!cfar_data_pending) begin 521 // No CFAR data available yet — skip to footer 522 current_state <= SEND_FOOTER; 523 end 524 end 525 526 SEND_FOOTER: begin 527 if (!ft601_txe) begin 528 ft601_data_oe <= 1; 529 ft601_be <= 4'b0001; 530 ft601_data_out <= {24'b0, FOOTER}; 531 ft601_wr_n <= 0; 532 current_state <= WAIT_ACK; 533 end 534 end 535 536 // Gap 2: Status readback — send 6 x 32-bit status words 537 // Format: HEADER, status_words[0..5], FOOTER 538 SEND_STATUS: begin 539 if (!ft601_txe) begin 540 ft601_data_oe <= 1; 541 ft601_be <= 4'b1111; 542 case (status_word_idx) 543 3'd0: begin 544 // Send status header marker (0xBB = status response) 545 ft601_data_out <= {24'b0, 8'hBB}; 546 ft601_be <= 4'b0001; 547 end 548 3'd1: ft601_data_out <= status_words[0]; 549 3'd2: ft601_data_out <= status_words[1]; 550 3'd3: ft601_data_out <= status_words[2]; 551 3'd4: ft601_data_out <= status_words[3]; 552 3'd5: ft601_data_out <= status_words[4]; 553 3'd6: ft601_data_out <= status_words[5]; 554 3'd7: begin 555 // Send status footer 556 ft601_data_out <= {24'b0, FOOTER}; 557 ft601_be <= 4'b0001; 558 end 559 default: ; 560 endcase 561 ft601_wr_n <= 0; 562 if (status_word_idx == 3'd7) begin 563 status_word_idx <= 3'd0; 564 current_state <= WAIT_ACK; 565 end else begin 566 status_word_idx <= status_word_idx + 1; 567 end 568 end 569 end 570 571 WAIT_ACK: begin 572 ft601_wr_n <= 1; 573 ft601_data_oe <= 0; // Release data bus 574 current_state <= IDLE; 575 end 576 endcase 577 end 578 end 579 end 580 581 // ============================================================================ 582 // FT601 clock output forwarding 583 // ============================================================================ 584 // Forward ft601_clk_in back out via ODDR so that the forwarded clock at the 585 // pin has the same insertion delay as the data outputs (both go through the 586 // same BUFG). This makes the output delay analysis relative to the generated 587 // clock at the pin, where insertion delays cancel. 588 589 `ifndef SIMULATION 590 ODDR #( 591 .DDR_CLK_EDGE("OPPOSITE_EDGE"), 592 .INIT(1'b0), 593 .SRTYPE("SYNC") 594 ) oddr_ft601_clk ( 595 .Q(ft601_clk_out), 596 .C(ft601_clk_in), 597 .CE(1'b1), 598 .D1(1'b1), 599 .D2(1'b0), 600 .R(1'b0), 601 .S(1'b0) 602 ); 603 `else 604 // Simulation: behavioral clock forwarding 605 reg ft601_clk_out_sim; 606 always @(posedge ft601_clk_in or negedge ft601_reset_n) begin 607 if (!ft601_reset_n) 608 ft601_clk_out_sim <= 1'b0; 609 else 610 ft601_clk_out_sim <= 1'b1; 611 end 612 // In simulation, just pass the clock through 613 assign ft601_clk_out = ft601_clk_in; 614 `endif 615 616 endmodule