Hacker News new | ask | show | jobs
by moring 2434 days ago
How do Chisel/FIRRTL handle inference of built-in primitives like synchronous RAM blocks in FPGAs?

I have built my own HDL, which is basically "cleaner Verilog" and not a generator-style approach like Chisel, and gets compiled to Verilog. One big problem I had was how to describe RAM blocks with synchronous read/write ports, or even worse, RAM blocks with two independent ports which are both synchronous read/write (i.e. BlockRAM in Xilinx FPGAs).

My intention was to make the HDL more powerful than just providing BlockRAM as a built-in module that can be instantiated, because this way the "assignment" of the read/write port, which determines clock/enable logic, can be merged into other synchronous blocks using the same clock and enable signals (nested if-statements), thus be more readable. But I never found an easy way to "extract" the BlockRAM's output register and enable out of a statement block, short of writing a full primitive inference system myself (which I tried to avoid).

Without such extraction, I could only convert the statement to a Verilog statement and rely on the inference from Xilinx's tools. I ended up with "patterns" that the hardware developer has to use, very similar to Xilinx's primitive instantiation templates, which would be compiled to the appropriate patterns in Verilog. Naturally this takes several tries until Xilinx's tools recognize what I intended to build. In retrospect, providing built-in submodules would have been easier.

1 comments

For non-BRAM/SRAM primitives that you explicitly want to use, your best bet would be a blackbox. However, for memory, Chisel has built in memory hardware types `Mem` (synchronous write/asynchronous read) and `SyncReadMem` (synchronous write/synchronous read). A read or a write access to these infer a port.

On the FIRRTL side, there's a dedicated pass `ReplSeqMems` that will replace sequential memories with a blackbox and configuration file. The intent here is that the configuration file (describing info like width, depth, number of ports, etc.) can then be used as input to an SRAM generator.

For FPGAS, (and I may be wrong here), I think that without `ReplSeqMems`, when using `SyncReadMem`, things will automatically get inferred to BRAM for Xilinx tools. However, the same approach to `ReplSeqMems` could be used to replace memories with the correct template for a specific FPGA vendor tool.