Jim said:
Getting back to what Andy said:
-- the background
-- the statement that worries me:
My read of this says:
process (clk)
begin
if rising_edge(Clk) then
if (le = '1') then
MyVar := ...
end if ;
MySig <= MyVar ;
end if ;
end process ;
In the past, I have seen synthesis tools create a register for
MyVar even when it was redundant with the one for MySig.
The reference to MyVar in the assignment to MySig is a combinatorial
reference to MyVar if le='1', and a registered reference if le ='0'.
So, the synthesis will put a mux on the input to the MySig register to
make that choice. The interesting optimization is that the mux before
MySig looks amazingly like the clock enable mux on the MyVar register.
And if the same mux feeds two registers, then the registers are
redundant, and one can be optimized out. I suspect this optimization
has to do with at which point the synthesis tool selects a clock
enabled register, with the mux built in, for MyVar. If it does it too
soon, the optimization is not available when needed.
A larger point is, do you always code to get exactly the hardware
structure you want? If I always, only coded in a manner to which any
synthesis tool would give me the exact same implementation, I'd have to
write out a structural VHDL netlist. The same issue is present when and
if you use automatic register replication, or register retiming. In
either of these cases, the hardware you envisioned to write the
description will no longer exist when those optimizations are done. My
point is the link between code and hardware is getting looser and
looser as tools advance. The only thing that remains the same is that
the synthesis tool will give you hardware which will behave the same as
the code, on a cycle by cycle basis.
Now, suppose you had written:
....
MySig <= MyVar + 1;
....
Now the two registers are not redundant, but the mux is shareable in
both places. However, for performance reasons, most synthesizers will
not share them (i.e. they'll use a clock enabled register for MyVar,
and blend the mux in with the incrementor for MySig)
I suppose if I was in the business of writing code for all kinds of
customers to use, on all kinds of tools, I'd get a lot more
conservative in my coding practices. As it is, I've had pretty good
luck getting results by telling vendor A that vendor B already does
this.
For those of you just tuning in, I realize that some, but not
all, synthesis tools support the following:
process (clk)
begin
if rising_edge(Clk) then
if (le = '1') then
MyVar := ...
end if ;
end if ;
MySig <= MyVar ;
end process ;
So personally I would not use either of the above.
Say you added the same incrementor to this one. The incrementor would
be after the MyVar register, and the assignment to MySig is
combinatorial. So MySig is now a combinatorial output from a clocked
process!
This one is handled by the tools I use, so I use it. Maybe instead of
arguing over whether it is a good idea to use it, we should be opening
up support cases with those vendors who don't support it. Again,
"...but Vendor B (Synplicity) handles this correctly" works amazingly
well! (A really sad story about "thousands of lines of code, riddled
with this stuff, works with Vendor B, but we'd like to use Vendor A's
tool, if it just worked on this code" can't hurt either.)
Andy