migen
migen copied to clipboard
Cat(..)[slice] on LHS needs a proxy
When attempting to use Record.raw_bits() to create a bus to manipulate in further Migen expressions, Migen will generate the concatenation "in place" in the generated Verilog code for each use of the bus instead of assigning to a temporary bus.
E.g. Assuming a record with fields a, b, c, d of varying widths and used as inouts, Migen will generate:
{a, b, c, d}[0] = my_wire;
for each use of the Signal created from Record.raw_bits(), as opposed to:
my_bus = {a,b,c,d};
assign my_bus[0] = my_wire;
While the generated Verilog code in the former may be syntactically valid, some vendors may reject such assignments anyway- Xilinx's compiler (when use_new_parser=YES, as it should be for Migen) is known to choke on these assignments.
See the following gist for the code I was trying to synthesize when I ran into this issue: https://gist.github.com/cr1901/c994d2d307a35f1344ac
A workaround to using Record.raw_bits() is to iterate over a record's subsignals using Record.iter_flat(). Using the above gist as an example, replace the line
self.specials += [self.iobufs[i].get_tristate(self.pins[i])]
with the following lines in a separate loop after for i in range()
:
for subsig, _ in pads.iter_flat():
siglen = flen(subsig)
for i in range(siglen):
self.specials += [self.iobufs[start + i].get_tristate(subsig[i])]
start += siglen
if(start >= 30): #iter_flat() is generator... only need 30 out of 32 signals.
break
I suspect that the solution here is to reaffirm that migen does not guarantee syntactictally valid verilog.
@jordens You may be right. FWIW, I have found another edge case where the same invalid Verilog idiom will be generated when dealing with tristates: https://gist.github.com/cr1901/3a666c635f956fa6a819
Triage: fixed in nMigen.