state machine reset

rickman schrieb:
On Aug 15, 8:34 am, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
Rickman,

of course for a counter describing a counter is most easy and readable
way. Describing a state machine as I did can serve as a template for
much bigger ones with some good benefits.

Best regards

Wolfgang
 
On Aug 15, 8:34 am, Wolfgang Grafen <wolfgang.gra...@ericsson.com>
wrote:
KJ schrieb:

Personally, I would dispense completely with next_state and simply do
a signal assignment to 'state'. Most times the only time 'next_state'
is needed would be handled inside the case statement anyway. Less
typing, less objects to track, etc.

There is a problem with assigning to state as a signal directly:
- you see a change only in the next clock cycle but as signal transition
depends on that value you can't debug you state machine easily
I would dispute that. The value that you would see on the
"next_state" signal is the value that will appear on the "state"
signal after the clock. What does "next_state" tell you that "state"
won't?

Are you saying that you can look at the values of "next_state" other
than at the clock edge and see what input changes are causing the
output change? I don't think I have ever done that with a registered
signal, even when I did have the input value available. I think the
tools for analyzing the logic of code are pretty good and I don't see
the need for an extra variable to get this sort of insight. That
would be like using multiple signals and assignments just to be able
to see smaller pieces of the logic. Yes, I suppose that for some
people this can be a help, but I don't recall ever having a logic
problem where this was really helpful. I don't have trouble seeing
what the logic of my code is. My issue is making sure I understand
the problem enough to have selected the right logic to be coded.


- It is less readable. Where do you modify state? Easy by looking for
next_state.
That is almost silly. Where do you modify state? Easy, look for
state!


- Of course in some situations a counter can be a typing lazy
alternative BUT don't do that, you will not understand what you were
thinking a month after, and for a code review you have to talk your
mouth fuzzy that other designers will understand your work, more worse
you will have to document where plain code could be documentation
enough...
Hmmm... if you think a counter as a FSM is hard to understand, then I
think maybe you need the extra crutch of superfluous signals. If the
design of the FSM is that it gets a trigger and goes through states,
1, 2, 3, 4, 5, ... until it reaches state N and then waits for the
trigger... this will be coded as a loadable counter, not as an FSM
with enumerated states.


- The way I showed worked perfectly for designing complex state
machines in some very large ASICS, including debug and verification.

=> Lazy is not always best IMO.
There is lazy and there is making extra work. Is there some reason
that you think adding extra signals makes non-working code work? I
don't see how adding the signal for the *input* to the register in
addition to the signal for the output of the register makes anything
easier to debug. It can lead to the usage of extra logic resources.
It is common for the tool to use the clock enable of registers. If
you code the register input separately like this, it is conceivable
that it may fold the enable that would otherwise be used, into the
data input instead of the clock enable input potentially using extra
LUTs.

I just don't see an advantage to creating this extra code and logic.

Rick
 
On Aug 15, 11:49 am, jacko <jackokr...@gmail.com> wrote:
Yes moore macines are prefered,http://nibz.googlecode.comis a mealy
machine at present, but the signal which makes it so would be driven
by synchronous logic in a full design, making it finalize as a moore
machine.
I know you mean well, but making your inputs registered, does not
change a FSM from Mealy to Moore, unless of course you are considering
the entire design to be a single Moore FSM.

The difference in the two FSMs is that the Mealy model defines the
outputs in terms of both the inputs and the state (or you can say the
transitions) while the Moore model defines the outputs in terms of
just the state.

The only thing that registering your inputs buys you is avoidance of
metastability issues in the FSM.
 
jacko wrote:

Maybe it is also more correctly reflecting the formal
definitions of Moore and Mealy machines and academic work must always
be of high academic quality regardless of its industrial usefulness.

Yes moore macines are prefered, http://nibz.googlecode.com is a mealy
machine at present, but the signal which makes it so would be driven
by synchronous logic in a full design, making it finalize as a moore
machine.
I didn't say that, Svenn did.
I use a clocked process model and input synchronization.
This eliminates the "advantages" of either of these models.

