The Short Circuit

Mike Morgan's technical journal

Electrical engineering rules of thumb (EEROTs) are time saving design guidelines used by electrical engineers.  However, not all EEROTs are created equal, and many are not timeless.   I have witnessed engineers, including myself, blindly apply EEROTs, only to regret it the morning after. 

This raises the question:  how does a young electrical engineer know when to use an especially alluring rule of thumb?  The answer is:  one must keep in mind not only the EEROT, but also its rationale.

Here, we begin what will hopefully be the first in a series of posts discussing various EEROTs.

Old EEROT #1: Do not use signal initializations in synthesizable code

Signal initilization in synthesizable VHDL to initialize registers used to be a cardinal sin because initialization was simulatable but not sythesizable.  What this means is it would behave one way in simulation, but infer logic that did not behave the same way in practice.  This led to behavioral discrepancies between simulation and hardware.  Consequently, a popular EEROT used to be "do not use signal initialization in synthesizable code." 

For example, Ben Cohen, in VHDL coding styles and methodologies, wrote "initialization is ignored by sythesizers".(Cohen 1999, p. 119)  To be fair, Mr. Cohen's advice is still correct when targeting ASICs, and it was probably valid for FPGAs back in 1999, but FPGA synthesizers have evolved since then, and no longer universally ignore initializations when initialized signals infer registers.

Specifically, in addition to the connections among registers and the specification of combinatorial logic, FPGAs, unlike most if not all ASICs, have an innate capacity to provision the values registers contain immediately after configuration, independent of reset.

In response, FPGA synthesizers initially provided out-of-band mechanisms to specify the after-configuration value of registers.  One such mechanism took advantage of VHDL's ability to specify user defined attributes.  In the following (now depreciated) example, based on XST, a VHDL user defined attribute init is applied to my_reg, in order to control its value upon exiting FPGA configuration:

  signal my_reg : std_logic_vector(16 downto 0);
  attribute init: string;
  attribute init of my_reg: signal is "1011111011101011";

However, simulators did not pay attention to the vendor specified user defined attribute init, which led to simulation/synthesis mismatches.  To address this, a combination of user defined attributes (for synthesis) and signal initialization (for pre-synthesis simulation) were necessary:

  signal my_reg : std_logic_vector(16 downto 0) := X"BEEF";
  attribute init: string; attribute init of my_reg:
  signal is "1011111011101011";

Eventually, software engineers who write FPGA synthesizers recognized the redundancy implicit above (either that, or I noticed the INIT was unnecessary), as well as the risk of mismatch between the VHDL initialization used by the simulater and the user defined attribute use by the synthesizer, and broke ranks with those who write ASIC synthesizers.  They added an ability to synthesize signal initialization when the signal in question was used to infer a register, RAM, or ROM.  (Even now, however, the user defined attributes are still supported, but often unnecessary.)

For example, the following VHDL will infer a 16-bit circular shift register initialized to BEEF16:

library IEEE;
use IEEE.STD_LOGIC_1164.all;
-- free-running 16-bit circular shift
-- register initialized with 0xBEEF
-- intended for use in FPGA supporting
-- register initialization
entity BEEFCR is
  iCLK  : IN   std_logic;
  oBEEF : OUT  std_logic_vector(15 downto 0)
end entity BEEFCR;

architecture rtl of BEEFCR is

signal my_reg : std_logic_vector(15 downto 0) := X"BEEF";

begin -- architecture

  if(rising_edge(iCLK)) then
    my_reg <= my_reg(my_reg'high-1 downto 0) & my_reg(my_reg'high);
  end if;
end process ICSR_PROCESS;

oBEEF <= my_reg;

end architecture rtl;

In this case, the behavior of the hardware inferred will match the pre-synthesis simulation.  It has the added advantage of not depending on vendor specific user defined attributes.

This initialization of my_reg is synthesizable using recent versions of Xilinx's XST and Synopsis' Synplify Pro when targeting recent Xilinx FPGAs.  This code is likely to also synthesize when using other synthesizers and/or FPGAs, but if you would like to use the "register initialization via signal intitialization" feature of FPGA synthesizers, it is always best to heed the advice of Ronald Reagan:  "Trust but Verify."   Don't just take my word for it.  Examine the post place and route simulation model, the routed FPGA, and/or the netlist, and verify that the flip-flops used to implement my_reg are really initialized to X"BEEF".  (If it doesn't work for you, please leave the synthesizer/fpga combination used in the comments below).

My take on this rule of thumb

EEROT #1 is still useful if targeting ASICs, or while developing reusable code that may be ported to ASICs.  However, if you are writing code that will only be used in an FPGA, and your synthesizer supports it, initialization of registers via VHDL signal initialization is a simple and useful tactic. 

You may find yourself working at a company with engineering standards that explicitly prohibit the use of signal initialization in VHDL code.  As we will see,  the value of rethinking EEROT #1 while designing FPGAs will become more apparent in future post on EEROT #2, where we will discuss reset vis-à-vis modern FPGAs.  In such cases, it may behoove your company to rethink its coding standards when targeting FPGAs.

New EEROT #1: Do not use signal initializations in synthesizable code if the synthesizer or targeted hardware does not support it, or if the code may be reused with such synthesizers or hardware in the future, or if your company has a blanket prohibition and you're not the type to fight city hall.

That was a mouth full.

Closing caveats

In closing, it should be noted that the initialization of signals that infer combinatorial logic is not synthesizable.  E.g.,:

  signal Y : std_logic := '1'; -- This initialization is not synthesizable
  Y <= A XOR B;

is not synthesizable. 

It should also be noted that the VHDL syntax to make an assignment to a constant is and probably always was synthesizable, but doesn't fall under the purview of EEROT #1.

  constant LOGIC1 : std_logic := '1'; -- Synthesizable


  • Xilinx (2011)
  • Cohen, Ben (1999) VHDL coding styles and methodologies 2nd Edition Springer

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

© 2018 The Short Circuit | Entries (RSS) and Comments (RSS) |