3
\$\begingroup\$

Take this example:

port(clk        : in  std_logic; 
 areset_n       : in  std_logic; 
 ena            : in  std_logic; 
 load           : in  std_logic;
 load_val       : in  unsigned(cnt_width-1 downto 0) := (others => '0');  
 counter_value  : out unsigned(cnt_width-1 downto 0) := (others => '0')  
);

counter_value should be initialised to some value since it's my output, but is it neccessary to initialise the input values too?

Should all the signals be initialised to 0, including clk and reset?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Do not use initial values in synthesizable VHDL i.e. VHDL which creates a logic circuit in your target FPGA/CPLD/ASIC. Use a reset term, controlled by the reset input you have.

This makes your design far more portable other devices and lets you drop in other IP more easily. In my experience, the vast majority of IP you'll encounter uses reset terms, for the same reason of portability.

In a RAM-based FPGA, initial values are typically added into the configuration file during synthesis and therefore loaded into the relevant registers during device configuration. This is not true of flash-based FPGAs or many CPLDs, as well as ASICs, so the same design put into these devices now won't work and the source can be hard to track down.

Using a reset term removes all these problems. You want to have design modules that you can pull into other designs in the future and you don't know what you'll be working with by then.

You can use initial values safely enough in testbenches.

Remember that this is a digital logic circuit, not a computer program. The inputs do not need a reset value here - the logic gate driving them needs one.

If you have an external reset, don't forget to synchronise it to your clock before use. This is in case the reset input changes just as your clocked register sees its active edge on its clock and possibly goes metastable. Use a shift register to produce a reset at least (say) 4 clocks long which is asynchronously asserted and synchronously negated, such as:

  signal resetSR : std_logic_vector(3 downto 0);

  process(RESET_N, CLK) is
  begin
    if (RESET_N = '0') then
      resetSR  <=  "1111";

    elsif rising_edge(CLK) then
      resetSR  <=  resetSR(2 downto 0) & '0';

    end if;
  end process;

  rst  <=  resetSR(3);

If you don't have an external reset to use for your internal reset, you can produce one in a RAM-based FPGA using (dare I say it) one solitary instance of an initial value. With big comments all over it, drawing the attention of other engineers who may migrate your design in the future. You can create a (say) 4-bit shift register with the initial value of "1111" and shift a '0' into it at clock rate. Use the last bit of this shift register as your reset. It will be '1' for the first four clocks after reset, then '0' thereafter.

Avoid doing this if you have an external reset signal.

  -- THIS SIGNAL IS THE ONLY USE OF AN INITIAL VALUE.
  -- THIS MAY NEED TO CHANGE WHEN MIGRATING THIS DESIGN TO OTHER DEVICES.
  signal resetSR : std_logic_vector(3 downto 0) := "1111";

  process(CLK) is
  begin
    if rising_edge(CLK) then
      resetSR  <=  resetSR(2 downto 0) & '0';
    end if;
  end process;

  rst  <=  resetSR(3);
\$\endgroup\$
6
  • \$\begingroup\$ Why are you formatting your code snippets so oddly? All you need to do is type/paste them in, highlight the whole block of text, and then either hit control-k or click on the double braces in the toolbar. This inserts four spaces at the beginning of each line, which is what signals the Markdown rendering engine to treat it like an HTML <pre> tag, preserving indentation with no word wrap, etc. \$\endgroup\$
    – Dave Tweed
    Commented Jun 4, 2017 at 22:22
  • \$\begingroup\$ Well, certainly not for the love of it, @DaveTweed. I was clicking on {} to start with, then putting text it and it went weird over multiple lines and I ended up bodging it and knowing it. Didn't know the text-then-{} order, I'll give it a try. Thanks. \$\endgroup\$
    – TonyM
    Commented Jun 4, 2017 at 22:29
  • \$\begingroup\$ If you're typing the code in directly, just be sure to start each line with at least four spaces, and it will be formatted as you go. The {}/ctrl-K feature is mainly useful when you're pasting code from somewhere else. \$\endgroup\$
    – Dave Tweed
    Commented Jun 4, 2017 at 22:35
  • \$\begingroup\$ @DaveTweed, oh that's interesting and probably why my 2-space starts go wrong. I'm usually pasting something in that I knocked up in UltraEdit. OK, cheers for that :-) \$\endgroup\$
    – TonyM
    Commented Jun 4, 2017 at 22:38
  • \$\begingroup\$ Also, this is on a port — giving a default value to an in port that may be unconnected is useful in synthesis. \$\endgroup\$ Commented Nov 15, 2021 at 19:52
0
\$\begingroup\$

Tt is possible to initialize registers, wires can not be initialized because they are simple connections to registers (which, most of the time, need to be initialized).

When RAM-based FPGA configures (e.g. Altera Cyclone series), it initializes registers to 0 (to my knowledge), thus it is a task of designer to ensure there's some external to FPGA signal acting as reset, which triggers FPGA registers' initialization according to application's initial state.

From HDL point of view, as you ask, registers can be driven (including initialization) in one process/always block; input going from registers can not be initialized because for initialization you need output ("write") action, input can only be "read".

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.