Either model could be demonstrated on one process.
The question is, why demonstrate such a small
subset of what is possible?

Like mechanical cash register theory,
these models should be presented as a historical footnote,
not as a viable standard for logic description.
Well said.
I agree with this guy ;)


-- Mike Treseler

Thread recursion is getting out of hand.
Time to exit...
 
Yes a nice product of all enumerations, reduce by all inaccessable
enummrative combinations.
one hot via decode or register all. Bingo!

cheers
jacko

p.s. I say use an enumeration where possible (i.e. when bit vector
value can be any differing one).
 
On Aug 15, 1:41 pm, Wolfgang Grafen <wolfgang.gra...@ericsson.com>
wrote:
Well, the interesting thing is when you change a state for the next
transition. Allowing only one assignment to state and using next_state
for searching and looking over the text makes it more readable and
useable IMO.

state <= s8;
if state == s1 then
state <= s2;
elsif state = s2 then
state <= s3;
elsif state <= s3 then
state = s4;

or

next_state := s8;
if state == s1 then
next_state := s2;
elsif state = s2 then
next_state := s3;
elsif state = s3 then
next_state := s4;
.
.
state <= next_state;
If you enjoy the needless extra coding of a nested if-then-else tree
for a state machine, then I suppose all the extra references to state
would be a hindrance to readability.

But the solution to readability (and better/safer code too) is to use
the case statement for state machines. Then all but the original
reference to state are assignments to it, the same as all but the
final reference to next_state are assignments to it in your example.

I quit using variable/signal pairs for 'd' and 'q' years ago, and
have never wanted them back.

Andy
 
On Aug 15, 2:41 pm, Wolfgang Grafen <wolfgang.gra...@ericsson.com>
wrote:
KJ schrieb:

On Aug 15, 8:34 am, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
KJ schrieb:

Personally, I would dispense completely with next_state and simply do
a signal assignment to 'state'. Most times the only time 'next_state'
is needed would be handled inside the case statement anyway. Less
typing, less objects to track, etc.
There is a problem with assigning to state as a signal directly:
- you see a change only in the next clock cycle

Exactly as it should be, the clock causes state transitions, flip
flops to update, etc.

but as signal transition
depends on that value you can't debug you state machine easily

You only have difficulty if you compute other signals based on
'next_state', rather than 'state'. Personally I haven't had any
difficulty debugging without the 'next_state' signal.
There are reasons to compute other signals based on next_state. For
example this is how a Moore FSM can change the output without waiting
for decoding of the current state and without glitches. The clock may
run slower, perhaps, but the output can be obtained faster.

However, it is not common for speed to be the real issue in designing
a FSM. Typically readability and maintainability is often the primary
goal of FSM design. This is facilitated by other factors having to do
with coding to match your application typically.


Typically other signals/variable that are a function of the state
machine's state I compute based on the current state (i.e. the signal
'state' in this example) not on what the next state is going to be.
Typically this leads to higher clock cycle performance of the design
since the combinatorial logic that is needed to compute 'next_state'
does not roll into the logic needed to compute the output (or other
signal).

next_state will not generate logic, though :)
I have no idea what that means. If it doesn't produce logic, then you
can omit it, no?


- It is less readable.
Readability would not necessarily be a function of whether there was
an explicit 'next_state' signal/variable or not. Either form can be
just as readable. For those cases, where duplication of code would
have to take place, I would have a variable 'next_state' for assigning
to those signals that would benefit from it. That's why I said "Most
times the only time..." 'most times' does not mean 'all times', it
means 'usually the case'.

Well, the interesting thing is when you change a state for the next
transition. Allowing only one assignment to state and using next_state
for searching and looking over the text makes it more readable and
useable IMO.
That is the point. There is nothing inherently more readable about
the separated processes. I think you are just used to that. On the
other hand, the combined process has less clutter and is more concise
describing a register and the logic driving it. You don't separate
the logic for a counter from the counter register do you? I see this
as the same.

state <= s8;
if state == s1 then
state <= s2;
elsif state = s2 then
state <= s3;
elsif state <= s3 then
state = s4;

or

