one hot machine without elsif

B

Brad Smallridge

Guest
I have a state machine done with one flag for each state. Most of the states
are sequential accomplished with a default assignment:

signal state : std_logic_vector(0 to 61);
begin
state<='0'&state(0 to 60);

There are some variations to the sequential flow. Elsewhere I assign data
paths to these states like this:

if state(33 to 36)>0 then
mem_out<=a;
elsif state(37)>0 then
mem_out<=b;

The elsif are a bit long and have an unnecessary priority logic to them as
state(33 to 36) trumps state(37) although I can be very sure that the states
are mutually exclusive by design.

I am of the understanding that a series of "if end if" statements would only
serve to put the priority on the last "if end if" statement and therefore
would still have priority logic.

So my question is how to get rid of the priority logic? If I have to resort
to a case statement, how do I code this succinctly with this long state
vector? And is there some other way to do it, perhaps with a variable?

Brad Smallridge
AiVision
 
On Feb 16, 5:10 pm, "Brad Smallridge" <bradsmallri...@dslextreme.com>
wrote:
I have a state machine done with one flag for each state. Most of the states
are sequential accomplished with a default assignment:

signal state : std_logic_vector(0 to 61);
begin
state<='0'&state(0 to 60);

There are some variations to the sequential flow. Elsewhere I assign data
paths to these states like this:

if state(33 to 36)>0 then
 mem_out<=a;
elsif state(37)>0 then
 mem_out<=b;

The elsif are a bit long and have an unnecessary priority logic to them as
state(33 to 36) trumps state(37) although I can be very sure that the states
are mutually exclusive by design.

I am of the understanding that a series of "if end if" statements would only
serve to put the priority on the last "if end if" statement and therefore
would still have priority logic.

So my question is how to get rid of the priority logic? If I have to resort
to a case statement, how do I code this succinctly with this long state
vector? And is there some other way to do it, perhaps with a variable?

Brad Smallridge
AiVision
The "if end if" logic should not produce "priority" logic. You can
always code a simple example, synthesize it, and then look at the
results with the synthesizer's RTL viewer.
-Dave Pollum
 
"Dave Pollum" <vze24h5m@verizon.net> wrote in message
news:f4f96b31-d418-4194-ab66-d33e01b21241@m42g2000yqb.googlegroups.com...
On Feb 16, 5:10 pm, "Brad Smallridge" <bradsmallri...@dslextreme.com>
wrote:
I have a state machine done with one flag for each state. Most of the
states
are sequential accomplished with a default assignment:

signal state : std_logic_vector(0 to 61);
begin
state<='0'&state(0 to 60);

There are some variations to the sequential flow. Elsewhere I assign data
paths to these states like this:

if state(33 to 36)>0 then
mem_out<=a;
elsif state(37)>0 then
mem_out<=b;

The elsif are a bit long and have an unnecessary priority logic to them as
state(33 to 36) trumps state(37) although I can be very sure that the
states
are mutually exclusive by design.

I am of the understanding that a series of "if end if" statements would
only
serve to put the priority on the last "if end if" statement and therefore
would still have priority logic.

So my question is how to get rid of the priority logic? If I have to
resort
to a case statement, how do I code this succinctly with this long state
vector? And is there some other way to do it, perhaps with a variable?

Brad Smallridge
AiVision
| The "if end if" logic should not produce "priority" logic. You can
| always code a simple example, synthesize it, and then look at the
| results with the synthesizer's RTL viewer.
| -Dave Pollum

Why not? The sequence of statements (in a process) below:

If x > a then
y <= j;
end if;
if x < a then
y <= k;
end if;
if x = a then
y <= m;
end if;

is equivalent to

if x = a then
y <= m;
elsif x < a then
y <= k;
elsif x > a then
y <= j;
end if;

which is clearly priority encoded. The synthesis tool may, when all
conditions are mutually exclusive, implement a balanced tree.

JTW
 
On 17 Feb., 05:42, "jtw" <wrigh...@hotmail.invalid> wrote:
"Dave Pollum" <vze24...@verizon.net> wrote in message

news:f4f96b31-d418-4194-ab66-d33e01b21241@m42g2000yqb.googlegroups.com...
On Feb 16, 5:10 pm, "Brad Smallridge" <bradsmallri...@dslextreme.com
wrote:



I have a state machine done with one flag for each state. Most of the
states
are sequential accomplished with a default assignment:

signal state : std_logic_vector(0 to 61);
begin
state<='0'&state(0 to 60);

There are some variations to the sequential flow. Elsewhere I assign data
paths to these states like this:

