I’m looking to implement a register file with a zero register. In previous Verilog projects, I found the most performant way to do this was to make an asynchronous RAM initialized to have 0 in the zero-register position and gate the write-enable based on the address being nonzero.
In Clash it seems like the asyncRam primitive doesn’t have an initialization option. Is there a way to implement this behavior? The options that leap to mind are either another primitive that I haven’t found yet or some way of introducing a register write during the reset phase, but I don’t know my way around the documentation well enough yet to be able to know if such things are possible.
The tricky thing would probably be coming up with a good API for such a feature.
I’ve seen people write small wrappers these things, something like:
regFile :: _ => SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
regFile size rd wr = res
where
res = mux (rd .==. 0) (pure 0) (asyncRam size rd wr')
wr' = fmap ignoreWrite0 wr
ignoreWrite0 (Just (0,_)) = Nothing
ignoreWrite0 x = x
I don’t know if the Clash side is smart enough to optimize that properly - my design isn’t far enough along to start testing in hardware yet - but in a previous plain-Verilog implementation yosys+nextpnr generated substantially faster bitstreams when using an initialized RAM primitive rather than a mux. I have something like that in my current implementation but I suspect it will be slow.