~~~~~~~
Form 1: Clocked process, with combinational output logic
outside the usual clocked if..else...endif block.
~~~~~~~
process(clock, reset)
variable count: unsigned(7 downto 0);
begin
-- 8-bit counter, clocked with async reset
if reset = '1' then
count := (others => '0');
elsif rising_edge(clock) then
count := count + 1;
end if;
-- Combinational logic
q <= std_logic_vector(count);
msb <= count(7);
if count = (count'range => '1') then
tc <= '1';
else
tc <= '0';
end if;
end process;
This is the form I was objecting to in an earlier post,
on the grounds that the signal assignments don't match
standard synthesis templates. EVERY ONE of the five
synthesis tools I tried gave exactly the results you
might hope for: "msb" is directly connected to count[7],
"q" is directly connected to count[7:0], "tc" is the
output of an AND gate looking at all eight bits of count.
~~~~~~~
Form 2: Clocked process, with outputs assigned based on
next-state value of counter variable.
~~~~~~~
process(clock, reset)
variable count: unsigned(7 downto 0);
begin
if reset = '1' then
count := (others => '0');
q <= std_logic_vector(count);
msb <= count(7);
if count = (count'range => '1') then
tc <= '1';
else
tc <= '0';
end if;
elsif rising_edge(clock) then
count := count + 1;
q <= std_logic_vector(count);
msb <= count(7);
if count = (count'range => '1') then
tc <= '1';
else
tc <= '0';
end if;
end if;
end process;
You'll note that this is quite a bit nastier because
it's necessary to assign to the outputs both in the
reset and in the clocked branch, otherwise the
"q" and "count" registers will have subtly different
behaviour and could not be merged.
All five tools gave correct results, but two tools
failed to merge the duplicate registers they had
created for count and q. Of course, it is entirely
possible that those duplicate registers might be
merged later, during place-and-route, as they were
indeed exact duplicates.
I'm not quite sure what to think now. Form 1 still
does not really appeal. In particular, it cannot be
reproduced in Verilog. Form 2 gives registered outputs
for everything - not even the very simplest combinational
logic between flops and outputs - and maps well to Verilog,
but it's disappointing that some tools didn't merge the
duplicate registers and there is no doubt that it's
clumsier to code, especially if there's an asynchronous
reset in the process.
One final data point: The style of asynch reset
that has been suggested here on several occasions,
allowing you to reset some but not all of a process's
registers without implying unwanted enable logic,
worked as expected in all five tools I tried:
process (clock, reset)
variable count: unsigned(7 downto 0);
begin
if rising_edge(clock) then
count_pipe <= count; -- count_pipe isn't reset
count := count + 1;
end if;
if reset = '1' then
count := (others => '0');
end if;
end process;
This form also maps happily to Verilog.
Comments welcomed.
--
Jonathan Bromley, Consultant
DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan...@MYCOMPANY.com
http://www.MYCOMPANY.com
The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
On Mon, 18 Aug 2008 16:53:12 +0100, Jonathan Bromley wrote:
> process (clock, reset)
> variable count: unsigned(7 downto 0);
> begin
> if rising_edge(clock) then
> count_pipe <= count; -- count_pipe isn't reset
> count := count + 1;
> end if;
> if reset = '1' then
> count := (others => '0');
> end if;
> end process;
>
>This form also maps happily to Verilog.
Erm, no it doesn't. Since Verilog has no rising_edge
test, you can't sensibly do this in Verilog.
Whoops.
> I have been able to try this on five different
> synthesis tools, spanning the whole range of
> cost and FPGA-vs-ASIC. The results surprised
> me a little - it's a long time since I did such
> a complete survey.
...
> Comments welcomed.
> --
Jonathan,
This is interesting, but I'm not sure exactly what conclusions to
draw. At least, no incorrect logic was generated (sighs of relief from
vendors involved). This smells like it could turn into a hunt for
cases which *do* mess up synthesizers, but that's a lot of
experimenting.
This is also interesting in that you've performed experiments, guided
by some hypotheses, and examined the results in light of those
hypotheses. Smells a bit like the scientific method to me. Clearly,
you don't get this usenet thing at all :-)
- Kenn
I can't say I follow you on this. A reset input by definition defines
the state of all registers, state and output. Why would you want to
assign the outputs to be dependant on the previous state when the
reset is asserted??? I have never done this since it was not the
desired behavior. Oh, I guess it is because you are trying to force
the use of the carry chain. Do you have any reason to believe that
this is needed? Considering that the if (count = 1's) in the reset
code is redundant (at this point count is always the value 0), this
just seems so verbose.
> All five tools gave correct results, but two tools
> failed to merge the duplicate registers they had
> created for count and q. Of course, it is entirely
> possible that those duplicate registers might be
> merged later, during place-and-route, as they were
> indeed exact duplicates.
>
> I'm not quite sure what to think now. Form 1 still
> does not really appeal. In particular, it cannot be
> reproduced in Verilog. Form 2 gives registered outputs
> for everything - not even the very simplest combinational
> logic between flops and outputs - and maps well to Verilog,
> but it's disappointing that some tools didn't merge the
> duplicate registers and there is no doubt that it's
> clumsier to code, especially if there's an asynchronous
> reset in the process.
What about form B, not using a variable since it adds nothing to the
situation and is clearly making things more difficult.
> One final data point: The style of asynch reset
> that has been suggested here on several occasions,
> allowing you to reset some but not all of a process's
> registers without implying unwanted enable logic,
> worked as expected in all five tools I tried:
>
> process (clock, reset)
> variable count: unsigned(7 downto 0);
> begin
> if rising_edge(clock) then
> count_pipe <= count; -- count_pipe isn't reset
> count := count + 1;
> end if;
> if reset = '1' then
> count := (others => '0');
> end if;
> end process;
I personally don't care for this since it is 1) complex and 2) not the
same as your other code that sets the values of the outputs.
Rick
>This is interesting, but I'm not sure exactly what conclusions to
>draw.
Me neither. I should have presented the context a little
better:
"Form 1" was, for all practical purposes, my
preferred way to write a process with internal synchronous
state that has outputs that are a function of that state,
guaranteeing that all outputs come direct from a register
with no intervening logic. There was never any doubt that
tools would generate correct logic from it, but the
description inherently creates duplicate registers and
I wanted to get a bead on whether tools would reliably
merge those duplicated registers; my (poorly documented)
experience in the past has been that it's usually OK.
The answer: some do, some don't.
"Form 2" is something I've tried before and rejected
because it doesn't follow the usual "industry standard"
synthesis coding guidelines, and is too easily abused for
my taste. However, it's come up in discussion here a few
times recently, and I wanted to take a second look at
whether it works. It is potentially a clean and convenient
way of describing the Moore-machine behaviour, but putting
some combinational logic between the internal state and
the ultimate outputs of the process. To my surprise,
all tools did The Right Thing (TM) with it.
"Form 3" was just a variant of Form 2 that I played with
while I had an example in the cooking-pot; the difference
is in the manner of describing asynchronous reset. It has
the useful property, not available with the conventional
clocked process template, that in a single process you can
describe some registers that have asynch reset and some
that don't. Again, tools are OK with it, which I wasn't
necessarily expecting.
Neither Form 2 nor Form 3 can be made to work in Verilog,
which is not good news for those of us who are bilingual.
> This smells like it could turn into a hunt for
>cases which *do* mess up synthesizers, but that's a lot of
>experimenting.
Yeah. Far too much for a non-paying project :-)
>This is also interesting in that you've performed experiments, guided
>by some hypotheses, and examined the results in light of those
>hypotheses. Smells a bit like the scientific method to me. Clearly,
>you don't get this usenet thing at all :-)
Oh, don't worry; I can do unjustified inflammatory assertion
when the need arises :-)
Thanks
>> it's necessary to assign to the outputs both in the
>> reset and in the clocked branch, otherwise the
>> "q" and "count" registers will have subtly different
>> behaviour and could not be merged.
>
>I can't say I follow you on this. A reset input by definition defines
>the state of all registers, state and output.
Not if I write a description in which some of the registers
are reset and some aren't, surely?
> Why would you want to
>assign the outputs to be dependant on the previous state when the
>reset is asserted??? I have never done this since it was not the
>desired behavior. Oh, I guess it is because you are trying to force
>the use of the carry chain.
No, nothing as smart as that. It's just a simple thing
about the usual synthesisable clocked process:
process(clk)
begin
if reset = '1' then
Q0 <= '0'; -- reset, but never clocked
Q1 <= '0'; -- reset and clocked, OK
elsif rising_edge(clk) then
Q1 <= D1; -- reset and clocked, OK
Q2 <= D2; -- clocked but never reset
end if;
end process;
The usage of Q0 and Q2 is unsatisfactory because...
- Q0 is a latch, enabled by reset, with constant input
- Q2 is a regular flop with (reset = '0') as its clock enable
So, what happens when I wish to describe some kind of pipeline
in which the first stage has an asynch reset but the later
stages do not? That's a sensible design; if you know that
the clock will tick several times during reset, then you
don't need to reset anything but the first stage of the
pipeline because all later stages will flush through
by clocked action during the reset interval. But how
to describe that? You need TWO PROCESSES, one for the
register that HAS a reset and one for the registers
that LACK a reset. Of course, synch reset doesn't suffer
this problem - you can freely apply it to individual
registers, and not to others, in a single process.
All of that was the motivation for my final example,
which you didn't like...
>> begin
>> if rising_edge(clock) then
>> count_pipe <= count; -- count_pipe isn't reset
>> count := count + 1;
>> end if;
>> if reset = '1' then
>> count := (others => '0');
>> end if;
>> end process;
> I personally don't care for this since it is 1) complex and 2) not the
> same as your other code that sets the values of the outputs.
I abbreviated the example; it could easily set outputs just as
the "Form 2" variant does. But I take the point that it is
unfamiliar (surely not really "complex"?) and, as someone else
has pointed out, it's not too nice to have a piece of code that
says Do-Lots-Of-Complicated-Stuff only to have the rug pulled out
from under you by an If-The-World-Is-About-To-End condition
right at the end of the process. It's better to know about
those global things right up front.
Of course you can define any world you wish to work in. I was
referring to the world of FPGA design. There a global async reset is
nearly always provided and needs to be specified. The standard
template is mapped to the global reset quite well by the tools. In
that context, there is no reason to leave any register uncontrolled on
reset (unless you have some very odd requirements) and failure to do
so can result in unpredictable power up behavior.
I don't have to consider the entire universe of possibilities. I just
have to consider the universe that I choose to work in and I don't
want to make my life difficult by not controlling the power up state
of registers in my design. It also helps with simulation a great
deal!
Again, you don't explain the context of your async reset. If it is
the global reset I see no reason to leave it off of any registers in
your design. A sync reset is one that is typically used at any time
during operation. The async reset is typically mapped to the global
reset. If it does not, IMHO, the async reset does not belong in a
synchronous design. I avoid the problem by avoiding it!
> All of that was the motivation for my final example,
> which you didn't like...
>
> >> begin
> >> if rising_edge(clock) then
> >> count_pipe <= count; -- count_pipe isn't reset
> >> count := count + 1;
> >> end if;
> >> if reset = '1' then
> >> count := (others => '0');
> >> end if;
> >> end process;
> > I personally don't care for this since it is 1) complex and 2) not the
> > same as your other code that sets the values of the outputs.
>
> I abbreviated the example; it could easily set outputs just as
> the "Form 2" variant does. But I take the point that it is
> unfamiliar (surely not really "complex"?) and, as someone else
> has pointed out, it's not too nice to have a piece of code that
> says Do-Lots-Of-Complicated-Stuff only to have the rug pulled out
> from under you by an If-The-World-Is-About-To-End condition
> right at the end of the process. It's better to know about
> those global things right up front.
I will point out that the above example can fail to initialize
count_pipe. The above should produce two registers and only the
first, count, will be reset. Why would you want to do that???
So I still fail to see your motivation, or at least I don't share
it.
Rick
> I can't say I follow you on this. A reset input by definition defines
> the state of all registers, state and output. Why would you want to
> assign the outputs to be dependant on the previous state when the
> reset is asserted???
Maybe I want to describe a block ram and
a lut shifter in the same process as some registers.
The registers need a reset, but the ram and
shifter can't have one.
-- Mike Treseler
Thanks for all the unbillable hours.
> All five tools gave correct results, but two tools
> failed to merge the duplicate registers they had
> created for count and q. Of course, it is entirely
> possible that those duplicate registers might be
> merged later, during place-and-route, as they were
> indeed exact duplicates.
I have yet to see a duplicate register
make it all the way through synthesis,
but they do sometimes clutter the RTL
schematic. The "odd" template seems
to tip the algorithm toward doing the
merge on the front end.
-- Mike Treseler
first off, let me say that I broadly agree with what you
say about FPGAs. But...
>I will point out that the above example can fail to initialize
>count_pipe. The above should produce two registers and only the
>first, count, will be reset.
I was careful to qualify the suggestion by noting that
there must be enough clocks during reset for the pipe
to flush. Given the way reset is likely to be managed
on an ASIC design, that is not unreasonable.
>Why would you want to do that???
In ASIC technologies, reset is not free. In the
example I gave, I need only one active clock during the
reset interval to flush the second register with the
async-reset contents of the first. That's an entirely
plausible scenario. If the downstream processing pipe
is long or wide, the area and routing resources saved
by *not* resetting it can be worth having.
>
>So I still fail to see your motivation, or at
>least I don't share it.
There are lots of ASIC designers out there....
most of the time I'm not one of them, so I
absolutely see where you're coming from. But
it's not the only point of view.
Jonathan Bromley <jonathan...@MYCOMPANY.com> writes:
>>Why would you want to do that???
>
> In ASIC technologies, reset is not free.
True in theory. But then, ASIC design rules I am familiar with require
that there be not logic in the reset tree. Put differently, a signal
declared (to the tool) as reset signal must only be connected to the
async reset input of a flip-flop. Deviations from this rule must be
justified and documented. Automatic design rule checkers must be told
to skip individual "violations".
I'd say that *unless* there is a block of significant size in which
registers don't require reset, trying to be clever is not likely to
save a lot.
Regards
Marcus
--
note that "property" can also be used as syntaxtic sugar to reference
a property, breaking the clean design of verilog; [...]
Haent had time to dig through the long converstation where this
origionated, but myself and a colleague are wondering why not use this
template instead?
process(clock, reset)
begin
if reset = '1' then
count <= (others => '0');
elsif rising_edge(clock) then
count <= count + 1;
end if;
end process
q <= count;
msb <= count(7);
tc <= '1' when (count = X"FF") else '0'; --(or just use the
"and_reduce" function).
or am I missing the point?
>Haent had time to dig through the long converstation where this
>origionated, but myself and a colleague are wondering why not use this
>template instead?
>
>process(clock, reset)
> begin
> if reset = '1' then
> count <= (others => '0');
>
> elsif rising_edge(clock) then
> count <= count + 1;
>
> end if;
> end process
> q <= count;
> msb <= count(7);
> tc <= '1' when (count = X"FF") else '0';
>or am I missing the point?
No, I don't think so. Of course you're right that
your code is the same. But it exposes the internal
state of the process ("count") as a signal that is
global to the architecture; and it splits out the
functionality into many processes. For the counter
example, none of that matters; for bigger examples,
it can have an important impact on encapsulation
and readability. I was simply seeking out viable
alternatives - and trying to find what *really*
works and doesn't work, rather than relying on
myth or (in my case) obsolete information.
> process (clock, reset)
> variable count: unsigned(7 downto 0);
> begin
> if rising_edge(clock) then
> count_pipe <= count; -- count_pipe isn't reset
> count := count + 1;
> end if;
> if reset = '1' then
> count := (others => '0');
> end if;
> end process;
We had a discussion about this style some months ago. And nobody found
any problems using this style. Unfortunately for Verilog you have to
split this process into two always-blocks.
Additionally it is a pitfall that the following process looks so similar
to your form 3, but creates the unwanted clk-enable for count_pipe:
process (clock, reset)
variable count: unsigned(7 downto 0);
begin
if reset = '1' then
count := (others => '0');
elsif rising_edge(clock) then
count_pipe <= count; -- count_pipe isn't reset
count := count + 1;
end if;
end process;
In my company we had a case where this unwanted clk-enable has caused
some trouble. Therefore form 3 should be the recommended "synchronous
template". It is so easy to forget the unwanted clk-enable - especially
if one tries to put everything into one big process.
Ralf
I can't say I understand your complaints.
"it exposes the internal state of the process ("count") as a signal
that is global to the architecture"
What is that a problem? One of the issues I have with variables is
that they are hard to debug since they can only be viewed when in
context, so I prefer a signal that is always viewable. It was a long
ago that I worked with signals and maybe the tools I used were not
very good. Has that changed?
"it splits out the functionality into many processes"
Is that really an issue? You are indicating that each concurrent
statement is a process. Why would I care about that? I use
concurrent statements freely. Is there a reason to restrict them?
I want to get work done effectively. I don't care much about finer
points of the language or simulation. I want to find ways that make
the most effective use of *my* time. I don't see how any of these
issues achieve that.
I would almost prefer a language that did not offer so much freedom.
I can't help but think this offers limited value to the coders and
makes life a lot harder for the tool writers.
Rick
I don't get it. Where is the unwanted clock enable, do you mean
"reset"?
If the tool is treating reset in this case as a clock enable, I think
you need a new tool vendor. This is the classic inferred register
model I have seen from every tool vendor I have used.
Rick
>"it exposes the internal state of the process ("count") as a signal
>that is global to the architecture"
>
>What is that a problem?
Encapsulation, and separation of concerns - all the
usual stuff that anyone needs to think about as their
designs (be they hardware, software or mechanical)
get larger.
>One of the issues I have with variables is
>that they are hard to debug since they can only be viewed when in
>context, so I prefer a signal that is always viewable. It was a long
>ago that I worked with signals and maybe the tools I used were not
>very good. Has that changed?
There's no difficulty viewing variables (at least, the static
variables that you declare in processes) in any tools I use.
Dynamically-created variables - locals of a function or procedure,
or automatics in Verilog - may require the use of breakpoints.
>"it splits out the functionality into many processes"
>
>Is that really an issue?
It's not a big deal, except that a process is (to my mind)
a block of stuff that has a life of its own; it's nice for
such blocks to be coherent and decoupled, i.e. to be as
far as possible related to one set of concerns and to
be a complete implementation of that set of concerns.
Inevitably in hardware that ideal is unrealizable, but
it's still worth fighting for.
Speaking of "blocks", of course the (very under-utilised)
VHDL "block" construct allows you to group a bunch of
processes, and the signals that link them, without
requiring a module (entity) to encapsulate them.
>I want to get work done effectively. I don't care much about finer
>points of the language or simulation. I want to find ways that make
>the most effective use of *my* time. I don't see how any of these
>issues achieve that.
I am very well aware that you are experienced and productive,
so I think it's best for us to agree to differ here and for
me to note the very interesting fact that different people
think about these issues in very different ways.
>I would almost prefer a language that did not offer so much freedom.
>I can't help but think this offers limited value to the coders and
>makes life a lot harder for the tool writers.
Again, perhaps we should agree to differ.
Thanks.
>> process (clock, reset)
>> variable count: unsigned(7 downto 0);
>> begin
>> if reset = '1' then
>> count := (others => '0');
>> elsif rising_edge(clock) then
>> count_pipe <= count; -- count_pipe isn't reset
>> count := count + 1;
>> end if;
>> end process;
>I don't get it. Where is the unwanted clock enable, do you mean
>"reset"?
"reset" is a clock DISABLE for the count_pipe register.
Think about what happens when there's a rising edge on
clock at a time when reset is held asserted. We activate
the process, but we test reset and find it is '1' so we
do the reset branch of the logic; this has no effect on
count_pipe, which therefore holds its value.
>If the tool is treating reset in this case as a clock enable, I think
>you need a new tool vendor. This is the classic inferred register
>model I have seen from every tool vendor I have used.
No, it's not. It's my favourite RTL coding error, in which
I add a register to the clocked logic in a process but then
forget to add it to the reset branch because it doesn't
seem to need resetting from a functional point of view.
If the tool did NOT treat "not reset" as a clock enable on
the count_pipe register, it would be generating logic that
behaved differently from the simulation - and that WOULD be
cause for a bug report.
Naturally, none of this weakens the arguments that you have
already presented for resetting every register in an FPGA
design.
Hierarchy in VHDL is best expressed at the entity level, not process
or procedure. As the design gets larger and it becomes apparent that
a different (or simply finer grained) breakdown is needed, that should
be accomplished by creating new entities. That's where the
encapsulation and separation of concerns should occur.
Entity/architectures can also generally be reused in some new
application without modification, processes and procedures generally
can not since they usually need the context that is provided by the
entity/architecture.
> >One of the issues I have with variables is
> >that they are hard to debug since they can only be viewed when in
> >context, so I prefer a signal that is always viewable. It was a long
> >ago that I worked with signals and maybe the tools I used were not
> >very good. Has that changed?
>
> There's no difficulty viewing variables (at least, the static
> variables that you declare in processes) in any tools I use.
You can't view variables in a wave or list windows after the fact
using Modelsim.
When something fails in any simulation, the reason for the failure
many time is in the past, although sometimes the reason is in the
present. The wave and list windows are the available tools for
investigating what happened prior to the failure in order to discern
what was the root cause. When you use variables extensively you lose
at least some of the ability to use those tools to debug. Given that
handicap you must turn to other methods such as re-running the
simulation to either step through code, or add the variables that
you'd like to see to the wave/list windows at sim start (hoping you've
guessed correctly at all of the ones you need). At best you're only
slightly less productive because of this handicap.
Modelsim's log -r /* command is a very powerful debug aid...it get
signals, it doesn't pick up variables.
> Dynamically-created variables - locals of a function or procedure,
> or automatics in Verilog - may require the use of breakpoints.
>
Again, the use of breakpoints implies that the simulation was
restarted so that one can get visibility into what led up to the bad
thing. This starts to happen when the use of variables and procedures
has clouded things to the point that one can not easily discern what
is going wrong given the available information (which is the entire
'signal' history). Don't get me wrong, I do like variables and
procedures, but whenever possible I'll use a signal instead of a
variable simply for the debug value.
> >"it splits out the functionality into many processes"
>
> >Is that really an issue?
>
> It's not a big deal,
Whew, I was wondering if someone was charging you a fee per process or
something.
> except that a process is (to my mind)
> a block of stuff that has a life of its own; it's nice for
> such blocks to be coherent and decoupled,
Coherent yes, decoupled no. Anything that is decoupled from the rest
of the world is not needed (and a synthesis tool will see to that by
optimizing it away). I realize that this extreme of 'decoupled' is
more decoupled than what you likely had in mind, but my point is that
every process interacts with some input stimulus and provides some
output. It interacts with and is therefore coupled to other things.
What one really wants to have is good interfaces between these hunks
of code (be they multiple processes or multiple entities) rather than
some unachievable decoupling. Personally I prefer Altera's Avalon
specification as a model interface to use, it provides for
handshaking, latency, etc. at a zero (or minimal) logic resource
overhead.
> i.e. to be as
> far as possible related to one set of concerns and to
> be a complete implementation of that set of concerns.
> Inevitably in hardware that ideal is unrealizable, but
> it's still worth fighting for.
>
But the reason it's unrealizable is because of what I just mentioned
above regarding interfaces. Given that every useful process will have
some interface to other surrounding code I don't see what the cause is
that you would be 'fighting for'.
Within an entity, I tend to have multiple clocked processes and
concurrent statements. The physical grouping of what signals go in
this clocked process versus that clocked process has to do with how
closely related the logic is that is required to implement that
signal. Things that are unrelated go in separate processes. I'll
also tend to try to limit the physical size of a process so that it
fits on a screen. The end result is a file where you don't have to
scroll back and forth and all around in order to see what is going
on. During the design process where you're still working on what the
actual logic is, things can freely move (by cut/paste) from one
process to another as the realization sets in that the logic for
signal 'abc' is very similar after all to that which I have for
'xyz'. This type of situation is also where the limited use of
variables is a good thing since I can freely move and modify the code
from one process to the other to textually group together the related
stuff because, when the code being moved only uses signals, that cut/
paste can always be safely done without mucking up something else in
the process that it was cut from.
> Speaking of "blocks", of course the (very under-utilised)
> VHDL "block" construct allows you to group a bunch of
> processes, and the signals that link them, without
> requiring a module (entity) to encapsulate them.
>
I agree, and would add that the same can also be said for the generate
statement...both quite handy ways to create 'local' signals.
>
> >I would almost prefer a language that did not offer so much freedom.
> >I can't help but think this offers limited value to the coders and
> >makes life a lot harder for the tool writers.
>
> Again, perhaps we should agree to differ.
>
I agree with you (Jonathon). The more skilled you get with VHDL, the
more you appreciate all the things that they thought to include (but
you still gripe about the odd constraints).
Abel is a simple language to learn and use but I wouldn't use it today
because VHDL provides much more power for creating not only a design
but a self checking testbench of the design within a single language
environment. That design and testbench can also be as fully
parameterized as I would like it so that they can be reused for some
other project down the road.
Kevin Jennings
I rarely use async resets at all and wouldn't really use any of these
forms sticking instead with the simple synchronous process form
(putting the "if (reset = '1') then..." at the top for readability).
The one exception for async resets being the shift register(s) that
take as input the external reset pin and from that generate a reset
signal that is synchronous to any clock(s). Using a reset signal that
is not synchronized to the clock is a design failure waiting to
happen.
>
> Again, you don't explain the context of your async reset. If it is
> the global reset I see no reason to leave it off of any registers in
> your design.
I'd turn it around and say that if there is no functional requirement
to reset a register than don't bother spending the time and adding the
extra code to do so.
Most registers (by quantity) in a design do not have such a
requirement since they hold data and do not control anything. Signals
that control other things (like an 'enable' bit that turns on/off some
function, a state machine) do need resets.
> A sync reset is one that is typically used at any time
> during operation. The async reset is typically mapped to the global
> reset. If it does not, IMHO, the async reset does not belong in a
> synchronous design. I avoid the problem by avoiding it!
>
You're right when you say "the async reset does not belong in a
synchronous design"...but I would say that the only exceptions to that
being
- The reset synchronizer
- Any output pins of the top level design that require a specific
power up state prior to having a good clock.
Kevin Jennings
Does this go further into the variable vs signal argument? The same
colleague at work also says your Form 1 was a bad practice form of
code, because variables should never be used to store values between
clock cycles, and should only be used as logic, with the argument that
its just a danger synthesisers may not pick it up as such. He cited an
example of an old collegue (at another company) used to use variables
for starage often with less use of signals. This ran him into bother
after synthesis. Is this just old worrys? or was it more likely that
this person was probably just writing bad code?
If you don't use async resets, then you don't use FPGAs, at least none
that I am aware of. FPGAs have a global set/reset signal that
initializes the FFs on power up. You don't have to drive it with your
own signal, but it is active regardless of your code. But if you want
to control the state of the FF on power up, then you need to use a
register template with an async reset.
The shift register you describe driving a synchronous reset is what I
use, except I use it to drive the async reset. Since the output of
the shift register is sync'd to the clock, it will not cause
problems. It also does not use any extra resources since it will be
mapped to the dedicated GSR signal in the FPGA.
> > Again, you don't explain the context of your async reset. If it is
> > the global reset I see no reason to leave it off of any registers in
> > your design.
>
> I'd turn it around and say that if there is no functional requirement
> to reset a register than don't bother spending the time and adding the
> extra code to do so.
>
> Most registers (by quantity) in a design do not have such a
> requirement since they hold data and do not control anything. Signals
> that control other things (like an 'enable' bit that turns on/off some
> function, a state machine) do need resets.
But you are ignoring that the register *has* an async reset whether
you choose to control it or not.
> > A sync reset is one that is typically used at any time
> > during operation. The async reset is typically mapped to the global
> > reset. If it does not, IMHO, the async reset does not belong in a
> > synchronous design. I avoid the problem by avoiding it!
>
> You're right when you say "the async reset does not belong in a
> synchronous design"...but I would say that the only exceptions to that
> being
> - The reset synchronizer
> - Any output pins of the top level design that require a specific
> power up state prior to having a good clock.
You seem to ignore my point which is about the GSR signal.
Rick
Not exactly. Yes, the GSR is there, but you do not have to use the
async reset template to get controlled initialization at power up.
Constraints can be used, and some synthesis tools are using initial
value specifications to drive it.
I generally have to use an async reset since I usually have
requirements to safe the outputs in response to a external reset
input, even in the absence of a clock, well-behaved or not.
Additionally, GSR is only used for the most common clock domain in the
design. The other clock domains must have a reset synchronized
(deasserting edge only!) to their clock, and must use other means of
distribution.
Andy
Hierarchy is best expressed wherever you can express it. Decoupling /
information hiding is not an all or nothing affair. Of course, a
completely decoupled/hidden process is an absurdly useless
extrapolation, but there is tremendous value in restricting the scope
of access to information to those areas where it is really needed.
Using variables inside processes allows you to do that, while still
using signals to communicate between processes. Relying solely on the
entity for hierarchy leads to too many files (since most organizations
restrict designs to one entity/architecture per file) to reach the
same level of decoupling that variables in processes give you. A side
benefit of variables is that their definition is located within the
process where they are used, preventing needless scrolling up to the
architecture declarative region and back to the process of interest
while reviewing the code.
Block statements can be used to provide a similar level of hierarchy
(and locality of definition in the file), while preserving the comfort
of signal behavior for those that want it. I think they would be a
good idea for designers to "get their feet wet" in decoupling/hiding
without also having to deal with variables.
Those that wish for less freedom in an HDL are free to limit
themselves to whatever subset of the language they choose, but for
many of us, descriptive styles that allow abstraction above the level
of gates and registers are very useful. Given available optimizations
such as register retiming, etc., carefully crafted circuit
descriptions that attempt to define precise sequences of gates and
registers become useless in the face of the final implementation.
Sure, their clock cycle behavior is retained, but what exactly is that
behavior? I'd rather use a style that describes the behavior in the
first place, since that is the only thing that is sure to be preserved
in the implementation.
Andy
On the other hand log -r /* can slow down the simulations so much,
that it is more reasonable to rerun the simulation with the same
seed values for the testbench, and recreate the situation that was
visible in the regressions. The impact for productivity is even
bigger if the regressions can not be run during the night. Also I
once calculated that dumping all signals for one regression run would
have created about terabyte of data, that puts quite hard load to
fileservers and network.
Yes, I agree that variables are sometimes painful and make debugging
much harder, but on the other hand they help to make cleaner code
usually that is easier to read.
>> Dynamically-created variables - locals of a function or procedure,
>> or automatics in Verilog - may require the use of breakpoints.
>
> Again, the use of breakpoints implies that the simulation was
> restarted so that one can get visibility into what led up to the bad
> thing. This starts to happen when the use of variables and procedures
Also it might imply that the problem is in testbench, where more
abstract way of programming is usually a good thing. In SW side use
of debugger is normal way of finding problems. I use regulary
breakpoints in testbench side, because complex algorithms are not
always easy to follow without stepping trough them.
>> Speaking of "blocks", of course the (very under-utilised)
>> VHDL "block" construct allows you to group a bunch of
>> processes, and the signals that link them, without
>> requiring a module (entity) to encapsulate them.
>
> I agree, and would add that the same can also be said for the generate
> statement...both quite handy ways to create 'local' signals.
Sometimes complex generates and configurations can generate code
that is almost impossible to read and understand. It is not
always the original coder that has to debug the problems and fix them.
Too clever code usually becomes a problem later on, either it
is hard to fix, or it breaks tools. Many hot and new tools have
quite weak VHDL parser.
> Abel is a simple language to learn and use but I wouldn't use it today
> because VHDL provides much more power for creating not only a design
> but a self checking testbench of the design within a single language
> environment.
It's interesting to see what happens when now SystemVerilog has more
fancy features than VHDL. How much of the market and mindshare will
it capture. Will we see more and more for example designs where the
design is VHDL and the testbench is SV.
--Kim
There have been problems like that in the past. But I have seen designs
that use heavily variables for storage and they have worked just fine
with modern tools. If you are not using retiming current tools are
quite safe with different structures. But with retiming I have seen
some synthesis bugs, and they have been more in the codes that use
heavily variables. But those codes were also relying heavily on
retiming to balance their pipelines, so the code was also much more
heavily modified by the tool.
--Kim
Of course with FPGAs also initial values can be used and then no reset
is connected to the FF. The initial value comes from the configuration
file in that case.
> own signal, but it is active regardless of your code. But if you want
> to control the state of the FF on power up, then you need to use a
> register template with an async reset.
Not always. You can also use the FFs without any reset and give initial
values for the signals. Most synthesizers can transfer those values
to configuration image.
> The shift register you describe driving a synchronous reset is what I
> use, except I use it to drive the async reset. Since the output of
> the shift register is sync'd to the clock, it will not cause
> problems. It also does not use any extra resources since it will be
> mapped to the dedicated GSR signal in the FPGA.
It might cause problems, because the internal global reset lines inside
FPGA are quite slow. And the signal might not propagate trough the FPGA
during one clock cycle. I have seen problems with this kind of reset
style, the design locked once every 100 startups. The cause was that on
some one-hot statemachines the FFs got reset deasserted on different
clock cycles, and there was no guard logic in the state machines to get
out from that situation.
--Kim
> Yes, I agree that variables are sometimes painful and make debugging
> much harder, but on the other hand they help to make cleaner code
> usually that is easier to read.
...and less likely to have a logical error in the first place.
-- Mike Treseler
> On Aug 20, 6:00 am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
> wrote:
>> On Tue, 19 Aug 2008 14:29:55 -0700 (PDT), rickman wrote:
>> >One of the issues I have with variables is
>> >that they are hard to debug since they can only be viewed when in
>> >context, so I prefer a signal that is always viewable. It was a long
>> >ago that I worked with signals and maybe the tools I used were not
>> >very good. Has that changed?
>>
>> There's no difficulty viewing variables (at least, the static
>> variables that you declare in processes) in any tools I use.
>
> You can't view variables in a wave or list windows after the fact
> using Modelsim.
>
In defence of variables, you can view them when you've added them to
the wave before you start. When I start debugging an entity, I
usually just add all its various variables to a wave window at the
start.
> When something fails in any simulation, the reason for the failure
> many time is in the past, although sometimes the reason is in the
> present. The wave and list windows are the available tools for
> investigating what happened prior to the failure in order to discern
> what was the root cause. When you use variables extensively you lose
> at least some of the ability to use those tools to debug. Given that
> handicap you must turn to other methods such as re-running the
> simulation to either step through code, or add the variables that
> you'd like to see to the wave/list windows at sim start (hoping you've
> guessed correctly at all of the ones you need). At best you're only
> slightly less productive because of this handicap.
For the vast majority of my simulations, re-running the sim takes a
matter of seconds if I forget to add the signals to the wave window.
Problems that a "whole-FPGA" problems usually come down to signals anyway.
>
> Modelsim's log -r /* command is a very powerful debug aid...it get
> signals, it doesn't pick up variables.
>
It would be nice if it did :) Maybe some TCL could help here... hmm...
<snip>
> Within an entity, I tend to have multiple clocked processes and
> concurrent statements. The physical grouping of what signals go in
> this clocked process versus that clocked process has to do with how
> closely related the logic is that is required to implement that
> signal. Things that are unrelated go in separate processes. I'll
> also tend to try to limit the physical size of a process so that it
> fits on a screen. The end result is a file where you don't have to
> scroll back and forth and all around in order to see what is going
> on. During the design process where you're still working on what the
> actual logic is, things can freely move (by cut/paste) from one
> process to another as the realization sets in that the logic for
> signal 'abc' is very similar after all to that which I have for
> 'xyz'. This type of situation is also where the limited use of
> variables is a good thing since I can freely move and modify the code
> from one process to the other to textually group together the related
> stuff because, when the code being moved only uses signals, that cut/
> paste can always be safely done without mucking up something else in
> the process that it was cut from.
Except when you forget to move the reset clause for a signal - then
you have two processes driving it. But that's what std_ulogic is for :)
<snip>
>>
>> >I would almost prefer a language that did not offer so much freedom.
>> >I can't help but think this offers limited value to the coders and
>> >makes life a lot harder for the tool writers.
>>
>> Again, perhaps we should agree to differ.
>>
>
> I agree with you (Jonathon). The more skilled you get with VHDL, the
> more you appreciate all the things that they thought to include (but
> you still gripe about the odd constraints).
>
> Abel is a simple language to learn and use but I wouldn't use it today
> because VHDL provides much more power for creating not only a design
> but a self checking testbench of the design within a single language
> environment. That design and testbench can also be as fully
> parameterized as I would like it so that they can be reused for some
> other project down the road.
That get's my agreement too!
Cheers,
Martin
--
martin.j...@trw.com
TRW Conekt - Consultancy in Engineering, Knowledge and Technology
http://www.conekt.net/electronics.html
People keep saying this, but I have not seen one example. Can anyone
come up with a compelling example of why we should suffer the use of
variables in our code?
Rick
But this requires the global set reset signal. That is how the FFs
get their initial state.
> > own signal, but it is active regardless of your code. But if you want
> > to control the state of the FF on power up, then you need to use a
> > register template with an async reset.
>
> Not always. You can also use the FFs without any reset and give initial
> values for the signals. Most synthesizers can transfer those values
> to configuration image.
I don't think this is the rule. If you want to write portable code,
you need to use a reset as part of the clocked process.
> > The shift register you describe driving a synchronous reset is what I
> > use, except I use it to drive the async reset. Since the output of
> > the shift register is sync'd to the clock, it will not cause
> > problems. It also does not use any extra resources since it will be
> > mapped to the dedicated GSR signal in the FPGA.
>
> It might cause problems, because the internal global reset lines inside
> FPGA are quite slow. And the signal might not propagate trough the FPGA
> during one clock cycle. I have seen problems with this kind of reset
> style, the design locked once every 100 startups. The cause was that on
> some one-hot statemachines the FFs got reset deasserted on different
> clock cycles, and there was no guard logic in the state machines to get
> out from that situation.
Maybe if you are running at 200 MHz. There are always speed issues in
any design. That is why you use timing constraints. You do use
timing constraints, right?
Rick
>>
>> You'll note that this is quite a bit nastier because
>> it's necessary to assign to the outputs both in the
>> reset and in the clocked branch, otherwise the
>> "q" and "count" registers will have subtly different
>> behaviour and could not be merged.
>
>I can't say I follow you on this. A reset input by definition defines
>the state of all registers, state and output. Why would you want to
>assign the outputs to be dependant on the previous state when the
>reset is asserted??? I have never done this since it was not the
>desired behavior.
One reason (not the case in this example): a very long delay line,
containing delayed state (to be used when a slow operation started by
the main state machine has completed). You can either reset this along
with the main state, or simply let its inputs ripple through. The latter
can be implemented at 16 bits per LUT in SRL16s for Xilinx, saving
several hundred FFs. The former can't, because the SRL16s don't have the
necessary reset connections.
- Brian
No, implementing an initial value does not require *any* signal in the
design source files. Maybe we're delving into an area where the tools
that you're using don't (or you think they don't) support initial
values in the source code or something and in order to get those
intial values that tools requires you to code it as if it was an async
reset.
If xyz is a flip flop output and one can say...
signal xyz: std_ulogic := '1';
and signal xyz gets initialized at configuration time then the tools
support the VHDL language standard as it applies to defining initial
values.
If instead you have to say...
if (Reset = '1') then
xyz <= '1';
...
in order to get xyz initialized at configuration time then the tools
do not support the VHDL language standard as it applies to defining
initial values and the above code is the work around that might
help...but still it's a work around to a tool limitation, not some
fundamental principle.
> > > own signal, but it is active regardless of your code. But if you want
> > > to control the state of the FF on power up, then you need to use a
> > > register template with an async reset.
>
> > Not always. You can also use the FFs without any reset and give initial
> > values for the signals. Most synthesizers can transfer those values
> > to configuration image.
>
> I don't think this is the rule. If you want to write portable code,
> you need to use a reset as part of the clocked process.
>
Not really. If you're talking about portability to tools that don't
support initial value specification then you could still find yourself
at the mercy of having to supply an external I/O pin to ultimately
give you the reset at the end of configuration. Now this tool
limitation work around is requiring additional PCBA support that would
not otherwise be required.
Obviously all this only applies to devices that have a defined powerup/
end configuration state available but which *tools* don't support
initial value specification now-a-daze?
KJ
"We" have already given several examples that are compelling to many
of us:
Ease of discerning cycle based behavior from the code
Decoupling, etc. without resorting to separate files/entities/
architectures
Proximity of the variable definition to where it is used
Simulation efficiency
Apparently these are not compelling reasons to you, and you are free
to limit your use of the VHDL language and tool capabilities
accordingly.
Andy
> Ease of discerning cycle based behavior from the code
The 'ease of discerning' depends much on the skill of the person
writing the code, not whether or not variables were used.
> Decoupling, etc. without resorting to separate files/entities/
> architectures
Decoupling and hierarchy has nothing to do with the use of variables.
If you don't like the typing overhead of separate entities to express
hierarchy (a valid complaint for some) you're free to express
hierarchy within a block or generate statement and keep it all in one
file...the amount of typing would be the same (slightly less I guess
since 'block' is a shorter word than 'process').
If your point here though was that keeping things (in this case
variables) invisible outside of the scope of the process then this is
exactly analogous to keeping other things (in this case signals) local
to a block or generate...and inside that block you can still plop down
a process with its variables if you so choose. Processes are
handicapped in that they can not define a local signal if needed so
you're forced to use variables to keep it local.
> Proximity of the variable definition to where it is used
The proximity of a variable definition to it's use is identical to
that of a signal definition within a block to it's point of use.
> Simulation efficiency
I measured ~10-15% a while back...so that's one advantage.
> Apparently these are not compelling reasons to you, and you are free
> to limit your use of the VHDL language and tool capabilities
> accordingly.
You listed four reasons, only one of which is a valid advantage (which
in turn must be balanced against the disadvantages previously
mentioned).
@Rick
Where I tend to use variables in synthesis is where the logic to
express the function is best handled with sequential statements (i.e.
'if', 'case', etc.) and I don't want to bother writing it as a
function for whatever reason so that I could use the function output
in a concurrent signal assignment.
The other case I would use variables in synthesis is to compute some
intermediate thing which, if I didn't do it that way, would result in
basically copy/pasting code, or otherwise cluttering up the source
code...in other words, use of the variable becomes much like a
shorthand notation.
The biggest place I find for variables though has to be in the
testbench code where I model the various widgets on the board and
where synthesizability (if that's a word) is not a concern.
The 'compelling example' is only something that you find compelling.
Variables are just a tool in the toolkit for getting the job done.
Like any tool they can be used well or misused. The quality/
readability/*-ity of the resulting code that pops out depends solely
on the skill and knowledge of the designer. Being limited in either
area reduces the *-ity measure.
KJ
> Can anyone
> come up with a compelling example of why we should suffer the use of
> variables in our code?
Let say I want to describe a phase accumulator
in the traditional manner.
With a mult-process design, I might
say something like:
accum_s <= '0' & accum_s(accum_s'length - 2 downto 0)
+ ('0' & addend_c);
in one process and pick up the
output msb in another process:
msb <= accum_s(accum_s'length - 1);
Thats not too bad, but it's pretty easy
to get a count or length off by one.
I prefer a single process description
like this that does exactly the same thing.
...
accum_v := accum_v + addend_c; -- add magic number
msb_v := accum_v(accum_v'length-1); -- save the carry bit
accum_v(accum_v'length-1) := '0'; -- clear carry for next time
...
-- Now use msb_v however I like down here ...
To me, there is no comparison.
It's like calculus vs Laplace transforms.
--Mike Treseler
I have no idea why you would use two processes for the above??? At
first I thought that maybe you were assigning msb in a concurrent
assignment so that it would not be registered. But in the example
below you are assigning it in a clocked process.
So what is the basis for using two processes above and one below???
> I prefer a single process description
> like this that does exactly the same thing.
> ...
> accum_v := accum_v + addend_c; -- add magic number
> msb_v := accum_v(accum_v'length-1); -- save the carry bit
> accum_v(accum_v'length-1) := '0'; -- clear carry for next time
> ...
> -- Now use msb_v however I like down here ...
>
> To me, there is no comparison.
> It's like calculus vs Laplace transforms.
Yes, it would appear that, to you, there are a lot of things that I
can't see. For example, I can't see how you would make use of a
variable outside of the process it is defined in. Or is "down here"
still inside the process?
Andy seems to think I am being silly or argumentative or whatever.
But I maintain that no one in this discussion has actually explained
how the use of variables provides any advantage. Andy just keeps
waving his arms around saying "Decoupling" and "Proximity" without
actually explaining how any of this is worth the extra trouble using
variables. You have given an incomplete example that does not clearly
show your point.
Why is your point so hard to explain?
Rick
I am not aware that initial values of signals is part of a VHDL
standard for synthesis. In fact, I was under the impression that
there is no "standard" for what parts of the language were supported
for synthesis. Am I wrong about this? Are initial value assignments
a required construct for synthesis support? I know they have not been
historically.
> > > > own signal, but it is active regardless of your code. But if you want
> > > > to control the state of the FF on power up, then you need to use a
> > > > register template with an async reset.
>
> > > Not always. You can also use the FFs without any reset and give initial
> > > values for the signals. Most synthesizers can transfer those values
> > > to configuration image.
>
> > I don't think this is the rule. If you want to write portable code,
> > you need to use a reset as part of the clocked process.
>
> Not really. If you're talking about portability to tools that don't
> support initial value specification then you could still find yourself
> at the mercy of having to supply an external I/O pin to ultimately
> give you the reset at the end of configuration. Now this tool
> limitation work around is requiring additional PCBA support that would
> not otherwise be required.
If you want your part to come out of configuration cleanly, then you
have to provide a way to synchronizing the end of the internal reset
to the system clock. I have yet to find a way to do this without
proving that external reset pin, even if it is just tied high (or
low).
Maybe the perceived problem of synchronizing the end of reset is a red
herring. I have never seen a problem with it. But if you consider
how FSM and counters work, it is entirely possible that they will not
start up properly when reset in the default async manner.
> Obviously all this only applies to devices that have a defined powerup/
> end configuration state available but which *tools* don't support
> initial value specification now-a-daze?
That has been a large number of tools and FPGA devices by my
experience. Can you state that there are no tools that don't support
this feature?
Rick
Ok, so how does that relate to the issue of using variables?
Rick
> I have no idea why you would use two processes for the above???
I wouldn't.
I assumed that others would.
How would you do it?
> Yes, it would appear that, to you, there are a lot of things that I
> can't see. For example, I can't see how you would make use of a
> variable outside of the process it is defined in. Or is "down here"
> still inside the process?
Yes. Sorry but I can't publish this entire entity.
See my published examples for simpler cases.
> Why is your point so hard to explain?
I don't know.
My preference is based on writing shell scripts, C and python.
-- Mike Treseler
> "We" have already given several examples that are compelling to many
> of us:
>
> Ease of discerning cycle based behavior from the code
> Decoupling, etc. without resorting to separate files/entities/
> architectures
> Proximity of the variable definition to where it is used
> Simulation efficiency
All true, but I'm missing the most important point: the difference
in semantics between signals and variables.
There are things you can do with variables that you cannot easily
accomplish with signals. So they add another dimension to the game.
In particular, in a clocked process the same variable can be used
both "combinatorially" and "as a register". Once you get that,
the opportunities for elegant HDL solutions for real problems
pop up everywhere.
I consider register inference from variables the most powerful
tool in the RTL toolbox - however it is poorly understood and
probably banned in a majority of design teams.
http://myhdl.jandecaluwe.com/doku.php/cookbook:jc2
Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
Not to mention poorly supported compared to signals, both in
simulation and synthesis. If you use variables, you will see more
bugs and limitations of the tools. Why? I guess because it is just
not as mainstream. Kinda like driving a Maserati for the daily
commute.
Rick
Well, that makes sense. If you are used to writing software, then you
will be more comfortable with variables. I have a much stronger
hardware background. I design my hardware in block diagrams, tables
and state charts before I write any code (if needed). I then write
the code that describes the registers and logic. I take the D in HDL
literally (hardware Description language) and use the language to
describe the hardware I want. I actually did not get a job offer
once because I said that I code RTL. One of the lead engineers felt
very strongly that this was too inefficient to be effective and
blackballed an offer. Funny, I seem to be doing just fine on the
engineering side of things. I wish I had a business manager though.
This is in the clocked process
accum_v <= accum_v + addend_c;
This is a concurrent statement
msb_v <= accum_v(accum_v'high);
I don't recall needing this in a phase accumulator. Isn't the top bit
just your output signal? The NCOs I have written were producing a
digital output of 1 bit for use as a clock. Otherwise, why would you
need the carry? Actually, I didn't use the carry out. I used the
msb. Maybe I don't understand what you are doing with this.
accum_v(accum_v'length-1) := '0'; -- clear carry for next time
I guess my way uses an extra bit in the accumulator, one more than you
have in the phase increment register. You look at this as saving the
"carry" bit. But I don't get why you don't retain the carry bit into
the sum. But then it has been a while since I have done an NCO.
Maybe I am forgetting some things. BTW, "clearing" the carry can be
done in the sum if you really need to.
accum_v <= '0' & accum_v(accum_v'high-1 downto 0) + addend_c;
But where did the extra bit in the addend_c come from? Do you have a
bit in the addend that is never set?
Rick
> On Aug 22, 6:19 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:
>>
>> I consider register inference from variables the most powerful
>> tool in the RTL toolbox - however it is poorly understood and
>> probably banned in a majority of design teams.
>
> Not to mention poorly supported compared to signals, both in
> simulation and synthesis.
I really can't imagine a modern simulator not supporting variables to
spec, surely! That would be just plain broken!
> If you use variables, you will see more bugs and limitations of the
> tools. Why? I guess because it is just not as mainstream. Kinda
> like driving a Maserati for the daily commute.
>
I've never seen a variable-related bug in my time. In the old days
there we *limitations*, but I haven't come across any of those
recently either in the tools I use. And I use a *lot* of variables
(and records, and procedures within processes, and all sorts of other
things that didn't used to work, but make my life easier *now*).
YMMV however :)
That would be a counter Q type output.
I need to enable a prescaler with a carry-out.
By saving the bit before clearing it
I have exactly what I need and synthesis
does a fine job with the carry chain details.
I guess the advantage I see with variables
is this ability to build up the values
I need in sequential steps and to make
the computer do more of the detail work.
-- Mike Treseler
> On Aug 21, 7:27 am, rickman <gnu...@gmail.com> wrote:
> > On Aug 21, 2:52 am, Mike Treseler <miket_trese...@comcast.net> wrote:
> > > Kim Enkovaara wrote:
> > > > Yes, I agree that variables are sometimes painful and make debugging
> > > > much harder, but on the other hand they help to make cleaner code
> > > > usually that is easier to read.
> > > ...and less likely to have a logical error in the first place.
> > > -- Mike Treseler
> > People keep saying this, but I have not seen one example. Can anyone
> > come up with a compelling example of why we should suffer the use of
> > variables in our code?
> > Rick
> "We" have already given several examples that are compelling to many
> of us:
> Ease of discerning cycle based behavior from the code
The 'ease of discerning' depends much on the skill of the person
writing the code, not whether or not variables were used.
> Decoupling, etc. without resorting to separate files/entities/
> architectures
Decoupling and hierarchy has nothing to do with the use of variables.
If you don't like the typing overhead of separate entities to express
hierarchy (a valid complaint for some) you're free to express
hierarchy within a block or generate statement and keep it all in one
file...the amount of typing would be the same (slightly less I guess
since 'block' is a shorter word than 'process').
If your point here though was that keeping things (in this case
variables) invisible outside of the scope of the process then this is
exactly analogous to keeping other things (in this case signals) local
to a block or generate...and inside that block you can still plop down
a process with its variables if you so choose. Processes are
handicapped in that they can not define a local signal if needed so
you're forced to use variables to keep it local.
> Proximity of the variable definition to where it is used
IEEE 1076.6
http://www.google.com/search?hl=en&q=vhdl+1076.6
KJ
That's interesting. I did some Xilinx work recently, and reluctantly had
to change my code. I used variables for the sake of 'localization' - the
Xilinx simulator simulated it correctly, but XST gave me some warnings and
indeed when I scoped related outputs from the FPGA, some of the logic
related to the variables had been removed in line with the warnings.
My variable use was pretty simple - slv set in an async reset block and at
the end of the clocked part of the process, and used only in the clocked
part. I couldn't see anything wrong with it, and neither could the
simulator.
Regards,
Paul.
> Not to mention poorly supported compared to signals, both in
> simulation and synthesis. If you use variables, you will see more
> bugs and limitations of the tools. Why? I guess because it is just
> not as mainstream. Kinda like driving a Maserati for the daily
> commute.
If the tools don't support variables then I find that rather frustrating,
and using your car analogy, consider them old skoda style.
Regards,
Paul.
> That's interesting. I did some Xilinx work recently, and reluctantly had
> to change my code. I used variables for the sake of 'localization' - the
> Xilinx simulator simulated it correctly, but XST gave me some warnings and
> indeed when I scoped related outputs from the FPGA, some of the logic
> related to the variables had been removed in line with the warnings.
Post the code and I'll have a look.
Did you miss a port assignment?
There are many reasons that synthesis may remove logic
and none that I know of have to do with variables vs signals.
My examples here:
http://mysite.verizon.net/miketreseler/
use variables exclusively, and work fine with xst.
-- Mike Treseler
I'll have access to the code again next week - I'll have another look at
it and post it.
Thanks,
Paul.
No it does not. The FF state is set via the SRAM configuration cells
during the chip powerup.
>> Not always. You can also use the FFs without any reset and give initial
>> values for the signals. Most synthesizers can transfer those values
>> to configuration image.
>
> I don't think this is the rule. If you want to write portable code,
> you need to use a reset as part of the clocked process.
For portable code that works also with ASICs the reset signal is almost
mandatory. But for pure FPGAs the initial values can be used, and
for fast designs they save routing resources.
And and least Synplify supports initial values in signals and memories,
if the used FPGA also supports them. And most of the FPGA families
support setting of the initial value of FF, and also in many families
the memory contents can be set to predefined values.
>> It might cause problems, because the internal global reset lines inside
>> FPGA are quite slow. And the signal might not propagate trough the FPGA
>>...
> Maybe if you are running at 200 MHz. There are always speed issues in
> any design. That is why you use timing constraints. You do use
> timing constraints, right?
Usually if you put timing constraint to the synchronous reset it pops
out from the global line, because it is too slow. And also for multiple
clock domains reset networks in normal routing are needed. I have
sometimes asked from the FPGA manufacturers if they could build global
resets that are fast, and can be split to create many clock domains.
After that they would be more useful, single clock domain designs are
quite rare at least in telecommunication side.
--Kim
You are confused. The FFs do not have SRAM configuration cells that
set the initial state of the FF. The configuration memory sets the
select lines on a number of multiplexers in the logic cell as well as
other control points that remain fixed throughout the life of a given
configuration. They also control the routing elements outside the
logic cell. Finally, they *are* the LUT (along with some pass
transistors) that determines the logic. But there is no configuration
ram that sets the initial state of the FFs in the logic cells of a
Xilinx, Altera or Lattice FPGA that I have seen.
> For portable code that works also with ASICs the reset signal is almost
> mandatory. But for pure FPGAs the initial values can be used, and
> for fast designs they save routing resources.
The routing resource for the global set/reset is dedicated and can't
be used for any other purpose. Why? Because it is *always* used by
the GSR whether or not you decide to control its use.
> And and least Synplify supports initial values in signals and memories,
> if the used FPGA also supports them. And most of the FPGA families
> support setting of the initial value of FF, and also in many families
> the memory contents can be set to predefined values.
That may be true. But until it becomes a standard that is followed by
all vendors, you can't count on it when you write your code, unless
you don't care about portability. I sometimes write non-portable
code. But I try to limit it small, application specific code sections
that are well documented and easy to replace when doing a port. But
to toss the global set/reset would require a major rewrite if you need
to add it back at any time because you switched tools.
> Usually if you put timing constraint to the synchronous reset it pops
> out from the global line, because it is too slow. And also for multiple
> clock domains reset networks in normal routing are needed. I have
> sometimes asked from the FPGA manufacturers if they could build global
> resets that are fast, and can be split to create many clock domains.
> After that they would be more useful, single clock domain designs are
> quite rare at least in telecommunication side.
That may be true for designs at very high speed, but actually a sync
reset can be distributed on a clock line which should do the job quite
nicely.
The main point is that one of us has a misunderstanding of how a logic
cell FF gets it's initial state. I think this is fundamental to the
discussion. I am pretty confident that I am correct, but if you know
I am wrong, I would like to know that. I would feel like a fool if I
were having this discussion with a customer and turned out to be
wrong. I much prefer to find out now.
Rick
SW vs HW orientation as a preference motivation makes sense to me
also. I have more background in HW design than in SW, but when it
comes to executable language based descriptions (HDL), I guess I now
emphasize the L(anguage) part more. I started out coding HDL like I
used to draw schematics (this is a register, that is the gates, etc.),
but saw very limited benefit to using the language that way. I can
place and wire up a schematic symbol for a register faster than I can
type it's inference. The ability to describe more complex things like
state machines etc. was much easier in HDL though, especially when I
learned that you can infer the register for free in the same process.
From there I gradually adopted a more "software-like" approach to RTL
coding. I also took a couple of ada programming courses to gain some
knowledge in the use of packages, procedures, functions, etc. That's
where I started learning about using scoping rules to isolate an
implementation from its interface, at various levels of design. I
started out using all that stuff (including variables) in test
benches, then gradually started using it in RTL code (perhaps a bit of
a misnomer).
Mike's example is a very good one because it demonstrates that you can
take advantage of the immediate update behavior of variables to do
things that would be more difficult in signals. Your counter-example
of using a concurrent assignment is functionally valid, but I prefer
not to hop out of a sequential process, into a concurrent statement,
and then back to the process when I can use a variable to do the same
thing without changing contexts. Another benefit occurs when the
device driver writer and I are in the lab, integrating his SW with my
HW. Having an HDL coding style that both of us can understand is very
handy (I could already understand his programming language). I lost
count of how many times I used to have to explain that sequential code
(processes) using signals is only partially sequential, the updates
still happen concurrently. Perhaps that's another reason why the HW
approach to HDL coding makes more sense to some users: that's the only
way you can really make sense of signals in clocked processes (by
mentally mapping them to registers), they sure don't make sense
functionally to me.
I use Synplify almost exclusively, and it is very good with variables.
The times I've tried XST (admittedly somewhat in the past), I did not
appreciate its relative inflexibility, and usually got better results
from Synplify anyway.
Andy
Kim said the 'configuration file' not 'SRAM configuration cells',
there is a difference.
> The configuration memory sets the
> select lines on a number of multiplexers in the logic cell as well as
> other control points that remain fixed throughout the life of a given
> configuration. They also control the routing elements outside the
> logic cell. Finally, they *are* the LUT (along with some pass
> transistors) that determines the logic. But there is no configuration
> ram that sets the initial state of the FFs in the logic cells of a
> Xilinx, Altera or Lattice FPGA that I have seen.
>
There might not be a 'configuration ram' (as you call it), but there
are bits in the bitstream in the 'configuration file' (as Kim calls
it) that are a part of the data set that gets downloaded to the device
to implement the initial values. At leasst with Altera devices, this
all gets done without any 'global set/reset' signals, the only signals
needed are the ones needed to download the bitstream file. Once the
device configuration process has been completed, those initial values
are there.
Lastly, I might add that there may not even be specific bits in the
bitstream to say that flip flop #235 which happens to hold signal
'xyz' needs to be initialized to '1'. Instead the logic can be
implemented in such a fashion that the device, when it finishes
configuration and is begining initialization *prior* to coming alive
and being in user mode (i.e the chip at this point isn't totally alive
yet running your design) that all the flip flops simply get reset. In
that type of situation, the code would implement negative logic for
signal 'xyz' and then wherever 'xyz' is used, it would invert it
again. This double inversion is a fairly common way to implement
arbitrary power up states and since invertors are 'free' inside an
FPGA it is a very cost effective way as well.
For a discussion of Altera Cyclone II devices refer to
http://www.altera.com/literature/hb/cyc2/cyc2_cii5v1_06.pdf
They don't specifically say *how* they get things into the proper
initialization state but
- They do initialize memory and flip flops
- No special pins are needed (just the pins used to download the
bitstream). Spcifically there is no need for a 'GSR'.
- User specified default values for memory and flops are honored.
> > And and least Synplify supports initial values in signals and memories,
> > if the used FPGA also supports them. And most of the FPGA families
> > support setting of the initial value of FF, and also in many families
> > the memory contents can be set to predefined values.
>
> That may be true. But until it becomes a standard that is followed by
> all vendors, you can't count on it when you write your code, unless
> you don't care about portability.
It is already is a standard (i.e. the VHDL language says so). Although
I haven't looked to see if it is part of the synthesis subset in IEEE
1076.6. even if it is not, once some of the competition supports
something that gives the users of the laggard tools some ammo to have
them get their tools up to date. What tool are you using that does
not support it? Perhaps you should consider opening a case with
them. After all, there aren't that many synthesis tools out there,
opening a case can get results...maybe not when you need it 'today',
but at least by the time you need it down the road. That improves the
tools for everyone.
> That may be true for designs at very high speed, but actually a sync
> reset can be distributed on a clock line which should do the job quite
> nicely.
>
> The main point is that one of us has a misunderstanding of how a logic
> cell FF gets it's initial state. I think this is fundamental to the
> discussion. I am pretty confident that I am correct, but if you know
> I am wrong, I would like to know that. I would feel like a fool if I
> were having this discussion with a customer and turned out to be
> wrong. I much prefer to find out now.
>
I think the method by which initial values get loaded could be a
device specific discussion that the vendors may not fully disclose.
I will say that for the devices I've been using I do not need to use
the asynchronous reset form of a process or have any GSR signal to get
initial values loaded. Those initial values specified in the source
code get turned into a bitstream that when downloaded to the device
does seem to work...and when it doesn't I open a case with the
supplier.
But as I mentioned a while back, about the only time I actually *use*
initial values or async resets at all is to for the shift register(s)
used to generate the reset signal(s) that are synchronized to the
various clock(s)...and I can do it all without need for any external I/
O pin to initiate that reset.
KJ
To be precise, at least in Xilinx FPGAs, there is a configuration bit
that determines whether the GSR signal will reset or preset the
associated register(s). The GSR signal is asserted during and until
shortly after configuration. The GSR signal is what activates the set/
preset, but the configuration bit determines the initial state of the
register.
The application of a "synchronized asynchronous" reset (asynchronous
assertion and reset/preset operation, synchronous deassertion and
resumption of clocked operation) for multiple clock domains requires
multiple reset signals, each one appropriately synchronized to the
destination clock.
The GSR and such locally synchronized reset signals are logically
OR'ed at each CLB. The GSR block used to allow synchronization of GSR
to a single user clock, but I'm not sure if it still does, or if
synthesis tools typically implement it that way, since the propagation
delay on the GSR net is very slow.
I can personally attest that asynchronous reset synchronization is
most certainly NOT a red herring!
Andy
Ok, now we are getting somewhere. When you took the programming
courses, what did they teach was the reason for wanting to use
"scoping rules to isolate an implementation from it's interface"? If
those reasons are not concrete and don't apply equally to HDL as to
software, then I see no need to carry that baggage.
I find there are any number of important techniques in software design
that are much less important when coding in an HDL. The idea of scope
is one of those rules. The concept of scope is to prevent you from
using the wrong variable in the wrong situation when you only need to
be able to access a few "local" variables. Why is this important in
software design? Because when variables were global, people often
used them in very confusing ways. The real issue is how people used
them. A method of forcing better programming skills is to limit how
you can access variables.
I don't find this to be an issue in coding in HDL. For one, my code
is generally structured by using entities. For another, these sort of
rules have much less benefit for more experienced programmers. It is
not unlike training wheels. When you are learning, they help keep you
from making mistakes. But once you have enough experience to balance
on your own, why keep the training wheels? I have given up on a
number of software rules that I learned in college. Not that they
aren't useful, I just don't need to enforce them strictly because I
know when they are useful and when they get in the way.
> Mike's example is a very good one because it demonstrates that you can
> take advantage of the immediate update behavior of variables to do
> things that would be more difficult in signals. Your counter-example
> of using a concurrent assignment is functionally valid, but I prefer
> not to hop out of a sequential process, into a concurrent statement,
> and then back to the process when I can use a variable to do the same
> thing without changing contexts.
Hopping, I don't think I have ever heard it expressed that way. I
don't like breaking code up into excessively small pieces either. But
I find very few cases where this happens. The only time I pull logic
outside of a process is when the signal is useful outside of the
process and I want it to be combinatorial, not sequential. If I don't
want a signal to be clocked, I just don't make an assignment to it
inside a clocked process. In fact, to use a variable outside of a
process requires that you make it a global variable and that opens the
can of worms that you are trying to keep a lid on.
> Another benefit occurs when the
> device driver writer and I are in the lab, integrating his SW with my
> HW. Having an HDL coding style that both of us can understand is very
> handy (I could already understand his programming language). I lost
> count of how many times I used to have to explain that sequential code
> (processes) using signals is only partially sequential, the updates
> still happen concurrently. Perhaps that's another reason why the HW
> approach to HDL coding makes more sense to some users: that's the only
> way you can really make sense of signals in clocked processes (by
> mentally mapping them to registers), they sure don't make sense
> functionally to me.
I don't want to badmouth software people. But the last couple of
cooperative working situations I had made me want to work alone as
much as possible. But I feel no need in any case to alter the way I
code to suit someone who has no need to view my code. That is
certainly no reason to burden myself with using features that I have
no need for.
Rick
I would say that this information is device family specific and
information that the vendors are not telling in their datasheets
completely, it is partly visible in the netlists the external
synthesizers generate, but how are those attributes transferred to
bitstream is proprietary.
For example in V5 FF there are 6 settable parameters (FF, LATCH,
INIT1, INIT0, SRHIGH, SRLOW). Are those INIT0/1 bits only in the
bitstream and processed during the upload, or are they persistent,
I do not know. At the end of September I'll meet some A and X guys
who might know the answer, I'll ask if I remember.
This is for example from the V5 manual. How this is implemented is not
told.
"The initial state after configuration or global initial state is
defined by separate INIT0 and INIT1 attributes. By default, setting the
SRLOW attribute sets INIT0, and setting the SRHIGH attribute sets INIT1.
Virtex-5 devices can set INIT0 and INIT1 independent of SRHIGH and
SRLOW."
For Altera the SIV documentation was quite vague on this area. But
at least in the past they had only "init to zero" style thing, and
they added inversion if one was needed. Actually Synplify 8.8
had a bug in this inversion, with retiming it got very confused
wheter the signal was inverted or not ;)
--Kim
> For one, my code
> is generally structured by using entities.
I share this preference narrowly:
1. When I do have to wire things up myself,
I prefer to map pretested boxes with
the outs and ins clearly marked.
2. In a single-process box, variable/register IDs
are just as "global" as architecture signal IDs.
I find keeping track of signal drivers
and receivers for wires inside a multi-process box
to be tedious and hard to test.
Inside a single process box, synthesis is happy to
wire up the variable/registers and subprogram/gates
for me and then draw a schematic.
(thank you very much)
My logical "structures" are the types and subtypes
used to declare, and update, a gaggle of variable/registers at a time.
-- Mike Treseler
There is a very simple test. Does the GSR control the FF? If the GSR
signal controls the power up state of the FF, then there is no reason
to add extra controls to the bitstream and hardware. The answer is,
Yes, the GSR *will* control the state of a FF which has an initial
value.
Why anyone would imagine that there is extra logic and configuration
memory to control the initial state of CLB FFs is beyond me. There is
no reason to do it this way and the extra logic required is just
wasted silicon.
Rick
But only for those devices that have this extraneous 'GSR' that the
user apparently is forced to worry about...simply to get the device
into a specified state at power up. Glad I don't have those worries.
KJ
The ada courses taught me a lot about how to design/code with
maintenance in mind, with a LOT more than just limiting scope. In this
regard, limiting the scope of a sig/var limits the impact on later
changes to the behavior of that sig/var. For example, if my FSM state
is held in a variable, then there is nothing outside of the process
that depends directly on the state definitions, transitions, etc.,
since all those dependencies must be transmitted through separate,
well-defined (hopefully) signals of wider scope. I can later modify
the state machine, and be confident that all references to it are
contained within that process, where they can be modified accordingly.
Can you do this without variables or blocks? Sure you can, but there
is no compiler keeping you honest. More importantly, if you are
modifying someone else's design/code, there was no compiler keeping
them honest either.
Of course you could break everything down into tiny entities and
architectures to achieve the same scope control, but blocks and
variables allow a "lightweight" hierarchy, with less coding overhead
(no entity definitions or port maps), and a "semi-global" signal
concept (external signals are not global, but also not completely
local). There is a place for entity level hierarchy, and there is a
place for block/process level hierarchy.
Just like in SW, how you write HDL code depends a lot on your work
environment. If you typically work alone, and don't have a lot of
reuse across projects, then some of these techniques make less sense
in your environment. If you work in teams, on large projects, these
concepts can save a lot of time and effort down the road. In my
experience, once you are familiar with the concepts, the additional up
front effort is negligible.
I should also mention that not everything I learned in the ada courses
was taught by the instructors. I learned a lot from the other SW
students while working through lab exercises and just in general
conversation. I learned an awful lot about SW development on a large
scale, and design/code techniques that do and don't work on a large
scale project. I was a pretty good coder in C and VHDL before the
class. Afterwards, I was a better designer/developer/engineer.
>
> I find there are any number of important techniques in software design
> that are much less important when coding in an HDL. The idea of scope
> is one of those rules. The concept of scope is to prevent you from
> using the wrong variable in the wrong situation when you only need to
> be able to access a few "local" variables. Why is this important in
> software design? Because when variables were global, people often
> used them in very confusing ways. The real issue is how people used
> them. A method of forcing better programming skills is to limit how
> you can access variables.
>
> I don't find this to be an issue in coding in HDL. For one, my code
> is generally structured by using entities. For another, these sort of
> rules have much less benefit for more experienced programmers. It is
> not unlike training wheels. When you are learning, they help keep you
> from making mistakes. But once you have enough experience to balance
> on your own, why keep the training wheels? I have given up on a
> number of software rules that I learned in college. Not that they
> aren't useful, I just don't need to enforce them strictly because I
> know when they are useful and when they get in the way.
This is true so long as only you have to maintain only your code.
>
> I don't want to badmouth software people. But the last couple of
> cooperative working situations I had made me want to work alone as
> much as possible. But I feel no need in any case to alter the way I
> code to suit someone who has no need to view my code. That is
> certainly no reason to burden myself with using features that I have
> no need for.
I try to learn from different disciplines as much as I can. Some
things are useful, some things aren't. I've also had SW "experts" tell
me I had too many levels of nested case/if/loop statements in my
code...
I understand where you are coming from. Your style makes sense and
works for you in your environment. Mine makes sense and works in my
environment.
Andy
> I find there are any number of important techniques in software design
> that are much less important when coding in an HDL. The idea of scope
> is one of those rules.
Locality is good because:
(1) Imagine if in C you couldn't use local variables in functions, and
had to scroll up to the top of the file to declare *every* variable, and
then scroll back down to continue writing your functions. It would
interrupt your train of thought - it would be a PITA.
(2) Using locality effectively allows easier review of code (not only for
someone else, but for you too) and debug. If you can *easily* determine a
variable is local to a chunk of code, then you don't have to concern
yourself with its use anywhere else in that file - it lightens the load on
the brain and makes the job easier.
In various studies in bug detection rates/costs in software (I suspect
there is *some* correlation to HDL coding), it has been found that bugs
found by code review cost a lot less per bug compared to unit testing. I
suspect that's why verification often consists of test benches + code
review.
But I guess not *everyone* will find those things useful.
Paul.
I guess you don't use FPGAs then.
This conversation seems to have taken a wrong term somewhere. I don't
know why this is getting contentious.
I have been talking about FPGAs from the beginning and I have stated
that clearly. ASICs are a whole different animal and I have not
addressed that at all. If you are using a programmable device that
does not have a global power-on reset signal, then you are either
using a very small device (CPLD) or you are using one I have never
heard of.
The "worry" is always there. You have to get the device into a known
state following configuration and any time another reset is applied.
Of course you can use configuration as a reset if you want. But the
issue is still there that you have to have a way to specify the
initial condition for the sequential logic. Most people consider the
GSR to be a *useful* feature toward this goal.
Rick
No one is suggesting that locality is useful. But micro-managing of
locality is not so useful. If you have a variable for a counter and
later you find that you *need* the value of that counter, then you
have to change the code to use a signal. On the other hand, the fact
that a signal is declared does not require that it is used anywhere
other than in the process where it is assigned.
Comparing the use of signals to C code with only global variables is
not really useful and is just a straw man argument.
> (2) Using locality effectively allows easier review of code (not only for
> someone else, but for you too) and debug. If you can *easily* determine a
> variable is local to a chunk of code, then you don't have to concern
> yourself with its use anywhere else in that file - it lightens the load on
> the brain and makes the job easier.
If you spend more time reviewing code than writing, I guess this can
be important. I prefer to write code that is inherently easy to
read. Of course this is not always possible for complex problems, but
that is my goal. Using variables will do little to make the difficult
code more readable.
> In various studies in bug detection rates/costs in software (I suspect
> there is *some* correlation to HDL coding), it has been found that bugs
> found by code review cost a lot less per bug compared to unit testing. I
> suspect that's why verification often consists of test benches + code
> review.
So how does using signals preclude code review? This is just a non-
sequitur.
> But I guess not *everyone* will find those things useful.
I find *useful* things useful. I don't use forced techniques when
they are not needed. I use appropriate techniques. I expect that NASA
uses all of these techniques and many more. But that doesn't stop
problems from happening, like mixing feet and meters at an
interface.
Rick
Of course using signals doesn't preclude code review - my point was that
localization aids code review.
Paul.
I certainly do.
> This conversation seems to have taken a wrong term somewhere. I don't
> know why this is getting contentious.
>
Going in circles somewhat, so I guess we can agree to end it here.
> I have been talking about FPGAs from the beginning and I have stated
> that clearly. ASICs are a whole different animal and I have not
> addressed that at all.
Same here, no ASIC conversations from me.
> If you are using a programmable device that
> does not have a global power-on reset signal, then you are either
> using a very small device (CPLD) or you are using one I have never
> heard of.
>
I'm sure you've heard of Altera, Stratix, Cyclone, etc. Lattice
sometimes, Xilinx less so.
The point is that a global power on reset for the device is not needed
in order to get the flops and memory into a known state at the point
where configuration ends. I know this has been said several times and
you seem to dispute that for some reason but it is the truth.
> The "worry" is always there. You have to get the device into a known
> state following configuration and any time another reset is applied.
Agreed...but also note that you've mentioned two distinct times for
reset: "following configuration" and "any time another reset is
applied". The initial default values that one can specify in the
design source code only apply to the "following configuration"
instant.
> Of course you can use configuration as a reset if you want.
Only to generate the synchronous reset signals that resets the rest of
the device...then using a synchronous process form darn near every
other place in the design. That way the design will come up properly
even if the external reset signal is busted inactive for whatever
reason.
> But the
> issue is still there that you have to have a way to specify the
> initial condition for the sequential logic.
Lood at what you just wrote though. The specification of the 'initial
condition of sequential logic' does not require any signal for it to
be implemented. It is simply the 'initial condition' which exists at
t=0 which for FPGAs is at the point where the part is switching to
some form of 'user mode' where the device is from then on implementing
the logic defined in your source code. For a CPLD or anything that
retains it's programming, t=0 is usually defined relative to the power
supply rails reaching some magic voltage for some specified period of
time.
> Most people consider the
> GSR to be a *useful* feature toward this goal.
>
No, most people use some form of reset signal to *try* to get their
logic into the same state that existed at t=0. I'm not trying to play
semantic games or anything, but the application of reset is not the
same thing as going back to t=0. In order to get back to t=0 you
would have to reconfigure the device. If you don't think so, then
explain how a reset alone would recover an FPGA from an SEU that upset
some important bit in the device.
I'm not suggesting such an event is likely just using that to drive
home the point that application of an external reset signal is not the
same as downloading a configuration and as I've said many times
before, the initial value specification in the code gets implemented
from downloading the configuration code, not from any GSR signal.
KJ
>On Aug 21, 9:07 am, Brian Drummond <brian_drumm...@btconnect.com>
>wrote:
>> On Mon, 18 Aug 2008 11:39:42 -0700 (PDT), rickman <gnu...@gmail.com>
>> wrote:
>> >I can't say I follow you on this. A reset input by definition defines
>> >the state of all registers, state and output. Why would you want to
>> >assign the outputs to be dependant on the previous state when the
>> >reset is asserted??? I have never done this since it was not the
>> >desired behavior.
>>
>> One reason (not the case in this example): a very long delay line,
>> containing delayed state (to be used when a slow operation started by
>> the main state machine has completed). You can either reset this along
>> with the main state, or simply let its inputs ripple through. The latter
>> can be implemented at 16 bits per LUT in SRL16s for Xilinx, saving
>> several hundred FFs. The former can't, because the SRL16s don't have the
>> necessary reset connections.
>
>Ok, so how does that relate to the issue of using variables?
I think it's an orthogonal issue, applying to both variables and
signals. It only relates to your point about always wanting reset to
define the entire state.
- Brian
This seems to be the crux of the discussion. I posted why I think the
GSR is required to initialize the FFs in FPGAs. Why do you think the
GSR is *not* needed to initialize the FFs in FPGAs?
If you want me to say it again... The configuration memory is loaded
from the config stream. This uses a significant number of transistors
and directly controls static signals in the logic elements and routing
matrix. Once configured, these elements do not change. The only
exception to this that I am aware of are the config elements in the
LUTs of a Xilinx device when used as a shift register. Otherwise they
are static and their construction is very different from the FFs in
the logic elements.
The FFs are initialized by the GSR which is routed to the set/reset
under control of the config memory. This logic *has* to exist in
order for the GSR to function even if you don't use it. Then to add
additional logic that will set the initial state of the FF on
configuration would be superfluous.
Have you seen anything that contradicts this? Can you cite a
reference? Just saying it is "the truth" is not really useful.
Rick
This is a good summary of the entire discussion, "localization aids
code review". That is a statement without value. The issue is
whether the use of variables has any real advantage, sufficient to
require learning of additional complexity. So far, I have only seen
hand waving, statements that are either not supported, or that have no
clear meaning. I don't accept that localization of variables actually
provides any advantage in code reviews. I also don't accept that
"aids code review" is a sufficiently strong reason to use variables.
The question is whether the benefit is worth the cost. It has been
said that the cost of using variables is not high and is in fact near
zero once you get over the learning curve. I say this learning curve
is significant, even if it is just the fact that a large portion of
HDL designers don't use variables. So there is a significant portion
of the community that will have to work to understand your code. I
think this is a significant barrier to communication and without some
clear advantage is not worth the cost.
It has also been said that the use of variable localization "aids code
review". Maybe it does in some small way, but I don't see how this is
any significant advantage. A code review is not done in a meeting
room using paper. The code review should take place before the
meeting where the reviewers have access to all of the typical
programming tools, such as an editor with search capabilities. I can
determine the localization of both variables and signals using a
search. This is in no way hard to do, is 100% effective and works for
everything in the code, not just one class of objects.
So it seems clear to me that the cost of using variables is non-
trivial and the advantage of using variables is minimal.
Rick
You use a search function to review locality of use, we use the
compiler.
But localization is not just about code review! It is also, and even
more importantly IMHO, about code maintenance and the code's ability
to be more easily changed to implement new functionality, or fix bugs
in old functionality, while limiting the effects of those changes to
the intended purpose.
One can design using global signals for everything, and still have a
good design from a locality of use standpoint (just because you
declared a global signal does not mean you used it willy-nilly all
over the place). The problem is that someone reviewing and/or
maintaining such code would have to go to significantly more effort to
verify that you did use locality if you used signals. The locality
advantage of using variables is that you, the compiler, and everyone
else that reads and/or maintains the code knows that locality was not
only intended, it was enforced.
What is clear to each of us is obviously different...
Andy
As I said previously, the extra configuration control is to determine
whether the initial/reset condition is '1' or '0' when GSR or local
reset is applied. Given there is only one GSR input and one local
reset input (and they are ORed together to reset the register), how
else do you suppose they might control whether the register is '1' or
'0' upon configuration or reset?
Andy
Forgetting for a moment the set of device I/O pins that are required
to load any bitstream into the device and are basically dedicated I/O
for the bitstream load function, all I'm saying is
1. No *other* external I/O pin is *required* to initialize the FPGA
in order to implement an initial condition on a signal that happens to
be the output of a flip flop or memory (i.e. signal xyz: std_ulogic :=
'1';). If the device (and tool set) supports initial values then flip
flop #234 which contains signal 'xyz' will be set to a '1' at the
moment when the device switches over to user mode and starts
functioning as I've described in the HDL. (Later I'll get into if the
device/tools do not meet the condition).
2. I wouldn't use a device input that performs a device wide reset
because in order to do so the trailing edge of such an input signal
would have to be synchronized to each of the clocks internal to the
device. From a practical standpoint about the only way to get this
would be to disable the clock input to the device until some time
after that device wide reset signal goes inactive. What you're doing
here though is shifting the burden off chip to the PCBA just so you
can take advantage of what it does for you inside the FPGA.
Apparently you see this as something 'free' to be taken advantage of
and in some instances it might be. In general though there will be
some cost to be incurred to implement your requirements. As an
example, any other part on the PCBA that intends to use that same osc
as a clock input had better be able to cope with the clock shutting
off during the period of time when the FPGA is getting reset. What if
it can't cope with it? You'll need multiple clocks (one gated to the
FPGA, one not) and there will now be clock skew now between those
two...does the clock skew matter? Yeah, sometimes it does when the
two devices are expected to be receiving the 'same' clock.
You can argue that putting a reset signal in all of the code now chews
up some logic resources (it does) and can hurt clock cycle performance
(it could) but I've only found this to be any sort of issue on designs
where *everything* gets reset (i.e. control and data path) for no
reason instead of just resetting the much more limited set of control
signals and state machines that need it.
So the bottom line here is that that there is a cost to be paid for
using the device wide reset pin and that cost could be evaluated on a
design by design basis. While there can be a logic/performance cost
to not using it, I've found that simply resetting only what needs to
be brings that cost down to 0 in many cases (i.e. when the input to
the LUT would not have been used) What I've found so often though is
that using the device wide reset pin costs more than it's worth so I
don't use it.
I do always have some reset input pin to a design (in case there was
some doubt that I only rely on end of config to get me off to the
correct starting point). But that reset input goes into the 'D' input
of one flip flop which is the first flop of a shift register and it
goes to the async reset of every flop of that shift register. There
is one of these shift registers for each internal clock in the
device. The outputs of the shift registers become the reset signals
that get distributed to the design. That reset signal though has no
requirement to go active at the end of configuration, it need only go
active when something on the board decides that the FPGA needs to be
reset.
Given that, even if the device/tools doesn't happen to support initial
values I wouldn't need to change anything in the RTL code as a
result. What that would mean is that there would be a requirement now
on this reset input to be active for some period of time after the
device is configured. Ysing the device wide reset you wouldn't change
your code either so there is no (dis)advantage either way from the
perspective of writing code.
> If you want me to say it again... The configuration memory is loaded
> from the config stream. This uses a significant number of transistors
> and directly controls static signals in the logic elements and routing
> matrix. Once configured, these elements do not change. The only
> exception to this that I am aware of are the config elements in the
> LUTs of a Xilinx device when used as a shift register. Otherwise they
> are static and their construction is very different from the FFs in
> the logic elements.
>
I'm not quite sure what you're getting at here, but it seems that
you're missing the fact that the configuration bitstream also contains
initial value contents of flops and memory (How do you think a read
only memory would get implemented? Discrete logic would work, but for
performance you might want to take advantage of the internal RAM
blocks that the FPGA has).
> The FFs are initialized by the GSR which is routed to the set/reset
> under control of the config memory. This logic *has* to exist in
> order for the GSR to function even if you don't use it. Then to add
> additional logic that will set the initial state of the FF on
> configuration would be superfluous.
>
There is no additional logic to set the initial state of the FF on
configuration. It simply changes some zeros to ones in the
configuration bitstream.
> Have you seen anything that contradicts this? Can you cite a
> reference? Just saying it is "the truth" is not really useful.
>
I believe I've said way more than just 'the truth' prior to this
post. Refer to the configuration guide for the device you're
interested in, or the Altera reference I provided earlier and/or
Altera's Quartus manual for what it has to say about initial values.
Kevin Jennings
This is the stuff that you keep saying with no real basis. For one
you keep referring to "global" signals. Signals are not global. They
are local to an entity. The only way another entity has access to
them is through a defined interface. You are saying that if you don't
use signals inside of processes (which tend to be rather small pieces
of code) then the signals are "global" with all the problems that
creates.
My point is that you are exaggerating the issues of using signals. I
think I said before that in a real software program, true global
variables can be very easily misused. But that is totally different
from signals in entities.
Sure using local variables in VHDL sounds like a good idea, but
compared to using signals, it provides very little advantage in a real
situation. I can very easily view a couple hundred lines of code
using an editor. There is *no* difficulty. By using variables to
make the use of an object strictly local to a process instead of the
entity buys you very little.
You want to make it sound like managing signals is a tough thing. It
is not.
I have worked in situations where there was very little enforced
order. Yes, that was fairly much chaos. In that environment it was
100% up to the programmer to produce good code and for it to be
maintainable. I have worked in environments where there were very
strict methods, like the use of local variables, that were enforced.
I found very little difference in productivity between the two. Why?
Because there are a million ways to write crappy code and techniques
like using variables as a method of coding regulation is in the
noise. It just isn't worth much.
I guess we can argue this all day and never come to any agreement.
But no one has yet given any real supporting information to show that
there is a significant advantage to using variables as a means of
coding control. Everything said here is just arm waving. It is not a
matter of what is "obviously different". I based decisions like this
on what I can measure. I have never been able to determine that there
was a difference for this sort of coding guidelines. Bad programmers
are still bad and good programmers are still good no matter what
guidelines you use.
I guess in a hierarchy, you have to do something to keep the coders in
line. Otherwise managers couldn't justify their paychecks.
Rick
First, you have made assumptions about the design to be used in the
FPGA that may or may not be correct for any given design.
The GSR signal does not *have* to be sync'd to the clock in order to
be useful. If you have a FSM which is waiting for an input and you
know for a fact that the input is not asserted on powerup, then you
don't have to worry about the FFs in the FSM all being released on the
same clock cycle. That is one example of when you don't need to sync
the GSR to the clock, there are others.
So as a designer, you have choices.
Regardless, I have already explained how you can use the GSR so that
it *is* sync'd to the system clock. Then the clock does not have to
be held and the GSR utility is "free" consuming no additional
resources. But I still don't get your point? Regardless of how the
FFs in an FPGA are initialized, you still have the problem of how to
synchronize their startup. I think you are glossing over the details
of how this happens. It happens when GSR is released. Check the data
sheets for the parts you are using. If that doesn't work for you,
then you need to make other arrangements. But for a large percentage
of designs, the GSR can be used to both set the initial state and to
synchronize the startup of the chip. If this is not done by the GSR
signal, what does control the startup timing of the chip?
> You can argue that putting a reset signal in all of the code now chews
> up some logic resources (it does) and can hurt clock cycle performance
> (it could) but I've only found this to be any sort of issue on designs
> where *everything* gets reset (i.e. control and data path) for no
> reason instead of just resetting the much more limited set of control
> signals and state machines that need it.
You keep saying stuff like this but it is not true. The global reset
is "global" and dedicated. It is *allways* used. You have two
choices, control it, or let it default to initializing all of the FFs
to zeros.
> So the bottom line here is that that there is a cost to be paid for
> using the device wide reset pin and that cost could be evaluated on a
> design by design basis. While there can be a logic/performance cost
> to not using it, I've found that simply resetting only what needs to
> be brings that cost down to 0 in many cases (i.e. when the input to
> the LUT would not have been used) What I've found so often though is
> that using the device wide reset pin costs more than it's worth so I
> don't use it.
I don't get what you mean by all of your cost stuff. What you
explained above for cost is the startup of the chip, not the initial
conditions. If you don't control GSR, how do you control the startup
of the chip? When you reset what you want reset, how does that
happen? Doesn't that have a cost?
> I do always have some reset input pin to a design (in case there was
> some doubt that I only rely on end of config to get me off to the
> correct starting point).
Ahhh, how do you control this??? How do you get your freshly
configured design all started on the same clock cycle?
> But that reset input goes into the 'D' input
> of one flip flop which is the first flop of a shift register and it
> goes to the async reset of every flop of that shift register. There
> is one of these shift registers for each internal clock in the
> device. The outputs of the shift registers become the reset signals
> that get distributed to the design. That reset signal though has no
> requirement to go active at the end of configuration, it need only go
> active when something on the board decides that the FPGA needs to be
> reset.
This is using a *LOT* of resources that may be unnecessary. I'm not
clear on why you use multiple outputs from the shift register. I use
one output as the async reset to the entire design. This is then
mapped to the GSR signal by the software and my entire design is
released from reset synchronous to the clock and on the same clock
cycle. Since it uses the GSR signal, the chip ORs its own end of
configuration reset in with the one from the shift register and all is
right with the world.
Yes, if you have multiple clocks in the design, then this is not
viable. But I seldom have multiple clocks that require this sort of
reset release. Instead I try to use a single clock throughout the
chip and sync other clock domains at the I/O point. This eliminates
the need for multiple clock domains in most cases.
> Given that, even if the device/tools doesn't happen to support initial
> values I wouldn't need to change anything in the RTL code as a
> result. What that would mean is that there would be a requirement now
> on this reset input to be active for some period of time after the
> device is configured. Ysing the device wide reset you wouldn't change
> your code either so there is no (dis)advantage either way from the
> perspective of writing code.
Except that your solution is using a lot more of the chip and
especially the routing resources.
> > If you want me to say it again... The configuration memory is loaded
> > from the config stream. This uses a significant number of transistors
> > and directly controls static signals in the logic elements and routing
> > matrix. Once configured, these elements do not change. The only
> > exception to this that I am aware of are the config elements in the
> > LUTs of a Xilinx device when used as a shift register. Otherwise they
> > are static and their construction is very different from the FFs in
> > the logic elements.
>
> I'm not quite sure what you're getting at here, but it seems that
> you're missing the fact that the configuration bitstream also contains
> initial value contents of flops and memory (How do you think a read
> only memory would get implemented? Discrete logic would work, but for
> performance you might want to take advantage of the internal RAM
> blocks that the FPGA has).
The configuration bitstream *doesn't* contain initial values for FFs.
You keep referring to memory. Memory is not the same as the logic
element FFs. Memory can be initialized by the configuration stream.
The LUTs can be initialized by the configuration stream. But the FFs
in the logic elements can only be initialized by the GSR. As I have
tried to explain, the GSR is ***always*** a part of release from
configuration. So there is no need for the extra transistors inside
the chip to make the FF state part of the configuration stream. If
you don't believe me, ask Peter Alfke. I bet he can clear this up.
I am happy to admit that I could be wrong about this. But I am very
confident I am not. I would be happy to hear Peter set the record
straight.
> > The FFs are initialized by the GSR which is routed to the set/reset
> > under control of the config memory. This logic *has* to exist in
> > order for the GSR to function even if you don't use it. Then to add
> > additional logic that will set the initial state of the FF on
> > configuration would be superfluous.
>
> There is no additional logic to set the initial state of the FF on
> configuration. It simply changes some zeros to ones in the
> configuration bitstream.
So how do the zeros and ones in the bitstream get into the FFs???
That would require that the FF have a mux on the D input and that the
clock have a mux to clock it from the bitstream clock. Just think of
how much extra logic that would require on every FF in the design.
> > Have you seen anything that contradicts this? Can you cite a
> > reference? Just saying it is "the truth" is not really useful.
>
> I believe I've said way more than just 'the truth' prior to this
> post. Refer to the configuration guide for the device you're
> interested in, or the Altera reference I provided earlier and/or
> Altera's Quartus manual for what it has to say about initial values.
Does any of these docs actually say that the FFs are directly
controlled by the configuration bitstream or does it say that the FFs
can be initialized using the GSR signal with the set/reset *selected*
by the configuration stream???
I think you have been reading between the lines. But then I am more
familiar with the Xilinx parts than the innerds of the Altera parts.
Although, I will say that on the ACEX 1K parts, there was no
configuration loading of the FFs. The FFs were ***always*** reset by
the GSR and the tools would invert the use of the signal if you wanted
the initial state to be a 1.
Can you quote something that clearly says what you are saying?
Rick
I like these shorter messages better!
You seem like you understand the internal structure of these devices.
But I can't say I understand your question.
As you said, the GSR signal is or'd with a local async reset input.
This control is ***configured*** to either set or reset the FF. That
is what I am saying. But others are saying that the FF is directly
loaded by the configuration bit stream in the same way that the LUT or
block rams are loaded. This is not the case. The LUTs and memory are
unaffected by the GSR signal but the FFs are controlled.
If you could suppress the GSR signal on configuration, the
configuration bitstream would have no effect on the state of the FFs
in the logic elements. Loading the FFs directly from the
configuration bitstream would require muxes on the D input and the
clock input. This would be a lot of extra logic in the chip for no
purpose since the GSR signal will set or reset every FF in the design
during configuration. You can then choose to use the GSR signal after
configuration for your own purposes or not.
Rick
Maybe it's too late in the thread to be more succint, but....
> This seems to be the crux of the discussion. I posted why I think the
> GSR is required to initialize the FFs in FPGAs. Why do you think the
> GSR is *not* needed to initialize the FFs in FPGAs?
>
In 100 words or more...I think a discrete device wide reset pin is not
needed because...
- The documentation for the devices that I commonly use does not in
any way indicate that a device wide reset input signal from some pin
is in any way needed to get the device configured.
- The documentation for the devices that I commonly use states that
the function of the device wide reset pin performs a function that I
do not happen to require in order to complete my design and meet all
function, performance, etc.
- In actual implementations, once configured the part implements the
logic that I've described. When it hasn't for some reason I open a
case with the supplier. The root cause for that failure has never
turned out to be due to the lack of use of the device wide reset.
- Actual implementations also support the first two
statements...again, for the devices that I commonly use.
>
> The FFs are initialized by the GSR which is routed to the set/reset
> under control of the config memory.
- For which devices can you reference documentation to support your
statement?
- Have you considered that there may very well be devices existing
today that do not require an external GSR pin to function properly?
> This logic *has* to exist in
> order for the GSR to function even if you don't use it. Then to add
> additional logic that will set the initial state of the FF on
> configuration would be superfluous.
>
- If it means avoiding a timing problem on the trailing edge of the
device wide reset relative to a clock, I wouldn't consider that to be
superfluous.
KJ
You're probably right; variables are just too hard for some people to
use. Maybe those people shouldn't use them.
Agreeing to disagree...
Andy
Probably true, but I view every storage element as having setup and
hold time requirements that must be met on all inputs and not waste
time and effort on the special cases where I might be able to get away
with violating those requirements (with the exception of course of my
reset shift register previously mentioned). If you choose to do
otherwise, in other situations that's your concern.
<snip special case example> If you have a FSM which is waiting for an
input and you
> be held and the GSR utility is "free" consuming no additional
> resources. But I still don't get your point? Regardless of how the
> FFs in an FPGA are initialized,
I though "how the FFs in an FPGA are initialized" was the point of
this part of the thread...oh well.
> you still have the problem of how to
> synchronize their startup. I think you are glossing over the details
> of how this happens.
No, when the device comes out of configuration and is starting up (and
is doing so independently of any input clock to the device), my reset
shift register is outputting a reset signal that is asserted for
several clock cycles due to the initial value specification. Since
the rest of the design is using that signal as their reset input,
everything starts up properly.
> It happens when GSR is released. Check the data
> sheets for the parts you are using.
I'll refer you to...
http://www.altera.com/literature/hb/cyc2/cyc2_cii5v1.pdf (Pages
363-365,375, 384-385, all interesting reading)
http://www.altera.com/literature/hb/cyc2/cyc2_cii51013.pdf (Pages 8-11
as an example)
http://www.altera.com/literature/hb/qts/qts_qii51007.pdf (Pages 40-42
are interesting).
> > I do always have some reset input pin to a design (in case there was
> > some doubt that I only rely on end of config to get me off to the
> > correct starting point).
>
> Ahhh, how do you control this??? How do you get your freshly
> configured design all started on the same clock cycle?
>
I've explained that several times already...including the following
paragraph from the previous post.
> > But that reset input goes into the 'D' input
> > of one flip flop which is the first flop of a shift register and it
> > goes to the async reset of every flop of that shift register. There
> > is one of these shift registers for each internal clock in the
> > device. The outputs of the shift registers become the reset signals
> > that get distributed to the design. That reset signal though has no
> > requirement to go active at the end of configuration, it need only go
> > active when something on the board decides that the FPGA needs to be
> > reset.
>
> This is using a *LOT* of resources that may be unnecessary. I'm not
> clear on why you use multiple outputs from the shift register.
I only use one output (the last one) from the shift register. Many
designs have multiple clocks so I have one shift register per clock
domain so that each clock domain gets a reset signal that is
synchronized to their clock.
> I use
> one output as the async reset to the entire design.
I use it as a synchronous reset, but OK. On benchmarks I've seen some
designs better with sync some better with async. I haven't been
convinced that one way is always (or usually) better than the
other...that might be device family specific though I admit.
> Yes, if you have multiple clocks in the design, then this is not
> viable.
But my method is viable.
> But I seldom have multiple clocks that require this sort of
> reset release.
Well at least you do have designs with more than one clock...do you
just punt on those designs? Or do you in fact synchronize to each
clock domain?
> Instead I try to use a single clock throughout the
> chip and sync other clock domains at the I/O point. This eliminates
> the need for multiple clock domains in most cases.
>
Most of your cases perhaps...but even there it is 'most' not 'all'.
Whether you need a separate clock domain or not generally depends on
the relative difference there is between two domains and what the
timing requirements of the external devices actually are. The greater
the difference in clock frequency, the more likely that the fast clock
can be used to meet the timing requirements of the slower clock
domain.
> > Given that, even if the device/tools doesn't happen to support initial
> > values I wouldn't need to change anything in the RTL code as a
> > result. What that would mean is that there would be a requirement now
> > on this reset input to be active for some period of time after the
> > device is configured. Ysing the device wide reset you wouldn't change
> > your code either so there is no (dis)advantage either way from the
> > perspective of writing code.
>
> Except that your solution is using a lot more of the chip and
> especially the routing resources.
>
One shift register per clock domain is a handful of LUTs which is not
a lot of anything. I haven't had routing resource issues since the
early 90s and brand X 3K parts.
>
> The configuration bitstream *doesn't* contain initial values for FFs.
> You keep referring to memory. Memory is not the same as the logic
> element FFs. Memory can be initialized by the configuration stream.
> The LUTs can be initialized by the configuration stream. But the FFs
> in the logic elements can only be initialized by the GSR.
Initialized to a value that is determined by data in the configuration
stream if it is going to implement initial values. If not, then it
would appear that your devices do not support initial value
specification which is the reason for the ongoing talk.
> As I have
> tried to explain, the GSR is ***always*** a part of release from
> configuration. So there is no need for the extra transistors inside
> the chip to make the FF state part of the configuration stream.
> If you don't believe me, ask Peter Alfke. I bet he can clear this up.
>
Besides the fact that Peter isn't posting here anymore due to a recent
re-org at X, I doubt that he would care to have any comment on the
workings of competitors.
>
> > There is no additional logic to set the initial state of the FF on
> > configuration. It simply changes some zeros to ones in the
> > configuration bitstream.
>
> So how do the zeros and ones in the bitstream get into the FFs???
> That would require that the FF have a mux on the D input and that the
> clock have a mux to clock it from the bitstream clock. Just think of
> how much extra logic that would require on every FF in the design.
>
Or perhaps just read the previously mentioned Altera docs for some
insights to their approach. Maybe brand X is better than A, maybe
not...but you're making your own assumptions on how it would have to
be done.
>
> Does any of these docs actually say that the FFs are directly
> controlled by the configuration bitstream or does it say that the FFs
> can be initialized using the GSR signal with the set/reset *selected*
> by the configuration stream???
>
In either case the configuration bit stream is used to get the flip
flop into the specified state at the end of configuration mode as the
device is entering user mode. Whether it is 'directly controlled' by
the bitstream or 'selected' by the bitstream is irrelevant.
> I think you have been reading between the lines. But then I am more
> familiar with the Xilinx parts than the innerds of the Altera parts.
> Although, I will say that on the ACEX 1K parts, there was no
> configuration loading of the FFs. The FFs were ***always*** reset by
> the GSR and the tools would invert the use of the signal if you wanted
> the initial state to be a 1.
>
And they call that technique 'not gate push back', do you find it
offensive or something? Since invertors are free in an FPGA,
complaining about push back is like complaining that synthesis
implemented the DeMorgan equivalent of your logic.
> Can you quote something that clearly says what you are saying?
>
Hopefully I have.
KJ
> So it seems clear to me that the cost of using variables is non-
> trivial
true, as is the cost of using:
functions,
procedures
types and subtypes,
type attributes
array attributes
numeric_std.all
I could get by without any of these.
They were all hard to learn,
but once apprehended,
they are harder to leave alone.
> and the advantage of using variables is minimal.
maybe true, in an alternate universe where I never happened to
use a debugger,
printf,
trace code,
compare algorithms,
attach 32 little clips to an address bus and wait for trigger
-- Mike Treseler
> in the logic elements. Loading the FFs directly from the
> configuration bitstream would require muxes on the D input and the
> clock input. This would be a lot of extra logic in the chip for no
> purpose since the GSR signal will set or reset every FF in the design
> during configuration. You can then choose to use the GSR signal after
> configuration for your own purposes or not.
But for example in V5 you can set different init value for the FF
compared to the set/reset value that can be connected to the GSR signal
in functional mode. The real implementation might be that first the
init0/init1 attributes are set from the configuration to the SR
settings, after that internally GSR is asserted and after that the real
srhigh/srlow attributes are set up.
One again this is from the V5 manual:
"The initial state after configuration or global initial state is
defined by separate INIT0 and INIT1 attributes. By default, setting the
SRLOW attribute sets INIT0, and setting the SRHIGH attribute sets INIT1.
Virtex-5 devices can set INIT0 and INIT1 independent of SRHIGH and
SRLOW."
But without the design spec for V5 we can just guess. My understanding
is that the high level logical schematic of a logical element (LUT+FF
etc) is quite different compared to the real transistor level
implementation. Also the FPGAs contain hidden undocumented features all
over the place, for certain customers those features can even be enabled
with special tool patches. So there are many things inside the chip
that are just not documented.
--Kim
From the use of SRLOW and SRHIGH I suspect this is not even addressing
the FF state. SR likely refers to the shift register that you get
when using the LUT memory as logic. The LUT memory *can* be set by
the configuration bit stream, but in none of the logic families I have
seen can it be controlled by the GSR signal. Did you find any mention
of what SRLOW, SRHIGH, INIT0 and INIT1 control?
Rick
Maybe you should even open the V5 user guide. SR* controls the set/reset
polarity. All four parameters were FF related configuration parameters.
> seen can it be controlled by the GSR signal. Did you find any mention
> of what SRLOW, SRHIGH, INIT0 and INIT1 control?
Yes, you can also if you open UG190.
--Kim