From 0c71b06aa3a1105f4fbc41ac29dcadfa050f1389 Mon Sep 17 00:00:00 2001 From: Joris van Zwieten Date: Thu, 30 Jul 2026 15:38:22 +0200 Subject: [PATCH] himbaechel/xilinx: fix MMCM loop filter programming The MMCM fasm writer put the 10-bit BANDWIDTH loop-filter word into FILTREG1_RESERVED[11:0] and wrote a hardcoded 0x3d4 into TABLE[9:0]. prjxray's TABLE[9:0] is the loop-filter table word; with the filter word misplaced the MMCM analog loop is misconfigured and never asserts LOCKED on hardware (clock outputs stay dead). Swap them: TABLE[9:0] gets filter_lookup[CLKFBOUT_MULT-1], FILTREG1_RESERVED[11:0] gets the constant 0x8, matching Vivado bitstreams for the same configurations. Hardware-validated on xc7a100t (QMTech Wukong): MMCM-derived clocks lock and run; the same designs never asserted LOCKED before this change. Co-Authored-By: Claude Fable 5 --- himbaechel/uarch/xilinx/fasm.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/himbaechel/uarch/xilinx/fasm.cc b/himbaechel/uarch/xilinx/fasm.cc index 7cf5704a..a33707f4 100644 --- a/himbaechel/uarch/xilinx/fasm.cc +++ b/himbaechel/uarch/xilinx/fasm.cc @@ -1691,14 +1691,15 @@ struct FasmBackend filter_lookup = Xc7MMCM::filter_lookup_high; else filter_lookup = Xc7MMCM::filter_lookup_optimized; - write_int_vector("FILTREG1_RESERVED[11:0]", filter_lookup[clkfbout_mult - 1], 12); + // TABLE holds the loop-filter word; FILTREG1_RESERVED is a constant 0x8 (matches Vivado) + write_int_vector("FILTREG1_RESERVED[11:0]", 0x8, 12); // 0x9900 enables fractional counters // only int counters would be 0x1 << 8 // 0xffff enables everything, I suppose, this is what is used in xap888 write_int_vector("POWER_REG_POWER_REG_POWER_REG[15:0]", 0xffff, 16); write_bit("LOCKREG3_RESERVED[0]"); - write_int_vector("TABLE[9:0]", 0x3d4, 10); + write_int_vector("TABLE[9:0]", filter_lookup[clkfbout_mult - 1], 10); pop(2); } void write_dsp_cell(CellInfo *ci)