if state(33 to 36)>0 then
mem_out<=a;
elsif state(37)>0 then
mem_out<=b;

The elsif are a bit long and have an unnecessary priority logic to them as
state(33 to 36) trumps state(37) although I can be very sure that the
states
are mutually exclusive by design.

I am of the understanding that a series of "if end if" statements would
only
serve to put the priority on the last "if end if" statement and therefore
would still have priority logic.

So my question is how to get rid of the priority logic? If I have to
resort
to a case statement, how do I code this succinctly with this long state
vector? And is there some other way to do it, perhaps with a variable?

Brad Smallridge
AiVision

| The "if  end if" logic should not produce "priority" logic.  You can
| always code a simple example, synthesize it, and then look at the
| results with the synthesizer's RTL viewer.
| -Dave Pollum

Why not?  The sequence of statements (in a process) below:

   If x > a then
       y <= j;
   end if;
   if x < a then
       y <= k;
   end if;
   if x = a then
       y <= m;
   end if;

is equivalent to

   if x = a then
      y <= m;
   elsif x < a then
      y <= k;
   elsif x > a then
       y <= j;
   end if;

which is clearly priority encoded.  The synthesis tool may, when all
conditions are mutually exclusive, implement a balanced tree.

JTW
Hi JTW,
sorry to say, that your example is definitely not priority encoded,
because there is no possible priority in it.
x and a can have only one value at a time, so there will always only
be only one match.
The resulting hardware in both cases is a magnitude comparator (=,<,>)
for x and a connected to a mux for y.

Of course if/elsif can create prioritiy encoded hardware, but does
only if necessary.

if u = a then
y <= m;
elsif v = b then
y <= k;
elsif w = c then
y <= j;
end if;

Here it is possible that all three conditions match at the same time.
Now the synthesis tool is forced to create some hardware that disables
the lower priorized paths.

Have a nice synthesis
Eilert
 
On 16 Feb., 23:10, "Brad Smallridge" <bradsmallri...@dslextreme.com>
wrote:
I have a state machine done with one flag for each state. Most of the states
are sequential accomplished with a default assignment:

signal state : std_logic_vector(0 to 61);
begin
state<='0'&state(0 to 60);

There are some variations to the sequential flow. Elsewhere I assign data
paths to these states like this:

if state(33 to 36)>0 then
 mem_out<=a;
elsif state(37)>0 then
 mem_out<=b;

The elsif are a bit long and have an unnecessary priority logic to them as
state(33 to 36) trumps state(37) although I can be very sure that the states
are mutually exclusive by design.

I am of the understanding that a series of "if end if" statements would only
serve to put the priority on the last "if end if" statement and therefore
would still have priority logic.

So my question is how to get rid of the priority logic? If I have to resort
to a case statement, how do I code this succinctly with this long state
vector? And is there some other way to do it, perhaps with a variable?