next_state := s8;
if state == s1 then
next_state := s2;
elsif state = s2 then
next_state := s3;
elsif state = s3 then
next_state := s4;
.
.
state <= next_state;
You have omitted the duplicated overhead of the two processes
including the need for maintaining an accurate sensitivity list. If
you over simplify the example then all coding becomes the same.


Where do you modify state?
I modify state in the state machine. There is no need to have an
intermediate signal/variable to compute the 'next_state', just so that
it can be synchronously assigned to a signal called 'state'. There is
one clocked process of the following general form:

process(clk)
begin
if rising_edge(clk) then
if (reset = '1') then
current_state <= idle;
else
case current_state is
when idle => current_state <= Michigan;
when Michigan => current_state <= California;
when California => current_state <= Hawaii;
end case;
end if;
end if;
end process;

This is a super simple state machine. Read over state machines filling
several pages, and lots of calculations within every state...
Yes, and those calculations are no different if done in one process or
two. Look at the changes needed to combine processes. It is truly a
simple job and eliminates the need for duplicating the process
overhead and maintaining a sensitivity list.


Easy by looking for next_state.
Just as easy looking for 'current_state'.

- Of course in some situations a counter can be a typing lazy
alternative BUT don't do that, you will not understand what you were
thinking a month after, and for a code review you have to talk your
mouth fuzzy that other designers will understand your work, more worse
you will have to document where plain code could be documentation
enough...

Actually you'll likely have more trouble explaining the state machine
then the counter. For example, let's say this design is for some form
of memory controller. Let's say that after issuing a read command to
the memory device you need to wait 40 ns for the data to be valid,
let's also assume that the clock period is 10 ns. One might be
tempted to make a state machine that has the proper number of states
so that 4 clock cycles after the read command is issued that data gets
sampled. Your design will be very fragile (in my opinion) because of
the implicit constants (i.e. the number of states) that are really a
function of the following parameters:
- Clock period
- Memory access time
Using a counter approach, one would have constants (actually I'd use
generic inputs on the entity) for both of these and they would be
defined in units of time and I'd define the upper end of the counter
to be the ceil() of the ratio of memory access time divided by clock
period. So it would be painfully clear where the design error is that
needs fixing when I find that the board was built with 60ns access
time parts instead of 40ns, the 'fix' would be to simply change the
generic parameter input to the entiy from 40ns to 60ns and rebuild.
With the state machine approach you'd have to modify a bunch more than
that and have a much higher risk of getting it wrong the first time.

Linking parameters that you have no control over in your design (in
this case the memory access time) so that they properly parameterize
the design will naturally lead to using counters. Hard coding in a
calculated number of states that depends on this uncontrolled
parameter (or pulse time requirement) in the form of states in a state
machine is a mistake. Although both designs will work, one will be
much more fragile and less likely to be able to be modified correctly
in the future...but that's just my 2 cents.

It depends on the problem. Where a counter is more readable use a
counter, otherwise use a state machine ...

- The way I showed worked perfectly for designing complex state
machines in some very large ASICS, including debug and verification.

And my method has worked just as perfectly.

=> Lazy is not always best IMO.

You're the one who brought up lazy, not me.

I am lazy I know :)
I don't get why you think this is any easier than one process. I
think you have done this for a long time and are just used to it. I
have my own style of indentation and I am used to it. But I don't say
it is better than any other. I just like it that way.

Rick
 
On Aug 15, 2:45 pm, Wolfgang Grafen <wolfgang.gra...@ericsson.com>
wrote:
rickman schrieb:

On Aug 15, 8:34 am, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:

Rickman,

of course for a counter describing a counter is most easy and readable
way. Describing a state machine as I did can serve as a template for
much bigger ones with some good benefits.
I'm still waiting for a description of those "good benefits". The
coding is identical other than eliminating the superfluous text. You
just type less of it...

Rick
 
On 15 Aug, 22:27, jacko <jackokr...@gmail.com> wrote:
Yes a nice product of all enumerations, reduce by all inaccessable
enummrative combinations.
one hot via decode or register all. Bingo!

cheers
jacko

