2
\$\begingroup\$

I'm writting a code and I have 2 dumb questions:

1- Is it a bad practice to use "initial" in the module description?

I'm asking this because I have a frequency divider with 2 signals (clk_in and clk_out). If I want to see the behaviour in simulation, I have to give an initial value to clk_out, otherwise clk_out will always keep as X. Then, I used "initial" instead of using a reset signal.

2- Why the code without initializing the output works fine in the FPGA but it doesn't in simulation?

My code basically do this: Clk_out <= ~Clk_out;

Thanks in advance.

\$\endgroup\$
2
  • \$\begingroup\$ I've tagged the question with FPGA as you seem to be talking about FPGAs. Feel free to roll back if you are asking about Verilog in general (e.g. including ASICs) \$\endgroup\$ Jan 28, 2018 at 15:27
  • \$\begingroup\$ not dumb questions at all \$\endgroup\$ Jan 28, 2018 at 16:04

4 Answers 4

3
\$\begingroup\$

1/ Is it bad practice?

It is perfectly fine and often done in test benches. But I assume that is not what you where alluding to. I would prefer to say it is rarely done. The reason is that it can not be synthesized for all FPGAs and definitely not for ASICs. This makes that your design can no longer be trusted as what you simulate may not match what the real logic.

However there are some exceptional cases where you need to use an initial in your module for the code to work. To give an example: below is a divide by four which does not require a reset. It is a safe circuit as all possible states are used so it does not matter in what state it starts. But without 'initial' it can not be simulated as it will not come out of the 2'bxx state.

reg [1:0] div_4;
always @(posedge clk)
   div_4 <= {div_4[0],~div_4[1]};

As I have commented in other Verilog posts: use it only if you really, really know what you are doing.

2/ Why the code without initializing the output works fine in the FPGA but it doesn't in simulation?

It may work in your FPGA but that does not mean it will work in general.

  • FPGAs often set all internal register to zero. In that case it works if your initial state is also zero.
  • Some FPGAs can preset the registers when they are loaded. Thus you can 'set' or 'clear' the initial register state.

For both it works only once at startup. If you for example reset your logic it may no longer be in the state you have used when you started your simulation the first time. Thus your code might or might not work.

\$\endgroup\$
3
  • \$\begingroup\$ If "initial" cannot be synthesized, why Xilinx ISE gives me no errors? It synthesizes the code perfectly. \$\endgroup\$ Jan 28, 2018 at 14:57
  • \$\begingroup\$ It is a common misconception that initial blocks cannot be synthesised. In fact, for FPGAs at least, they can - it is quite common to use initial blocks to set the power-on value of structures such as RAMs, ROMs, and registers. \$\endgroup\$ Jan 28, 2018 at 14:58
  • \$\begingroup\$ reg [1:0] div_4 = 2'b00; is an identical construct to reg [1:0] div_4; initial begin div_4 = 2'b00; end for setting the initial power-on value of a register. \$\endgroup\$ Jan 28, 2018 at 14:59
3
\$\begingroup\$

It is a common misconception that initial blocks cannot ever be synthesised.

In fact, for FPGAs, they can in most cases be synthesised. In fact the use of initial blocks is quite common. You can use them to set the power-on value of structures such as RAMs, ROMs, and registers.

This is not bad practice at all, and helps with both simulation and synthesis code.

In many cases with registers however, you are better off using a reset signal to control the value of the register. This is because it gives you the option to put the register in a known state at any point. If you only reset a partial group of registers in a circuit, you can end up with weird states existing.

In free-running circuitry such as your clock <= ~clock example, it is probably not necessary to include a reset, and using an initial value will help ensure that the simulation and synthesis behaviour match.


In terms of why your code doesn't work in simulation, it is because the simulation actually has four states, whereas synthesis really only has three.

The x (unknown) state is the default for signals which are not initialised in simulation. Unknown represents a condition where the simulator doesn't know what the value is, it could be a 1, or it could be a 0.

If you take an unknown value and invert it, you end up with another unknown value. As such your simulation will end up always showing x for the value, because it never knows where to start.

In synthesis code, this will not stop it running (*) - it will either be a 1 or a 0, and the FPGA will simply calculate the output based on whatever that value may be.


(*) The issue lies actually in the fact that you don't know how it will start. This is not a problem if you have simulated it to find out, but if your simulation fails, it can be hard to predict behaviours.

