Is there a reason to initialize (not reset) signal

2019-02-02 18:23发布

问题:

I have never initialized signals. That way any signal missing a reset or assignment would be unknown or initialized. In some reference code they have initialization. This defeats what I wish. Also since intialization isn't synthesizable, there could be a simulation/synthesis mismatch.

Is there any reason to initialize signals in this case?

EDIT 6/17/11: As @Adam12 asked, this is for both storage (Verilog reg) and combinatorial (wire) elements.

回答1:

(The following advice depends greatly on device architecture and synthesis tools, I speak from experience with Xilinx FPGAs such as Virtex-5 parts).

Your supposition that initialization is not synthesizable is incorrect. Initializing a signal absolutely is synthesizable!

For example, this can be synthesized so it programs the device with an initial value:

signal arb_onebit : std_logic := '0';
signal arb_priority : std_logic_vector(3 downto 0) := "1011"

Additionally, you can achieve better Quality of Results (QoR) using initialization of signals and forgoing the traditional async or sync global reset schemes. This is because the tools no longer need to route reset signals to all your FFs around your part. While some older generation FPGAs might have had dedicated resources for resets, this is not the case in newer parts. This means that the resets are routed just like every other signal in your design, slowing down your build process and dragging down performance.

What you can do instead? Use signal initialization.

  1. Use dedicated "GSR" (global set/reset I believe). This is accessible through a dedicated Xilinx primitive. Note that when using the GSR not all memory elements of the device is reset. For example, BRAMs retain values I believe, but FFs are reset to initialized values.
  2. PROGL your device. This will cause the entire device to be reprogrammed from the original bitstream (located in a PROM). Every time the device is loaded from a PROM all memory elements (FFs, BRAMs, etc) are brought up into a known state dictated by your initialization. If you do not initialize, I believe it defaults to a "0" state. You can verify the state that a memory element is initialized to by viewing the results using a tool like FPGA Editor (supplied as part of Xilinx toolset)

If you really need to reset just a small part of your design (a "local" reset) then you should handle this as you typically handle resets.

Here are some references for Xilinx tools:

  • White paper describing high level considerations for resets
  • XST 13.1 User Guide See page 50 and 128
  • Xilinx Virtex 5 YouTube training series. Part 4 looks like what you want.

EDIT

After some further research I have found that specifying initial values, while helpful in improving QoR in some cases, it can hurt it in others. It really boils down to how your synthesis tool vendor will honor the initial value. At its core, an initial value is a constraint on the tool. When your design is synthesized and then mapped to the part, a note gets added to your design that "when you implement this memory element, give it this initial value." In many cases, adding this constraint prevents the element from being optimized (removed, combined, etc).

Suggestion: There is no hard/fast/one-size-fits-all rule for reset and initialization. For best optimization and resource utilization you must know your synthesis tool, and you must know your targeted technology.



回答2:

There is a school of thought that touts signal initialization as a substitute for resets. Generally these people are targeting SRAM based FPGAs that will guarantee state upon startup. This will work for those devices but in general it is a bad practice. The usual reason for doing this is to alleviate routing resources and eliminate a class of net that needs to meet timing. That is okay in some cases but a reset-less design is painful to fix when you want to incorporate it into a system that really does need a reset. Often this technique is promoted for data flow designs that will clear out garbage data on their own. Again that is okay but only for the parts of the design state that are actually self clearing.

In general you should use some sort of reset. I prefer to use an asynchronous reset that is released synchronously. It provides the following advantages:

  • You can control initialization of your device independent of any startup logic in the FPGA.

  • You have guaranteed initialization even if the clock is dead. This is important if a design has bi-directional I/O and you don't want to risk coming up with output drivers stuck on.

  • You can migrate your code easily to an ASIC if needed. A proper controllable reset is essentially required for implementing BIST and JTAG.

  • If you still insist on a reset-less design you can easily tie the reset inactive and let the synthesizer strip it out. Going the other way is painful.

  • Not all synthesizers pay attention to the initialization value. You're going to go through a lot of pain if you have to switch to a tool that doesn't.

  • The synchronous release ensures that you won't have spurious setup or hold violations when coming out of reset. This of course still depends on configuring proper timing constraints.

  • It is easy to forget an initialization value and end up with a default that you didn't want. Having a reset section locally in each synchronous process/block is more maintainable.

Synchronous resets are often derided for introducing an additional level of delay for the reset control. In practice this is less of a concern with LUT based FPGAs especially the newer 6-LUT based families from Xilinx because you often have a spare input to the LUT feeding a FF that can be used for the synchronous reset without introducing another level of delay. I have done some rudimentary testing and found that at least for simple cases there is no real speed disadvantage compared to asynchronus. I avoid synchronous resets, though, because they don't work when the clock is dead.

Modern FPGAs are rich in routing resources and generally have a large number of unused global nets. Resets are usually not culpable in a design being unroutable. If you have timing issues with resets routed on the normal fabric try manually instantiating clock buffers on your reset nets to free up resources for the rest of the logic. This practice also sets up your design for convenient ASIC migration.