![]() |
|
|
|||||||
![]() |
VHDL - alternate synchronous process template |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
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). jens |
|
|
|
|
#2 |
|
Posts: n/a
|
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 KJ |
|
|
|
#3 |
|
Posts: n/a
|
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 Andy |
|
|
|
#4 |
|
Posts: n/a
|
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 KJ |
|
|
|
#5 |
|
Posts: n/a
|
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 Andy |
|
|
|
#6 |
|
Posts: n/a
|
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 KJ |
|
|
|
#7 |
|
Posts: n/a
|
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 KJ |
|
|
|
#8 |
|
Posts: n/a
|
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 Ralf Hildebrandt |
|
|
|
#9 |
|
Posts: n/a
|
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 Mike Treseler |
|
|
|
#10 |
|
Posts: n/a
|
>
> 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 KJ |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Asynchronous process from asp.net page button click event? | Ritha | Software | 0 | 09-29-2009 03:20 PM |
| Recycle Worker Process Not Working | JAB | Software | 0 | 09-04-2008 05:22 PM |
| Looking for 2-up CD label software or template | M.L. | DVD Video | 14 | 05-31-2007 01:49 AM |
| A+ Exam Revision Update Process Starting | John P. Dearing | A+ Certification | 6 | 02-10-2006 01:44 AM |
| Burn process failed - help! Log file posted for help troubleshooting | Michael Mason | DVD Video | 1 | 08-16-2004 09:24 PM |