Personally I would avoid these constructions:
1. You generate FFs from variables, which are often hard to find due to name
changing during synthesis.
2. Your logic path consists of FF, - operator, comparator; from a timing
perspective it's better to use the comparator directly on the FF output, and
adjust the expected value accordingly.
3. Your output is not a FF, which may also create timing problems.
Kind regards,
Pieter Hulshoff
#1: I've never had problems finding variable-inferred register names.
The hierarchical naming works the same for signals or variables,
there's just an additional level of hierarchy for the process with
variables. Use descriptive process names and you won't have any
problems.
#2: I think you misunderstood what happens with signal assignments
from variables. For instance, the initical example I gave, and this
one, are cycle-accurately identical to each other WRT the output
signal:
process (clk) is
variable count: natural range 0 to 2**n-1;
begin
if rising_edge(clk) then
count := (count - 1) mod 2**n;
output <= count = 2; -- registered decode of combo count
end if;
end if;
The difference is where the register is implemented. In the initial
example, the register is after the decrement, splitting the decrement
and comparison. In this example, the register is after both the
decrement and the comparison, and is a separate register. The cycle
based timing for output in both is identical. Depending on where the
output is needed, the advantage generally lies with the former.
Naturally this is a trivial example which could easily be re-coded
behaviorally to compensate for an additional clock delay from a
registered outputs, but that is not the point. Re-coding for such
compensation often obfuscates the overall behavior that is intended.
When I specify two output signals, using the same expression, but one
within and one after the clocked clause, Synplify will recognize they
are functionally identical, and optimize the combinatorial output
version away. However, I've never seen it convert the combinatorial
output to a registered output unless such duplication was being
adressed, or register retiming was invoked.
Both simulate the same (WRT cycle-based timing on output), both behave
the same after synthesis.
#3: These examples are not intended as a verdict on the
appropriateness for all applications of combinatorial outputs from
synchronous processes, but rather an example of how to generate one
without introducing an additional process (implied or explicit).
I use signals only for inter-process communication. My processes tend
to be large and complex to minimize both the number of processes and
the signal-based communication between them, both of which contribute
to simulation efficiency. All intra-process communication uses
variables, whether the behavior implies a register or not. I prefer
not to focus on the explicit location of registers, but on the cyclic
behavior of the process, which is easier to read and debug from a
truly sequential description of variables than a pseudo-sequential
description of signals. Register re-timing optimizations change the
register/logic locations anyway, and usually do it better than I can
afford to. Just make sure you disable such optimizations (as well as
register replication, etc.) around synchronization boundaries (and
don't ask me how I know that!).
Andy