-1

When making a FIRRTL register, it is possible to provide a "with: (reset => ...)" value used to initialize the register.

When making a FIRRTL memory (aka a dynamic register array), there seems to be no corresponding syntax for providing an initial value for the memory elements. What therefore is the best practice for initializing a memory?

toolic
  • 57,801
  • 17
  • 75
  • 117
Daniel
  • 1,861
  • 1
  • 16
  • 24
  • https://stackoverflow.com/questions/14130181/way-to-initialize-synthesizable-2d-array-with-constant-values-in-verilog does this help? – Fra93 Jul 27 '22 at 06:44
  • Not really because FIRRTL does not seem to have the corresponding syntax. For example, I do not see an "initial" statement in FIRRTL. – Daniel Jul 27 '22 at 14:18

1 Answers1

1

In general, there is no equivalent to a register reset for a memory because there is no way to reset all memory locations in a single cycle, when we look at the typical physical implementations of a VLSI memory (SRAM).

On ASICs, there is also (normally) no way to ensure that memory cells have a particular value when the circuit is powered on. However, in simulation, formal verification and on FPGAs, it is possible to ensure that a memory is initialized. For this purpose, there are several firrtl annotations which are respected by the Verilog backend, the treadle simulator and the formal backend. These annotations are:

  • MemoryScalarInitAnnotation
  • MemoryArrayInitAnnotation
  • MemoryFileInlineAnnotation

You can see how these annotations can be used by looking at the corresponding tests in the firrtl repository.

  • it seems that what you are saying is that the values of a memory are FIRRTL "invalid" until initialized; are they marked that way by default? is there a way to mark them that way? or perhaps "invalid" is not meant to be an initializer annotation that can be changed later, but is a static annotation that is always present, and therefore this idea does not work – Daniel Aug 08 '22 at 03:50
  • All memory cells start out with arbitrary data (what you call "invalid") by default, similar to default initialization to X in Verilog. The annotations I listed above allow us to specify that instead the cells should start out with a particular user specified behavior. – Kevin Laeufer Aug 08 '22 at 14:34
  • But, per your comments, not for an ASIC, right? Note that "invalid" is a FIRRTL term. – Daniel Aug 08 '22 at 20:18
  • On an ASIC you normally need to invest some manual effort into creating the correct memories using a memory compiler (like [Open RAM](https://openram.soe.ucsc.edu/)) and generally, most technologies do not support initialization. – Kevin Laeufer Aug 09 '22 at 13:46
  • What I'm doing right now is making a "valid" register that has a bit for every memory element and that uses "reset" to default to all zeros. When I read the memory, if the corresponding valid register bit is 0, then I just read a zero no matter what the memory says. When I write the memory, I write the corresponding valid register bit to 1. This plan accesses the register and memory in parallel, so seems like an ok design to me. Am I going to have unforeseen problems, such as some kind of non-linearity that lies outside the language model? Large memories requiring a large valid register? – Daniel Aug 10 '22 at 16:28
  • That sounds like a good plan if you need a memory that can be reset in a single cycle. An alternative would be to create a state machine that writes zero to each memory location before the circuit is ready to do its normal operation. Essentially this is a space vs. time tradeoff. Your solution might run into problems if you need a lot of valid registers for larger memories, but should be fine for smaller memory sizes. – Kevin Laeufer Aug 10 '22 at 18:34
  • I know what a state machine is, but how do I make one (1) start with the reset signal, (2) write a Memory, (3) go to the next state, and then (4) stop at the final state? I'm just asking for the basic FIRRTL syntax to make those things happen. The FIRRTL manual is a bit minimalist. All it shows how to do with a with a reset signal is initialize a register. – Daniel Aug 17 '22 at 01:00
  • You would want to store the state of your state machine in a register and that will be reset to the starting state of your FSM. You might find some inspiration from this memory loading state machine in the RISC-V Mini tests: https://github.com/ucb-bar/riscv-mini/blob/ca0c90214f4c18e23caecbfbec4354d7bd332e84/src/test/scala/mini/CoreTests.scala#L43 In the `Init` state, the memory is loaded, after which the FSM switches into the `Done` state. – Kevin Laeufer Aug 17 '22 at 01:30
  • Ah, so I think the missing piece for me was that you need a new clock cycle each time you want to make the state machine go around and you need to notify the client of the chip when the machine is in the final state. So make a state register, use reset to initialize it to the start state, at each clock, do a unit of work and use a mux to go to the next state. When in the final state, just stay there and signal to the outside world that initialization is done. – Daniel Aug 17 '22 at 02:35
  • That sounds correct. Essentially, SRAM memories are more space-efficient than a bunch of registers because you can only update a limited number of entries each cycle (limited by the number of write-ports). – Kevin Laeufer Aug 17 '22 at 14:31
  • I built this, but I seem to be having a problem with Verilator's notion of how to reset a chip. I looked at the FIRRTL and it looks like the register is being initialized when the reset signal is asserted. However, after I run Verilator eval() for the first time with top.reset=0, I get the output as if the state machine has _already_ made one transition and starts in the _second_ state, not the initial state. Even put in an input register used in the mux for writing to the state machine register to prevent it updating during the reset phase, but it updates anyway. – Daniel Aug 19 '22 at 01:58