p.s. I say use an enumeration where possible (i.e. when bit vector
value can be any differing one).
And ask programmer to supply all virtual inaccessable state reductions
to valid states in radio-hardened designs.

cheers
jacko
 
On Sat, 16 Aug 2008 08:27:08 -0700 (PDT),
kennheinrich@sympatico.ca wrote:

Now indulge me while I rant a little bit about the two process vs one
process approaches.
Indulgence willingly granted :)

Consider a machine with inputs Xin and current state Q, which computes
outputs Yout and next state Q'. In a Moore machine, Yout is a
function of Q, while in a Mealy, it's a function of Q and Xin.

The textbook two-process Moore approach looks like this (taking some
liberties with VHDL syntax)

-- two-process approach
process1 (clk)
Q <= Q'; -- clocked

process2 -- combinatorial
Q' <= f_next(Q,Xin);
Y <= f_out(Q);
-- end two-process approach
If you trust your synthesis tool to optimize
common sub-expressions across processes, you could
also write

process1 (clk)
Q <= f_next(Q,Xin);

process2 -- combinatorial
Y <= f_out(Q);

This has the considerable benefit that the second process
has ONLY the state in its sensitivity list, and you are
not obliged to clutter the architecture with a superfluous
next-state signal.

To simplify the code, I could simply write it as

-- one process approach
process1 (clk)
Q <= f_next(Q,Xin);
Yout <= f'_out(Q,Xin); -- where f'_out is derived from f_out above
-- end one-process approach

which is the essence of the single-process camp. Here, Xin,Yout, and Q
could be multiple signals, say bundled into a record or an array.
Unfortunately, deriving f'_out from a traditional state
diagram is troublesome and you lose the nice isomorphism
between the state diagram and the code. I don't want to
treat state diagrams as some kind of sacred cow, but there's
no doubt that they provide a very useful tool for thinking -
a stepping-stone on the path from timing diagrams to VHDL code.
The form you describe, sometimes called "registered-Mealy",
makes the jump from state diagram to VHDL rather error-prone
and hard to maintain.

I can move Y from process 1 to process 2 by changing Q to Q', and
fiddling with how I define f_out. The two are more or less isomorphic
modulo some minor timing constraints - half of the arguments on this
thread are about whether they are isomorphic or not, depending on what
assumptions you make about undefined cases.
The timing constraints thing is almost always a canard. In
every FSM I've looked at, f_out is pretty trivial and has
little impact on timing. Folding it into f_next, which
is what you must do to get f'_out, is unlikely to be
a timing show-stopper. Which leads me to a scheme
that I've proposed here before, but not so elegantly
as Kenn's exposition: MAKE Q BE A VARIABLE, not a signal,
and then...

process (clk)
variable Q: state_type;
Q := f_next(Q,Xin);
Y <= f_out(Q); -- NOTE f_out, NOT f'_out
end process;

Alternatively (equivalently, but not so easy to code):

process (clk)
Q <= f_next(Q,Xin);
Y <= f_out(f_next(Q,Xin));
end process;

The point being that the variable Q in fact holds the
value Q' after the first assignment. This form has
two advantages both of which I see as critical:
1) It gives me VHDL code that is exactly isomorphic with a
traditional state diagram.
2) It hides away the state inside the process that needs
it, whereas traditional approaches have both state and
next-state signal leaking out into the architecture, so
making its declarations complicated and hard to follow.

[...]

If I want to handle two symbols per clock, and I have already
separated my design into *functions*, I can almost trivially rewrite
my state machine thus:

process1(clk) -- clocked
Q <= f_next(f_next(Q,Xin1), Xin2);
Yout1 <= f_out(Q,Xin1);
Yout2 <= f_out(f_next(Q), Xin2);
-- all done!
Nice idea.

[...]

Clearly, you can't ignore the combinatorial complexity and hence the
time penalty per clock cycle that may come from this.
But, as I've said, if f_out is as simple as it usually is
then this is unlikely to be an issue in the real world.

In my humble opinion, this is how the separation of concerns *ought*
to be presented: as one process, with functions.
Yes. In practice I usually write f_next and f_out as case
statements switching on the state, but there is absolutely no
reason why this must be so. In some situations it's nicer to
have your case statement switch on the value of Xin. And
sometimes neither of those is quite right. Once you're writing
code like that, you soon begin to see how impoverished the
state diagram notation is as a way of describing sequential
activity - it's just too hard and messy to give similar
behaviours to several different states, for example, whereas
that's trivially easy when writing code. Hence my general
distaste for graphical FSM entry tools.

OK, I'll shut up now :) Soapbox mode off.
Shame - I was enjoying it :)
--
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.bromley@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.
 
For what it's worth, I'm with Mike and company about using a single
process for state machines. In my experience, if a state machine is
so complex that you can't maintain, change, or debug it (and you think
you want to debug it using a separate next_state variable), you have a
very basic problem: that your state machine is too complex. In that
case, you need to look at factoring the state machine into interacting
sub-machines, or taking a step back and rethinking how your design
works, or do something else creative. In some cases, the machine
really *is* a beast from hell, and you might want to generate the
state machine transitions from another higher level of synthesis (a C
program or a script, assuming you know how) where you can abstract and
express the design intent more clearly, or even use one of those
dreaded fancy GUI tools (shudder...). Or whatever gets you to a
simpler, more understandable, easier to maintain design.

Now indulge me while I rant a little bit about the two process vs one
process approaches.

It makes a lot of sense to me, that the two-process machine is a
throwback to a slavish adherence to the Moore/Mealy behaviour
dichotomy that came out of 1950's era mathematics. And I think it was
done wrong, way back in the 1980's, at the beginning of VHDL tutorials
and examples. However, I can see how separating the next state and
output computation from the clocking process makes sense, but *not* in
the naive two-process "digital design 101" style.

Consider a machine with inputs Xin and current state Q, which computes
outputs Yout and next state Q'. In a Moore machine, Yout is a
function of Q, while in a Mealy, it's a function of Q and Xin.

The textbook two-process Moore approach looks like this (taking some
liberties with VHDL syntax)

-- two-process approach
process1 (clk)
Q <= Q'; -- clocked

process2 -- combinatorial
Q' <= f_next(Q,Xin);
Y <= f_out(Q);
-- end two-process approach

To simplify the code, I could simply write it as

-- one process approach
process1 (clk)
Q <= f_next(Q,Xin);
Yout <= f'_out(Q,Xin); -- where f'_out is derived from f_out above
-- end one-process approach

which is the essence of the single-process camp. Here, Xin,Yout, and Q
could be multiple signals, say bundled into a record or an array.

I can move Y from process 1 to process 2 by changing Q to Q', and
fiddling with how I define f_out. The two are more or less isomorphic
modulo some minor timing constraints - half of the arguments on this
thread are about whether they are isomorphic or not, depending on what
assumptions you make about undefined cases.

The key idea here is separating f_next from the process1 assignment.
One reason I want to do this, is to support one critical speed
optimization that I might want to do, which is to handle multiple
inputs on a single clock cycle. In the context of a reactive state
machine, where you can't take liberties with time, this makes little
or no sense. But consider a state machine which decodes MPEG VLC
(Huffman codes) or operates sequentially on an independent input
stream, like a DSP stream processor. If you can handle multiple inputs
per clock, you come out ahead (modulo the act of increased
combinatorial complexity delay affecting minimum clock cycle time).

If I want to handle two symbols per clock, and I have already
separated my design into *functions*, I can almost trivially rewrite
my state machine thus:

process1(clk) -- clocked
Q <= f_next(f_next(Q,Xin1), Xin2);
Yout1 <= f_out(Q,Xin1);
Yout2 <= f_out(f_next(Q), Xin2);
-- all done!

This is a little trickier with Mealy machines, and of course, in some
cases it's not apparent what multiple output events (Y1 and Y2) mean,
but that's a different problem. The idea I'm trying to convey is that
I can string together output functions and next state functions to
modify the behaviour of the machine easily, at a very high level (for
example,doing a one-input per clock to a two-input per clock change).

The key idea is that the computation of f_next and f_out, and the
actual flop assignments, are separated. In my case one in functions
and one in a process. In the two-process approach, by two processes in
which the functions f_next and f_out are still hard-coded.

Clearly, you can't ignore the combinatorial complexity and hence the
time penalty per clock cycle that may come from this. And I'll admit
that this example is a little contrived, but it makes perfect sense
when related to the mathematical viewpoint of automata, from which the
Moore/Mealy dichotomy developed. This is just the VHDL version of
"lifting" the state transition function from a single symbol in an
input alphabet to finite-length strings on the the alphabet.

In my humble opinion, this is how the separation of concerns *ought*
to be presented: as one process, with functions. Then view the single
process approach as writing the function bodies in-line. The two-
process approach is a bastard stepchild of the single-process, more
functional approach. But the ugly stepchild has been allowed to breed
and corrupt the young people of today nonetheless :)

OK, I'll shut up now :) Soapbox mode off.

- Kenn
 
On Aug 16, 12:46 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
process (clk)
variable Q: state_type;
Q := f_next(Q,Xin);
Y <= f_out(Q); -- NOTE f_out, NOT f'_out
end process;
Without getting into the whole issue of state machine descriptions, I
want to understand your use of variables better.

I have not found the need to use variables in the past to any degree
as I try to work simply and use a minimum subset of the language to
facilitate code reuse and ease of maintenance (by others as well as
myself). But I can see where variables may have some useful
applications.

Looking at your code, it see where it appears that it would produce
the registers you describe, and at that same time allow the input to
the register Q to be used in the expression for Y. But when I look at
one of my books, I see a very different example.

architecture version1 of circuit is
signal Q1, Q2: std_logic;
begin
process (Clk)
variable tmp1, tmp2: std_logic;
begin
if rising_edge(Clk) then
tmp1 := A and B; -- the definition of A and B in the port
definition is assumed
tmp2 := Q1 and C;
end if;
Q1 <= tmp1;
Q2 <= tmp2;
end process;
end version1;

I find this example to be very difficult to understand. I don't
understand why the assignments to Q1 and Q2 are done outside of the
clocked if structure. I would have expected tmp2 to be tmp1 and C,
not Q1 and C. The logic diagram shown for this example shows tmp1
(combinatorial logic which is the input to register Q1) as an input to
tmp2. Considering that Q1 is a signal and does not get updated until
the process exits, I don't see how this can produce the logic shown.

I found in another book that "For synthesis, it would not matter if
the assignments to Var1 and Var2 were swapped over"...

Var2 := Var1 and D;
Y1 <= not Var2;
Var1 := A and B and C; - A, B, C and D are inputs, Y1 is an output to
the entity

I would think that this reversed order of assigning and using Var1
would produce a register, but then it is not a clocked process so I
guess it will be a latch, no?

I think this is why I don't use variables. If I don't use a feature a
lot, I don't remember the details and then get it messed up when I do
try to use it.

Rick
 
Jonathan Bromley wrote:

Unfortunately, deriving f'_out from a traditional state
diagram is troublesome and you lose the nice isomorphism
between the state diagram and the code. I don't want to
treat state diagrams as some kind of sacred cow, but there's
no doubt that they provide a very useful tool for thinking -
a stepping-stone on the path from timing diagrams to VHDL code.
It was an very useful tool for manual synthesis
and simulation in the previous century.
It is much less compelling now,
when I can trace code, edit the offending line,
and rerun simulation waveforms or assertions
in less than a minute.

....
Which leads me to a scheme
that I've proposed here before, but not so elegantly
as Kenn's exposition: MAKE Q BE A VARIABLE, not a signal,
Now you've let the cat out of the bag.
If designers learn that C-like variables can make
registers, this newsgroup will become a ghost town ;)


-- Mike Treseler
 
Hi

I've only ever used variables indirectly with generate, or maybe these
are generics or parameters, or indexes, or just plain symbolic things.
I have never used variables.

I understand that the benefits are:
Localization: No signals in architecture body, and name reuse
confusion possibilities.
Automatic Registration: Use before assign, register reduction to latch
on non-clocked (lots of unsafe latch behaviour warnings, data and
enable driven by same logic).

In some ways the use of a process body, is unnecessay as signal
assignment works outside processes. for generate complains if I place
it in a process. Process is basically an encapsulation. functions are
another kind of encapsulation for shortening common expressions. I was
really suprised to find I could not declare local signals in a
process.

Just a convinience to convert software algorithms to hardware.

cheers
jacko
 
rickman wrote:

I find this example to be very difficult to understand.
I agree. It's just two gates and two flops!

Some reasons why

[] the example declares and uses unneeded signals
[] example does not demonstrate a single advantage to using variables
[] variables are poorly named
[] variables are used only as wires (left before right)

The version below is still silly, but is readable.

library ieee;
use ieee.std_logic_1164.all;
entity var is
port (Clk : in std_ulogic;
A : in std_ulogic;
B : in std_ulogic;
C : in std_ulogic;
Q1 : out std_ulogic;
Q2 : out std_ulogic);
end entity var;
architecture synth0 of var is
begin
process (Clk)
variable q1_v : std_ulogic;
variable q2_v : std_ulogic;
begin
if rising_edge(Clk) then
q1_v := A and B; -- right before left
q2_v := q1_v and C; -- means no regs here
end if;
Q1 <= q1_v; -- output register
Q2 <= q2_v; -- output register
end process;
end synth0;

A better example would make use of the fact
that variable values can be used immediately:

http://mysite.verizon.net/miketreseler/stack.vhd

-- Mike Treseler
 
Mike Treseler wrote:

if rising_edge(Clk) then
q1_v := A and B; -- right before left
---------------------------------- left before right!!!
q2_v := q1_v and C; -- means no regs here
Dooh.
Make that
1. left before right means no register.
2. right before left" infers a register.

Not a very convincing argument about how easy this is ;)
I think of [2] as "save the value for next time"

Now, note that if I reverse these two variable assignments,
that q1_v becomes a register output and the
and gates are pipelined, making the example
slightly more interesting.

-- Mike Treseler
 
On Sat, 16 Aug 2008 22:23:20 -0700, Mike Treseler wrote:

process (Clk)
variable q1_v : std_ulogic;
variable q2_v : std_ulogic;
begin
if rising_edge(Clk) then
q1_v := A and B; -- right before left
q2_v := q1_v and C; -- means no regs here
end if;
Q1 <= q1_v; -- output register
Q2 <= q2_v; -- output register
end process;
I know that people do this, but it strikes me as
being distinctly weird. Q1, Q2 get updated (admittedly
without any change of value) on the INACTIVE clock edge
as well as the active clock edge. The simulation
behaviour would be identical if you were to move
the signal assignments inside the if statement.

I am aware that synthesis tools have not always done
the necessary register merging in this situation,
and I suspect that putting the final signal assignments
outside the if statement is effectively a hack to give
the synthesis tool an appropriate hint. But it means
that Q1 and Q2 no longer follow the proper synthesis
template.

You've stung me into action: I'll try to get some hard
data about how synth tools handle this, and report back.
rickman's position - that variables are potentially
useful, but also potentially too confusing - is obviously
rather well supported by this kind of uncertainty.
--
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.bromley@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.
 
rickman wrote:

begin
if rising_edge(Clk) then
q1_v := A and B; -- right before left
q2_v := q1_v and C; -- means no regs here
end if;
Q1 <= q1_v; -- output register
Q2 <= q2_v; -- output register
end process;
end synth0;

This still is not clear to me. Why are the signal assignments outside
of the clocked if condition? But they are inside the clocked
process! To me, this is un-synthesizable as it is describing a
register clocked on both edges.
No. It may waste some sim cycles, but since
I only put port wires here, the fact
that the assignment is updated unnecessarily
on the falling clock, does not change any outputs.
The reason for the odd placement does not
make any sense until you try to add reset.

I explain this in the comments of my reference
design. When I add an asynch reset,
I have two choices for a template the works for
both the clock edge and the reset level.
The first template avoids having to duplicate
the port update code. The second is easier to read.

