![]() |
|
|
|||||||
![]() |
VHDL - Re: Mixed clocked/combinatorial coding styles |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
On Aug 18, 11:53 am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote: > OK, so I tried the following synthesis example - > various declarations omitted to save space. > 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. > > ~~~~~~~ > 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. 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 rickman |
|
|
|
|
#2 |
|
Posts: n/a
|
On Aug 18, 4:38 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote: > On Mon, 18 Aug 2008 11:39:42 -0700 (PDT), rickman wrote: > >> 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? 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! > > 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. 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 rickman |
|
|
|
#3 |
|
Posts: n/a
|
rickman 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??? 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 Mike Treseler |
|
|
|
#4 |
|
Posts: n/a
|
KJ <> writes:
> 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 <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 -- TRW Conekt - Consultancy in Engineering, Knowledge and Technology http://www.conekt.net/electronics.html Martin Thompson |
|
|
|
#5 |
|
Posts: n/a
|
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 rickman |
|
|
|
#6 |
|
Posts: n/a
|
On Aug 21, 2:01 am, Kim Enkovaara <kim.enkova...@iki.fi> wrote:
> rickman wrote: > > On Aug 20, 9:45 am, KJ <kkjenni...@sbcglobal.net> wrote: > >> On Aug 18, 5:23 pm, rickman <gnu...@gmail.com> wrote: > > > 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 > > 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. 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 rickman |
|
|
|
#7 |
|
Posts: n/a
|
On Aug 21, 8:32*am, rickman <gnu...@gmail.com> wrote:
> On Aug 21, 2:01 am, Kim Enkovaara <kim.enkova...@iki.fi> wrote: > > > 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. > > But this requires the global set reset signal. *That is how the FFs > get their initial state. > 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 KJ |
|
|
|
#8 |
|
Posts: n/a
|
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 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 Andy |
|
|
|
#9 |
|
Posts: n/a
|
On Aug 21, 9:35*am, Andy <jonesa...@comcast.net> wrote:
> 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 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 KJ |
|
|
|
#10 |
|
Posts: n/a
|
rickman wrote:
> 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 Mike Treseler |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| OT: Blu-Ray Region Coding | RL | DVD Video | 11 | 12-11-2007 04:04 AM |
| Blockbuster Wants Region Coding To End. | Scot Gardner | DVD Video | 31 | 12-13-2003 02:45 AM |
| Re: The purpose of dvd region coding? | Shouse | DVD Video | 1 | 09-02-2003 05:47 PM |
| Re: The purpose of dvd region coding? | keved | DVD Video | 0 | 08-31-2003 05:11 AM |
| Re: The purpose of dvd region coding? | Mobutu | DVD Video | 0 | 08-31-2003 03:54 AM |