mirror of https://github.com/YosysHQ/nextpnr.git
himbaechel/xilinx: emit BRAM36 width-1 features for RAMB36E1
A RAMB36E1 port configured with width 1 (true 32K x 1 mode) needs the
RAMB36-level BRAM36_{READ,WRITE}_WIDTH_{A,B}_1 feature in addition to
the per-half RAMB18_Yx width bits, which were the only ones emitted.
In this mode the two 16K halves interleave even/odd bit addresses.
Without the RAMB36-level feature both halves respond at addr>>1:
every write hits the bit pair 2k/2k+1 and the address LSB is ignored,
so half the memory aliases the other half.
Verified against Vivado bitstreams for the same configuration and on
xc7a100t hardware (32K x 1 and cascaded 64K x 1 inferred memories).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
68c1acd80a
commit
75c8144d42
|
|
@ -1442,6 +1442,18 @@ struct FasmBackend
|
|||
write_bit("CASCOUT_ARD_ACTIVE", !used_rdaddrcasc.empty());
|
||||
write_bit("CASCOUT_BWR_ACTIVE", !used_wraddrcasc.empty());
|
||||
}
|
||||
// A RAMB36E1 with a width-1 port needs the RAMB36-level BRAM36_*_WIDTH_*_1
|
||||
// feature in addition to the per-half RAMB18_Yx width bits. Without it the
|
||||
// two 16K halves (which interleave even/odd bit addresses in true 32K x 1
|
||||
// mode) both respond at addr>>1: every write hits bit pairs 2k/2k+1 and
|
||||
// the address LSB is ignored.
|
||||
if (half == 0 && ci != nullptr && ci->type == id_RAMB36E1_RAMB36E1) {
|
||||
push("RAMB36");
|
||||
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");
|
||||
pop();
|
||||
}
|
||||
pop();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue