Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > VHDL > alternate synchronous process template

Reply
Thread Tools

alternate synchronous process template

 
 
jens
Guest
Posts: n/a
 
      06-15-2006
Most of us are familiar with this synchronous process template...

synchronous_process_template: process(clock, reset)
begin
if reset = '1' then
-- initialize registers here
elsif rising_edge(clock) then
-- assign registers here
end if;
end process synchronous_process_template;

However one problem with it is if there are multiple signals being
assigned, but not all of them need the reset. If not all signals are
being reset, then a gated clock is created for those signals (which
will cause some compilers to puke and is a bad idea even if it doesn't
puke). One option is to use two processes (one with reset and one
without), but that doesn't always work that well, especially if there
are variables that all signals need access to.

Here's an alternate synchronous process template...

alternate_synchronous_process_template: process(clock, reset)
begin
if rising_edge(clock) then
-- assign all registers here
end if;
if reset = '1' then
-- initialize some or all registers here
end if;
end process alternate_synchronous_process_template;

For example...

if rising_edge(clock) then
s1 <= <whatever>;
s2 <= <whatever>;
end if;
if reset = '1' then
s1 <= (others => '0');
end if;

This template makes it possible to reset signal s1 but not s2. Running
it through Xilinx tools yielded the desired RTL results (and identical
to a two-process model).

 
Reply With Quote
 
 
 
 
KJ
Guest
Posts: n/a
 
      06-15-2006
jens wrote:
> Most of us are familiar with this synchronous process template...
>
> synchronous_process_template: process(clock, reset)
> begin
> if reset = '1' then
> -- initialize registers here
> elsif rising_edge(clock) then
> -- assign registers here
> end if;
> end process synchronous_process_template;
>
> However one problem with it is if there are ...

Actually there are several problems with this 'synchronous process
template' starting with the fact that it is not synchronous....it has
an asynchronous reset input therefore it is not synchronous. The other
problem with using this as a general template is that 'most' of the
time asynchronous resets should not be used in the design at all.
People tend to forget that when the reset signal gets shut off and it
violates the setup time of the clock that darn near anything can happen
to any of the outputs of that process. Sometimes the symptoms are
benign (something shows up one clock later), other times they are not
(notably, state machines).

The reason for the more serious symptoms is violating the basic design
principle that no asynchronous input should ever go into computing the
output of more than one storage element (generally flip flops) if the
next state of those storage elements also depend on the current state.

This template should never really be used unless you know for a fact
that 'reset' is guaranteed to have a known and acceptable setup/hold
time relationship to 'clock'. If that's not the case, or if you have a
situation where 'reset' might be asserted at a time when 'clock' is not
guaranteed to be running, then it's far better to design a shift
register type of synchronizer to synchronize the reset signal before
distributing it to reset any logic. That way only the shift register
design needs the asynchronous reset 'template' and shift registers have
no inherent problems with asynchronous inputs other than metastability.

If you have multiple clock domains with things needing to be reset in
each domain, than you need to generate individual resets that are each
synchronized to the appropriate clock.

>
> Here's an alternate synchronous process template...
>
> alternate_synchronous_process_template: process(clock, reset)
> begin
> if rising_edge(clock) then
> -- assign all registers here
> end if;
> if reset = '1' then
> -- initialize some or all registers here
> end if;

end if; <-- Oops, you missed this one.
> end process alternate_synchronous_process_template;


Here's an equivalent (i.e. produces the exact same synthesis and
simulation results) but doesn't require the reader to read from the
'bottom up'.

alternate_synchronous_process_template: process(clock, reset)
begin
if rising_edge(clock) then
if reset = '1' then
-- initialize some or all registers here
elsif;
-- assign all registers here
end if;
end if;
end process alternate_synchronous_process_template;

Good points though.

KJ

 
Reply With Quote
 
 
 
 
Andy
Guest
Posts: n/a
 
      06-15-2006
KJ,

Many systems require control of outputs and/or states even in the
absence of a clock; therefore an "asynchronous" reset is required.

The setup and hold of the "asynchronous" reset need only be with
respect to the deasserting edge (i.e. reset going away). That can be
accomplished by the following:

process (rstin, clk) is
variable rstreg : std_logic;
begin
if rstin = '1' then -- active high
rstout <= '1';
rstreg := '1';
elsif rising_edge(clk) then
rstout <= rst_reg; -- registered reference to rstreg
rstreg := '0';
end if;
end process;

In the above example, rstin is the asyncrhonous system reset input, and
rstout is the asynchonously asserted, synchronously deasserted reset
signal for the rest of the registers clocked by clk, and is tied to
their async reset inputs. This would need to be repeated for each
unrelated clock.

Another option is to use rstout from above to disable the clock, either
via individual clock enables on the flops, or via the enable feature of
the xilinx clock buffer, which does it "safely". Then send rstin to
the async rst inputs of all the flops. This has the advantage of one
net for all the async resets, and multiple versions of rstout for the
various clock buffers.

Finally, even your synchronous reset template does not meet the needs
of functioning registers even when reset is active. Because of the
elsif statement, those registers that were not reset will have their
clock enable inputs deasserted when reset is active, preventing them
from updating (because the elsif section does not execute if reset is
active). There really is no good way, in one process, to avoid the
separate "if reset" statement at the bottom of the process. On the
other hand, I kind of like the reset at the bottom, since when I'm
reading the code, I'm usually more interested in what happens while not
in reset, and that comes first. On the other other hand, you don't get
those warnings about feedback muxes when you forget to include a
register in the reset clause either.

Andy


KJ wrote:
> jens wrote:
> > Most of us are familiar with this synchronous process template...
> >
> > synchronous_process_template: process(clock, reset)
> > begin
> > if reset = '1' then
> > -- initialize registers here
> > elsif rising_edge(clock) then
> > -- assign registers here
> > end if;
> > end process synchronous_process_template;
> >
> > However one problem with it is if there are ...

> Actually there are several problems with this 'synchronous process
> template' starting with the fact that it is not synchronous....it has
> an asynchronous reset input therefore it is not synchronous. The other
> problem with using this as a general template is that 'most' of the
> time asynchronous resets should not be used in the design at all.
> People tend to forget that when the reset signal gets shut off and it
> violates the setup time of the clock that darn near anything can happen
> to any of the outputs of that process. Sometimes the symptoms are
> benign (something shows up one clock later), other times they are not
> (notably, state machines).
>
> The reason for the more serious symptoms is violating the basic design
> principle that no asynchronous input should ever go into computing the
> output of more than one storage element (generally flip flops) if the
> next state of those storage elements also depend on the current state.
>
> This template should never really be used unless you know for a fact
> that 'reset' is guaranteed to have a known and acceptable setup/hold
> time relationship to 'clock'. If that's not the case, or if you have a
> situation where 'reset' might be asserted at a time when 'clock' is not
> guaranteed to be running, then it's far better to design a shift
> register type of synchronizer to synchronize the reset signal before
> distributing it to reset any logic. That way only the shift register
> design needs the asynchronous reset 'template' and shift registers have
> no inherent problems with asynchronous inputs other than metastability.
>
> If you have multiple clock domains with things needing to be reset in
> each domain, than you need to generate individual resets that are each
> synchronized to the appropriate clock.
>
> >
> > Here's an alternate synchronous process template...
> >
> > alternate_synchronous_process_template: process(clock, reset)
> > begin
> > if rising_edge(clock) then
> > -- assign all registers here
> > end if;
> > if reset = '1' then
> > -- initialize some or all registers here
> > end if;

> end if; <-- Oops, you missed this one.
> > end process alternate_synchronous_process_template;

>
> Here's an equivalent (i.e. produces the exact same synthesis and
> simulation results) but doesn't require the reader to read from the
> 'bottom up'.
>
> alternate_synchronous_process_template: process(clock, reset)
> begin
> if rising_edge(clock) then
> if reset = '1' then
> -- initialize some or all registers here
> elsif;
> -- assign all registers here
> end if;
> end if;
> end process alternate_synchronous_process_template;
>
> Good points though.
>
> KJ


 
Reply With Quote
 
KJ
Guest
Posts: n/a
 
      06-15-2006

Andy wrote:
> KJ,
>
> Many systems require control of outputs and/or states even in the
> absence of a clock; therefore an "asynchronous" reset is required.
>

I believe that is exactly what I said....what I was also said was that
'most' of the time asynchronous resets are not required and should not
be used because of the timing problems that one need to consider when
using async reset.

> The setup and hold of the "asynchronous" reset need only be with
> respect to the deasserting edge (i.e. reset going away).

Again...that's exactly what I said

> That can be
> accomplished by the following:
>
> process (rstin, clk) is
> variable rstreg : std_logic;
> begin
> if rstin = '1' then -- active high
> rstout <= '1';
> rstreg := '1';
> elsif rising_edge(clk) then
> rstout <= rst_reg; -- registered reference to rstreg
> rstreg := '0';
> end if;
> end process;
>
> In the above example, rstin is the asyncrhonous system reset input, and
> rstout is the asynchonously asserted, synchronously deasserted reset
> signal for the rest of the registers clocked by clk, and is tied to
> their async reset inputs. This would need to be repeated for each
> unrelated clock.
>

And this would be an example of a one deep shift register used to
asynchronously set 'reset' but synchronously clear it,
which...again...is exactly what I said. I'll also add here though that
the typical approach to resynchronizing async inputs is to put them
through two flops, the output of the second being the now
'synchronized' input, the output of the first having a higher
probability of being metastable than the first. Your example, of
course can be modified to add a second register, all I was saying is
that one should consider using a shift register. The depth of the
shift register would be a function of what you think the probabilities
are of metastability and how much you want to try to minimize it's
effects.

> Another option is to use rstout from above to disable the clock, either
> via individual clock enables on the flops, or via the enable feature of
> the xilinx clock buffer, which does it "safely". Then send rstin to
> the async rst inputs of all the flops. This has the advantage of one
> net for all the async resets, and multiple versions of rstout for the
> various clock buffers.
>

Good approach for Xilinx maybe others too. But has the disadvantage of
tying the code to a particular device architecture maybe a tad too
closely....and IMO tying your code to a particular vendor for something
as pedestrian as a reset signal is not a very good approach.

> Finally, even your synchronous reset template does not meet the needs
> of functioning registers even when reset is active. Because of the
> elsif statement, those registers that were not reset will have their
> clock enable inputs deasserted when reset is active, preventing them
> from updating

Not following you on this one at all. There was no clock enable, it
was simply a template that uses synchronous resets instead of async

> I'm usually more interested in what happens while not
> in reset

I am too, but I also don't like having to wade through the code only to
gete to the bottom to find that none of this applies because I happen
to have reset active....this is a 'style' thing though.
>, and that comes first.

After the two lines of code that say to check the reset first before
even bothering to look further for me, but to each his own.

KJ

 
Reply With Quote
 
Andy
Guest
Posts: n/a
 
      06-15-2006
KJ

Look again at the code I wrote; it IS a two deep shift register, with
metastability rejection built-in! Try it and see. (there is a typo, in
the reference to rst_out instead of rstout)

Your suggested solution in the case of needing a reset if the clock is
not running would not work. After you synchronize it (one or both both
edges), the fully synchronous circuits you suggest for the rest of the
chip would never respond to it without a clock! The point is, you must
have a half-synchronous reset, applied to the asynchronous resets of
your circuitry to ensure reset behavior in the absence of a clock,
combined with controlled behavior when it comes out of reset (and the
clock is active).

In your synchronous reset example, what happens if reset is active?
The elsif clause containing all the register assignments, including the
ones you don't want reset, does not execute. Therefore the synthesis
tool (synplicity) will use (not reset) as a clock enable on those
registers to prevent them from updating while reset is active.

Run your code through synthesis and see what you get...

Andy

 
Reply With Quote
 
KJ
Guest
Posts: n/a
 
      06-15-2006

Andy,

I think we're agreeing more than you might think
>
> Look again at the code I wrote; it IS a two deep shift register, with
> metastability rejection built-in! Try it and see. (there is a typo, in
> the reference to rst_out instead of rstout)

You're right, my bad it is two deep.
>
> Your suggested solution in the case of needing a reset if the clock is
> not running would not work. After you synchronize it (one or both both
> edges), the fully synchronous circuits you suggest for the rest of the
> chip would never respond to it without a clock! The point is, you must
> have a half-synchronous reset, applied to the asynchronous resets of
> your circuitry to ensure reset behavior in the absence of a clock,
> combined with controlled behavior when it comes out of reset (and the
> clock is active).
>

I don't disaree with any of that. My point was that in 'most' cases, this
control is not necessary. Asynchronous resets have their place in the bag
of tricks, but if you need a resetable flip flop it should not be your first
choice. You should use a synchronously resetable flip flop unless the
situation for whatever reason, requires the outputs to be in a particular
state even with no clock.

> In your synchronous reset example, what happens if reset is active?
> The elsif clause containing all the register assignments, including the
> ones you don't want reset, does not execute.

Understood and for 'most' cases (i.e. the ones that don't truly need to be
in any particular state immediately after reset) I would say that's just
fine. My method was simply to have the shift register essentially
'remember' that the reset came along, so that when the clock does start up,
it can provide that reset synchronously to the rest of the world. The way
it 'remembers' is that the shift register itself is asynchronously
resetable. Once the clock does start up it will still be outputing a
'reset' signal to the world that will shut off once the clock is running for
however many clocks deep I've made that shift register.