Brad Smallridge
AiVision
Hi Brad
when you really get priority logic, it is because you are using
different slices of your state vector.
You may use a case statement instead (and some constants to make it
readable:

small example:

signal state : std_logic_vector(0 to 5);
constant : Bit_0 : std_logic_vector(0 to 5) := "100000";
constant : Bit_1 : std_logic_vector(0 to 5) := "010000";
constant : Bit_2 : std_logic_vector(0 to 5) := "001000";
constant : Bit_3 : std_logic_vector(0 to 5) := "000100";
constant : Bit_4 : std_logic_vector(0 to 5) := "000010";
constant : Bit_5 : std_logic_vector(0 to 5) := "000001";

case state is
when Bit_0 to Bit_3 => mem_out <= a;
when Bit_5 => mem_out <= b;
when others => mem_out <= (others => '0');
end case;

Have a nice synthesis
Eilert
 
May I ask why your are explicitly declaring the states? why are you
not using an enumerated type?

Otherwise, if you keep with the 1 hot method, why not extract the
range and just or the bits in the state type to mux the mem_out value?

use ieee.std_logic_misc.all; --With VHDL-2008 you dont need this

signal a_select : std_logic;
signal b_select : std_logic;

subtype aout1 is natural range 13 to 16;
subtype aout2 is natural range 24 to 26;
sybtype bout1 is natural range 31 to 36;

....

a_select <= or_reduce( state( aout1'high downto aout1'low) & state
( aout2'high downto aout2'low ) );
b_select <= or_reduce( state( bout1'high downto bout1'low) );

--Or in VHDL 2008 standard:
a_select <= or state( aout1'high downto aout1'low) & state( aout2'high
downto aout2'low ) ;
b_select <= or state( bout1'high downto bout1'low);

mem_out <= a when a_select = '1'
else b when b_select = '1'
else (others => '0');

This still implies priority, but your state type is 1 hot already, so
everything is mutually exclusive.

small example:

 signal state : std_logic_vector(0 to 5);
constant : Bit_0 : std_logic_vector(0 to 5) := "100000";
constant : Bit_1 : std_logic_vector(0 to 5) := "010000";
constant : Bit_2 : std_logic_vector(0 to 5) := "001000";
constant : Bit_3 : std_logic_vector(0 to 5) := "000100";
constant : Bit_4 : std_logic_vector(0 to 5) := "000010";
constant : Bit_5 : std_logic_vector(0 to 5) := "000001";

case state is
  when Bit_0 to Bit_3 => mem_out <= a;
  when Bit_5          => mem_out <= b;
  when others         => mem_out <= (others => '0');
end case;

Have a nice synthesis
  Eilert
Fixed:

case state is
when Bit_0 | Bit_1 | Bit_2 | Bit_3 => mem_out <= a;
when Bit_5 => mem_out <= b;
when others => mem_out <= (others => '0');
end case;
 
Brad
I have a state machine done with one flag for each state. ... snip

So my question is how to get rid of the priority logic? If I have to resort
to a case statement, how do I code this succinctly with this long state
vector? And is there some other way to do it, perhaps with a variable?
My recommendation is that you use an enumerated type based
statemachine and learn the tool switches to get it to be a one-hot.
Usually most attempts to code a one-hot loose the intent of
decoding only one bit per state.

I have tinkered with it a little and this is what I think will
work well:

-- The constants define index of the bit that indicates you
-- are in a state, rather than a vector value.
-- Most vector examples decode all state bits as reduction
-- with an X for a state vector seems to be hard.

constant READY : Integer := 3 ; -- 1000
constant SETUP : Integer := 2 ; -- 0100
constant PRE_HOLD : Integer := 1 ; -- 0010
constant HOLD : Integer := 0 ; -- 0001
signal TxState : std_logic_vector(READY downto HOLD) ;
signal TxNext : std_logic_vector(READY downto HOLD) ;

The coding template then is something like the following.
You will need to modify it if you like one-process coding
style, but this is the easy part.

TxPortSmProc : process (FifoRdy, CountZero, TxState)
begin

-- default all outputs and only set the opposite
-- value in the state - otherwise you definitely
-- have priority.
PortRdy <= '0' ;
LoadDor <= '0' ;
SelHold <= '0' ;
m1TxStb <= '1' ;
CountEnable <= '0' ;
TxNext <= "0000" ;

-- Decode READY State
if TxState(READY) = '1' then
PortRdy <= '1' ;
if (FifoRdy = '1') then
m1TxStb <= '0' ;
LoadDor <= '1' ;
TxNext(SETUP) <= '1' ;
else
TxNext(READY) <= '1' ;
end if ;
end if ;

-- Decode SETUP state
if (TxState(SETUP) = '1') then
. . .
end if ;

-- Decode SETUP state
if (TxState(PRE_HOLD) = '1') then
. . .
end if ;

-- Decode SETUP state
if (TxState(HOLD) = '1') then
. . .
end if ;
end process ; -- TxPortSmProc


If you need to decode vectors or something of that sort,
you will probably need to do explicit and-or logic. For
me this is easiest if done externally to this part of the
statemachine. Putting them internally usually ends up
with priority logic.

My observation is that getting this right usually takes
more work than most are willing to do, so it is much
easier to learn the appropriate tool switches and
use them - even though at this point they are tool
specific.

BTW, there is a standard for some of the attributes (1076.6-2004)
that set things like one-hot, but I have not checked to see
which vendors have implemented it. It would be nice to
get the vendors to implement the same thing and if
necessary modify the standard s.t. they all are happy
with it and implement it.

Cheers,
Jim

--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis SynthWorks VHDL Training http://www.synthworks.com

A bird in the hand may be worth two in the bush,
but it sure makes it hard to type.
 
May I ask why your are explicitly declaring the states?
Why are you not using an enumerated type?
That's just the way it developed. I started with a diagram
of where the memory writes should go and where the reads
should go and numbered these clock cycles.

Otherwise, if you keep with the 1 hot method,
why not extract the range and just or the bits
in the state type to mux the mem_out value?
a_select <= or_reduce( state( aout1'high downto aout1'low) & state
( aout2'high downto aout2'low ) );
b_select <= or_reduce( state( bout1'high downto bout1'low) );

Ugly.

case state is
when Bit_0 | Bit_1 | Bit_2 | Bit_3 => mem_out <= a;
when Bit_5 => mem_out <= b;
when others => mem_out <= (others => '0');
end case;
This might work if there were some function
to generate 61 states, and I knew that the
synthesizer would reduce it to one hot logic.
What I see here is a huge amount of logic.

Brad Smallridge
AiVision
 
My recommendation is that you use an enumerated type based
statemachine and learn the tool switches to get it to be a one-hot.
Usually most attempts to code a one-hot loose the intent of
decoding only one bit per state.
Why is that? In ModelSim I can expand my state vector and
jump to any state I want. ISE will push wait states into
an SLR but all the states that are used are visible.

-- default all outputs and only set the opposite
-- value in the state - otherwise you definitely
-- have priority.
PortRdy <= '0' ;
LoadDor <= '0' ;
SelHold <= '0' ;
m1TxStb <= '1' ;
CountEnable <= '0' ;
TxNext <= "0000" ;

-- Decode READY State
if TxState(READY) = '1' then
PortRdy <= '1' ;
if (FifoRdy = '1') then
m1TxStb <= '0' ;
LoadDor <= '1' ;
TxNext(SETUP) <= '1' ;
else
TxNext(READY) <= '1' ;
end if ;
end if ;

-- Decode SETUP state
if (TxState(SETUP) = '1') then
. . .
end if ;

-- Decode SETUP state
if (TxState(PRE_HOLD) = '1') then
. . .
end if ;

-- Decode SETUP state
if (TxState(HOLD) = '1') then
. . .
end if ;
end process ; -- TxPortSmProc
I don't see how this gets rid of the "if end if" issue.
Are all these "if end if" in different processes. Or is
it that you don't have any non-state assignments in your
state procedures?

Brad Smallridge
AiVision
 
Brad Smallridge wrote:

I agree with Tricky.
Unless you rewrite the code using an enumeration,
there are no pretty options.

-- Mike Treseler
 
I agree with Tricky.
Unless you rewrite the code using an enumeration,
there are no pretty options.
-- Mike Treseler
I am not sure what I gain from enumeration.

I'm not happy with VHDL for not having a easy
method for turning off these logic chains. And
case is only good for single signals.

I think I'll take this to the FPGA group who
may be more sensitive to synthesis issues.

Brad Smallridge
Ai Vision
 
On Feb 18, 5:28 pm, "Brad Smallridge" <bradsmallri...@dslextreme.com>
wrote:
I agree with Tricky.
Unless you rewrite the code using an enumeration,
there are no pretty options.
      -- Mike Treseler

I am not sure what I gain from enumeration.
Enumeration will imply mutually exclusivity, in your original post you
said "although I can be very sure that the states are mutually
exclusive by design"...'very sure' is not really the same thing. You
may already be aware (but in case you're not), the individual cases do
not have to represent the actions of a single enumeration. As an
example...
case xyz is
when This | That => -- Do things when 'This' or 'That'
when Some_Other_Thing => -- Do when 'Some_Other_Thing'
...
end case;

I'm not happy with VHDL for not having a easy
method for turning off these logic chains. And
case is only good for single signals.
In order to express logic that you can be "very sure that the states
are mutually exclusive by design" but the case statement doesn't quite
do it for you, the other method is to express it in a sum of products
form.

From your original post...
if state(33 to 36)>0 then
mem_out<=a;
elsif state(37)>0 then
mem_out<=b;

If you know for darn sure that the two conditions being tested are
mutually exclusive, then you can express this as
mem_out <= To_Std_Logic(state(33 to 36)>0) and a
or To_Std_Logic(state(37)>0) and b;

I've taken some liberties here just to clarify the point. First
'To_Std_Logic' would be a function that simply converts a boolean to a
std_logic signal. Second, as written here 'a' and 'b' would be
std_logic although I know you're probably more interested in vector
types. But you can also override the 'and' function with one of the
form

function "and" (L: std_logic; R: std_logic_vector) return
std_logic_vector

Or, if you don't want to override "and" you could create another
function that takes in a std_logic and a vector, zeroing out or
passing through the bits based on the value of the std_logic
parameter.

The basic idea I'm trying to get across is that structuring your
equations in the sum of products form allows for arbitrarily complex
conditions to be evaluated and applied and does not create any
priority encoding logic of any sort. If the conditions you specify do
not happen to actually be mutually exclusive (i.e. 'very sure' was
wrong) all that happens is that two of the 'or' terms fire (which of
course will likely corrupt the output) but that's because you erred in
assuming that things were mutually exclusive when they really were
not.

I think I'll take this to the FPGA group who
may be more sensitive to synthesis issues.

I think you'll get better answers here myself.

Kevin Jennings
 
Eilert
when you really get priority logic, it is because you are using
different slices of your state vector.
You may use a case statement instead (and some constants to make it
readable:

small example:

signal state : std_logic_vector(0 to 5);
constant : Bit_0 : std_logic_vector(0 to 5) := "100000";
constant : Bit_1 : std_logic_vector(0 to 5) := "010000";
constant : Bit_2 : std_logic_vector(0 to 5) := "001000";
constant : Bit_3 : std_logic_vector(0 to 5) := "000100";
constant : Bit_4 : std_logic_vector(0 to 5) := "000010";
constant : Bit_5 : std_logic_vector(0 to 5) := "000001";

case state is
when Bit_0 to Bit_3 => mem_out <= a;
when Bit_5 => mem_out <= b;
when others => mem_out <= (others => '0');
end case;

Have a nice synthesis
Eilert
Unfortunately this is not one-hot. With one-hot your decoder
must only decode one state bit. When you map the others
condition to all 0, you then require all 6 bits of the other
terms to be decoded. Which actually means that this is worse
than priority logic which only decodes all 6 bits for the last
bit in the equation (assuming a parallel decode of the priority).

You could instead try adding the state, ALL_ZERO:
constant : ALL_ZERO : std_logic_vector(0 to 5) := "000000";

case state is
when Bit_0 | Bit_1 | Bit_2 | Bit_3 => mem_out <= a;
when Bit_5 => mem_out <= b;
when ALL_ZERO => mem_out <= (others => '0');
when others => mem_out <= (others => 'X');
end case;

When I last tried this (some time ago), only one synthesis tool
understood what I wanted enough produce the logic and then
on the next revision, they broke it and it no longer worked.
Haven't tried it recently, but it takes real smart X mapping
to do this.

I am all for enumerated types and letting the tool do it.

Cheers,
Jim


--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis SynthWorks VHDL Training http://www.synthworks.com

A bird in the hand may be worth two in the bush,
but it sure makes it hard to type.
 
Brad,
My recommendation is that you use an enumerated type based
statemachine and learn the tool switches to get it to be a one-hot.
Usually most attempts to code a one-hot loose the intent of
decoding only one bit per state.

Why is that? In ModelSim I can expand my state vector and
jump to any state I want. ISE will push wait states into
an SLR but all the states that are used are visible.
See my follow-up post to Eilert's post as to why his proposed
coding is not one-hot.

-- default all outputs and only set the opposite
-- value in the state - otherwise you definitely
-- have priority.
PortRdy <= '0' ;
LoadDor <= '0' ;
SelHold <= '0' ;
m1TxStb <= '1' ;
CountEnable <= '0' ;
TxNext <= "0000" ;

-- Decode READY State
if TxState(READY) = '1' then
PortRdy <= '1' ;
if (FifoRdy = '1') then
m1TxStb <= '0' ;
LoadDor <= '1' ;
TxNext(SETUP) <= '1' ;
else
TxNext(READY) <= '1' ;
end if ;
end if ;

-- Decode SETUP state
if (TxState(SETUP) = '1') then
. . .
end if ;

-- Decode SETUP state
if (TxState(PRE_HOLD) = '1') then
. . .
end if ;

-- Decode SETUP state
if (TxState(HOLD) = '1') then
. . .
end if ;
end process ; -- TxPortSmProc

I don't see how this gets rid of the "if end if" issue.
Are all these "if end if" in different processes. Or is
it that you don't have any non-state assignments in your
state procedures?
The key is to get the priority off of the state decode logic.
This is accomplished by decoding only one bit.

There are limitations to what logic you can code in the statemachine.
All array handling needs to be done separately with and-or logic.
With the vectors you cited, AND-OR logic is the only way to remove
the priority logic. Any bit based logic, default it to 0 and only
set it to 1 when required.

You might be right, there may be priority from other
states that does not need to be there.

This leads us back to my original statement. One-hot coding
styles are difficult to get exactly correct (coding wise) and
some are difficult for synthesis tools to understand (due to
complex X mapping).

So why not be lazy and use an enumerated type and a tool switch,
and let the synthesis tool handle this job as it typically does
a real good job at this task.

Cheers,
Jim


--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis SynthWorks VHDL Training http://www.synthworks.com

A bird in the hand may be worth two in the bush,
but it sure makes it hard to type.
 

Welcome to EDABoard.com

Sponsor

Back
Top