There are cases when having no initial value is not an issue - for example a data bus which has a valid signal. As long as the valid signal initialises to low to indicate the data bus is invalid, then it doesn't matter what value the data bus starts in. However for registers like the "launchMissile" variable, leaving it to chance whether that starts high or low is dangerous.

\$\endgroup\$
3
  • 3
    \$\begingroup\$ It is a common misconception that initial blocks cannot be synthesised. I don't agree with that. It can only be used in FPGAs, not in CPLD's, not in ASICs. (I have corrected my previous answer.) \$\endgroup\$
    – Oldfart
    Jan 28, 2018 at 15:21
  • \$\begingroup\$ @oldfart I agree that not in all cases, but I don't claim that. Saying they cannot be synthesised is wrong, because in some cases they can be. See If and only if. \$\endgroup\$ Jan 28, 2018 at 15:23
  • 1
    \$\begingroup\$ Capenter: I write it off as difference in language usage. Especially with many non-English speakers I try to use simple phrases but always make my language on the 'safe' side. So I agree with your remark that my usage of 'wrong' was at fault and corrected it. At the same time I find a phrase like you use to start the answer above extremely dangerous as most readers will not read it as "if and only if" but more like "He it is fine", whilst it can easy lead to simulation mismatches. It may also be because many years in ASIC design makes me paranoid for simulation mismatches. \$\endgroup\$
    – Oldfart
    Jan 28, 2018 at 15:39
1
\$\begingroup\$

You can indeed use initial values in Verilog or VHDL but they reduce the portability of your design. They are therefore to be avoided and are not recommended.

The reasons...

Your design will behave differently depending on the target device. Synthesize it for a RAM-based FPGA (typ. Altera, Xilinx) and your design will work because the initial values will be recognised.

Synthesize it for a Flash-based FPGA (typ. Microsemi), a CPLD (typ. Altera, Lattice) or an ASIC and your design won't work because initial values are meaningless. The cause will not immediately be apparent, particularly if it isn't your own design, so there's engineering time and cost in discovering it and reworking it.

The alternative...

Use a reset. RAM-based FPGAs provide asynchronous (or, less commonly, synchronous) resets on their DFFs, so it costs you routing but not resources. The design is now portable across all CPLDs, FPGAs and ASICs.

Each target device now needs to provide a reset for itself.

This might be externally generated, then passed through a simple input stage to make an asynchronously asserted, synchronously negated, reset that avoids metastability in DFFs on negation.

Or it can be internally generated in a RAM-based device, using a simple n-bit (I use 4-bit) shift register with an initial value of '0's and shifting in a '1'. An initial value can be used here on this shift register, and here alone, because (a) it results the same reset signal to all DFFs as an external reset would and (b) this is the only part to change if a different device is targeted. All other Verilog/VHDL remains completely unchanged in a device re-target.

The conclusion...

Initial values have pitfalls and can cause invisible problems. A reset does not and will not.

I could say it's up to the professional designer as to their choice...but it's not. Because, unless working completely alone, they don't pay for the development or bear the costs of the consequences.

If you're designing professionally then you should be delivering the most problem-free designs to your employer or client, and that includes portability. You're also making harder to re-use your own designs if you work elsewhere in a year, five years or ten years, on different devices. The design owners (your employer or client) will expect other engineers to be able to re-use your designs that they paid for, in different products with different target devices.

The fact that your design synthesized and worked here is proof of nothing, I'm afraid. In engineering, it is very easy to make designs that work. (Think of that bloke whose shelves are barely hanging up with one nail but still there.) Our goal is to make designs that never don't work. In digital circuit design, this is one way to make that much more likely.

Many clients I have worked for simply ban initial values in their coding standards for all these reasons. The majority of IP you'll find, especially PLD vendor IP, uses resets for the same reasons.

In summary: don't use initial values. Keep your designs portable. Keep yourself mobile across jobs and industry. Lessen everyone's fault-finding.

\$\endgroup\$
0
\$\begingroup\$

There is an easy way to avoid initial that is synthesizable : an explicit reset mechanism. Give your module a reset input and a requirement for it to be asserted during and for a few cycles after startup to get the module into a sane state.

This requirement can be easily fulfilled from a testbench, you can also verify that there are no X outputs generated by the full design (we don't care that much internally), and you get a design that can be used with a synthesis process that doesn't allow for initial values, or in a context that requires a shutdown mechanism for your module.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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