> Therefore the synthesis
> tool (synplicity) will use (not reset) as a clock enable on those
> registers to prevent them from updating while reset is active.
>

As it should, that's what the code says to do.

> Run your code through synthesis and see what you get...
>

I do, and it does just what I tell it to do

KJ


 
Reply With Quote
 
KJ
Guest
Posts: n/a
 
      06-16-2006
Oops....reset should NOT have been in the sensitivity list for my example of
a synchronous process template....apologies for the confusion.

Corrected_alternate_synchronous_process_template: process(clock)
begin
if rising_edge(clock) then
if reset = '1' then
-- initialize some or all registers here
elsif;
-- assign all registers here
end if;
end if;
end process alternate_synchronous_process_template;

KJ


 
Reply With Quote
 
Ralf Hildebrandt
Guest
Posts: n/a
 
      06-16-2006
KJ wrote:

>> Most of us are familiar with this synchronous process template...
>>
>> synchronous_process_template: process(clock, reset)
>> begin
>> if reset = '1' then
>> -- initialize registers here
>> elsif rising_edge(clock) then
>> -- assign registers here
>> end if;
>> end process synchronous_process_template;


> Actually there are several problems with this 'synchronous process
> template' starting with the fact that it is not synchronous....it has
> an asynchronous reset input therefore it is not synchronous.


Some people call a design having flipflops with asynchronous sets/resets
"partially synchronous". If you avoid this as you recommend it, it is
called "fully synchronous".


> The reason for the more serious symptoms is violating the basic design
> principle that no asynchronous input should ever go into computing the
> output of more than one storage element (generally flip flops) if the
> next state of those storage elements also depend on the current state.


Even a partially synchronous design can be reliable - even if there is
nothing known about setup/hold times in relation to the clock. The
reason is a "feature" of many circuits: Usually you have an async reset
and some /synchronous start condition/. As long as the sync start
condition is not true during reset you have plenty of time after reset
before something will happen in the design.

Example: A state machine waits for a key to be pressed. The key is
sampled and therefore this signal is synchronous. Even if the state
machine has an async reset - there is no problem.

Yes, I agree, that one has to take care if one choses a partially
synchronous or even an asynchronous (latches) design. On the other hand
you get some advantages in terms of area and (much more important) in
terms of power.

The fully synchronous design is a very good style for FPGAs, while the
asynchronous / partially synchronous design is very good for low-power
ASICs.


Ralf
 
Reply With Quote
 
Mike Treseler
Guest
Posts: n/a
 
      06-17-2006
Ralf Hildebrandt wrote:

> The fully synchronous design is a very good style for FPGAs, while the
> asynchronous / partially synchronous design is very good for low-power
> ASICs.


If I use Andy's reset pulse with
the synched trailing edge (see above)
the "partially synchronous" problem
is solved, and now I can get better
use of resources on every fpga I
have benchmarked. The data is in
the comments at the bottom of
my reference design.

-- Mike Treseler
 
Reply With Quote
 
KJ
Guest
Posts: n/a
 
      06-18-2006
>
> The fully synchronous design is a very good style for FPGAs, while the
> asynchronous / partially synchronous design is very good for low-power
> ASICs.
>

Actually the fully synchronous method that I mentioned is just as good for
low power ASICs. You're forgetting that synchronous designs work all the
way from DC (i.e. gated clocks) up to whatever is the maximum operating
frequency of the design. 'Synchronous' in no way implies a free running
clock.

If one only uses the async reset input of a flop to control the shift
register that is used to receive and then distribute the reset signals that
are now sync'ed to the appropriate clock domain (and then all other
processes using synchronous reset method) you'll consume no more power or
area or anything regardless of whether the overall design is synchronous,
gated clock or asynchronous.

KJ


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Why not mix concurrent and synchronous assignments in the same process? KJ VHDL 4 09-21-2012 01:11 PM
Re: Why not mix concurrent and synchronous assignments in the same process? Andy VHDL 3 09-11-2012 08:07 PM
Difference between synchronous (proactor pattern) and synchronous model in web server Rickert C++ 0 10-06-2011 04:54 AM
what's 'alternate' in <link rel=alternate>? Chris ASP .Net 2 03-04-2007 04:45 PM
Alternate initializers or alternate class? transfire@gmail.com Ruby 10 07-17-2006 03:20 AM



Advertisments