From 1686fe7cb3d6fc72386ceaef067838e157018324 Mon Sep 17 00:00:00 2001 From: Joris van Zwieten Date: Thu, 30 Jul 2026 15:46:21 +0200 Subject: [PATCH] himbaechel/xilinx: emit RAM_EXTENSION_{A,B}_LOWER for cascaded RAMB36E1 Depth-cascaded RAMB36E1 pairs (e.g. an inferred 64K x 1 memory) set RAM_EXTENSION_A/B to LOWER on the bottom cell and UPPER on the top cell. The fasm writer ignored these parameters entirely. The UPPER value shares its encoding with NONE (feature bit clear), so only the LOWER cell needs its RAM_EXTENSION_{A,B}_LOWER bit written. Without it the cascade data path between the two cells is not configured and the memory misbehaves beyond the first 32K. Verified against Vivado bitstreams and on xc7a100t hardware (128K ROM built from cascaded pairs passes a full content fingerprint). Co-Authored-By: Claude Fable 5 --- himbaechel/uarch/xilinx/fasm.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/himbaechel/uarch/xilinx/fasm.cc b/himbaechel/uarch/xilinx/fasm.cc index b1611f69..1576d934 100644 --- a/himbaechel/uarch/xilinx/fasm.cc +++ b/himbaechel/uarch/xilinx/fasm.cc @@ -1452,6 +1452,16 @@ struct FasmBackend for (const char *port : {"READ_WIDTH_A", "READ_WIDTH_B", "WRITE_WIDTH_A", "WRITE_WIDTH_B"}) if (int_or_default(ci->params, ctx->id(port), 0) == 1) write_bit(std::string("BRAM36_") + port + "_1"); + // Depth-cascaded pairs (64K x 1): the LOWER cell needs its + // RAM_EXTENSION bit set; UPPER shares the NONE encoding (bit + // clear), so only LOWER is written. Was never emitted, which + // breaks true width-1 cascaded memories. + for (const char *port : {"A", "B"}) { + std::string ext = + str_or_default(ci->params, ctx->id(std::string("RAM_EXTENSION_") + port), "NONE"); + if (ext == "LOWER") + write_bit(std::string("RAM_EXTENSION_") + port + "_LOWER"); + } pop(); } pop();