----------------------------------------------------------
procedure template_v_rst is
begin -- equivalent to a_rst below for synthesis.
if reset = '1' then
init_regs;
elsif rising_edge(clock) then
update_regs;
end if;
update_ports;
end procedure template_v_rst;
----------------------------------------------------------
procedure template_a_rst is
begin -- equivalent to v_rst for synthesis.
if reset = '1' then
init_regs;
update_ports;
elsif rising_edge(clock) then
update_regs;
update_ports;
end if;
end procedure template_a_rst;


Since I write "update_ports" as a procedure
anyway, I guess I have no good reason for preferring
the first template.

-- Mike Treseler
 
On Aug 17, 1:23 am, Mike Treseler <mtrese...@gmail.com> wrote:
rickman wrote:
I find this example to be very difficult to understand.

I agree. It's just two gates and two flops!

Some reasons why

[] the example declares and uses unneeded signals
[] example does not demonstrate a single advantage to using variables
[] variables are poorly named
[] variables are used only as wires (left before right)

The version below is still silly, but is readable.

library ieee;
use ieee.std_logic_1164.all;
entity var is
port (Clk : in std_ulogic;
A : in std_ulogic;
B : in std_ulogic;
C : in std_ulogic;
Q1 : out std_ulogic;
Q2 : out std_ulogic);
end entity var;
architecture synth0 of var is
begin
process (Clk)
variable q1_v : std_ulogic;
variable q2_v : std_ulogic;
begin
if rising_edge(Clk) then
q1_v := A and B; -- right before left
q2_v := q1_v and C; -- means no regs here
end if;
Q1 <= q1_v; -- output register
Q2 <= q2_v; -- output register
end process;
end synth0;
This still is not clear to me. Why are the signal assignments outside
of the clocked if condition? But they are inside the clocked
process! To me, this is un-synthesizable as it is describing a
register clocked on both edges. I guess the fact that the variables
which are the register inputs are only updated on the rising edge
means the signals can only change on the rising edge as well, but it
just looks "bad" to me. But like you said, it does not illustrate a
reason to use variables. I guess it was just intended as a minimal
example to show how variables work, but still, I don't understand this
construct.

Another book is a little better, but a third is nearly as poor showing
only two trivial examples with no info on *why* they should be used.
A fourth focuses on the mechanics of how a variable differs from a
signal showing the updating with time and delta delays, but again
nothing on the *why*.

Rick
 
On Sat, 16 Aug 2008 17:33:22 -0700 (PDT), jacko wrote:

In some ways the use of a process body, is unnecessay as signal
assignment works outside processes. for generate complains if I place
it in a process. Process is basically an encapsulation. functions are
another kind of encapsulation for shortening common expressions. I was
really suprised to find I could not declare local signals in a
process.
I think you are perhaps labouring under many misapprehensions
about the way VHDL is specified to work.

VHDL's discrete-event model of computation is *entirely* based
on processes in which procedural code executes, and signals
which communicate information and events from process to
process. The idea that processes are "unnecessary" is absurd.
I guess you are thinking of concurrent signal assignment and
component instantiation, but in reality these are both ways
to describe a process. For example, the concurrent assignment

Y <= f(some_signals);

is by definition identical to the process

process (some_signals)
begin
Y <= f(some_signals);
end process;

And an entity/architecture pair is just a way to encapsulate
a collection of processes so that you can instantiate it
as a single item, which then looks like one big process.

Functions and procedures, as you suggest, are encapsulation
for a collection of procedural code; the subprogram then
can be used in procedural code. Architectures (and blocks,
and generate statements) are encapsulation for a collection
of processes; they can then be used as if they were processes.

A process encapsulates procedural code so that it can be used
as a concurrent statement. There is no way to go the other
direction; you can't take concurrent statements and somehow
put them into a process. Contrast this with, for example,
CSP in which concurrent statements can be freely composed
into sequential statements and vice versa.

[processes are]
Just a convinience to convert software algorithms to hardware.
Nonsense.
--
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.bromley@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.
 

Welcome to EDABoard.com

Sponsor

Back
Top