Fix Vivado DRC: consolidate data_pending flags into single always block, fix MMCM LOCKED false_path

usb_data_interface.v: doppler_data_pending and cfar_data_pending were
driven by two always blocks (CDC sync block set them, write FSM cleared
them). Vivado DRC MDRV-1 flagged this as multiple drivers. Moved all
set/clear logic into the write FSM always block using doppler_valid_ft
and cfar_valid_ft edge wires.

adc_clk_mmcm.xdc: changed set_false_path -from to -through for MMCM
LOCKED pin (not a valid timing startpoint). Eliminates CRITICAL WARNING
from Builds 19/20/21.

19/19 FPGA regression pass.
This commit is contained in:
Jason
2026-03-20 01:56:20 +02:00
parent 05efe692ad
commit 2efab23cd9
2 changed files with 14 additions and 5 deletions
@@ -56,7 +56,10 @@ set_false_path -from [get_clocks clk_120m_dac] -to [get_clocks clk_mmcm_out0]
# --------------------------------------------------------------------------
# MMCM Locked — asynchronous status signal, no timing paths needed
# --------------------------------------------------------------------------
set_false_path -from [get_pins rx_inst/adc/mmcm_inst/mmcm_adc_400m/LOCKED]
# LOCKED is not a valid timing startpoint (it's a combinational output of the
# MMCM primitive). Use -through instead of -from to waive all paths that pass
# through the LOCKED net. This avoids the CRITICAL WARNING from Build 19/20.
set_false_path -through [get_pins rx_inst/adc/mmcm_inst/mmcm_adc_400m/LOCKED]
# --------------------------------------------------------------------------
# Hold waiver for BUFIO→MMCM domain transfer (if Vivado flags hold violations)
+10 -4
View File
@@ -228,8 +228,6 @@ always @(posedge ft601_clk_in or negedge ft601_reset_n) begin
doppler_real_cap <= 16'd0;
doppler_imag_cap <= 16'd0;
cfar_detection_cap <= 1'b0;
doppler_data_pending <= 1'b0;
cfar_data_pending <= 1'b0;
// Fix #5: Default to range-only on reset (prevents write FSM deadlock)
stream_ctrl_sync_0 <= 3'b001;
stream_ctrl_sync_1 <= 3'b001;
@@ -280,11 +278,9 @@ always @(posedge ft601_clk_in or negedge ft601_reset_n) begin
if (doppler_valid_sync[1] && !doppler_valid_sync_d) begin
doppler_real_cap <= doppler_real_hold;
doppler_imag_cap <= doppler_imag_hold;
doppler_data_pending <= 1'b1;
end
if (cfar_valid_sync[1] && !cfar_valid_sync_d) begin
cfar_detection_cap <= cfar_detection_hold;
cfar_data_pending <= 1'b1;
end
end
end
@@ -318,12 +314,22 @@ always @(posedge ft601_clk_in or negedge ft601_reset_n) begin
cmd_opcode <= 8'd0;
cmd_addr <= 8'd0;
cmd_value <= 16'd0;
doppler_data_pending <= 1'b0;
cfar_data_pending <= 1'b0;
// NOTE: ft601_clk_out is driven by the clk-domain always block below.
// Do NOT assign it here (ft601_clk_in domain) causes multi-driven net.
end else begin
// Default: clear one-shot signals
cmd_valid <= 1'b0;
// Data-pending flag management: set on valid edge, cleared when
// consumed or skipped by write FSM. Must be in this always block
// (not the CDC sync block) to avoid Vivado multiple-driver DRC error.
if (doppler_valid_ft)
doppler_data_pending <= 1'b1;
if (cfar_valid_ft)
cfar_data_pending <= 1'b1;
// ================================================================
// READ FSM — host-to-FPGA command path (Gap 4)
//