synthesizing 'rightof or 'succ

N

Neha

Hi.
I have an FSM with 32 states. States 0, 1 and 31 are unique, and the
rest are basically doing the same thing.
...so I wrote the code using case statements like this:

case state is

when t0=>--somecode....
state<=t1;

when t1=>--somecode....
state<=t2;

when t2 to t30=>
state<=state_type'succ(state) --or state<=state_type'rightof(state)
--somecode

when t31=>
state<=t0;
--somecode

However, Xilinx ISE doesn't synthesize 'rightof or 'succ. Is there any
way to overcome this? I don't want to copy the same code for each
state.

Thanx.
Neha
 
M

Mike Treseler

Neha said:
when t2 to t30=>
state<=state_type'succ(state) --or state<=state_type'rightof(state)
--somecode

when t31=>
state<=t0;
--somecode

However, Xilinx ISE doesn't synthesize 'rightof or 'succ. Is there any
way to overcome this? I don't want to copy the same code for each
state.

Consider using a counter rather
than a case.

-- Mike Treseler
 
J

Jonathan Bromley

I have an FSM with 32 states. States 0, 1 and 31 are unique, and the
rest are basically doing the same thing.

As Mike said, it's probably best to use a counter to cope
with this kind of thing.

I usually prefer to have a downcounter and leave it counting
unconditionally, synchronously loading it with a timeout value
whenever necessary. This commonly gives rise to more compact
and cleaner logic than a FSM that decrements the counter in
various different places - although these days the tools are
pretty good at recognising such shareable increment/decrement
operations.

My code would look something like this. Note the use of a
variable (even though it's not terribly convenient) to
hide away the downcounter entirely within the process
that needs it.

...
process (clock, reset)
variable timer, next_timer: unsigned(...);
begin
if reset = '1' then
--- do all your resets, including...
state <= t0;
timer := to_unsigned(0, timer'length);
elsif rising_edge(clock) then
next_timer := timer - 1; -- count down, by default
case state is
when t0 =>
.....
state <= t1;
when t1 =>
..... make decision to go into timed state tt
state <= tt;
next_timer := to_unsigned(DELAY, timer'length);
when tt =>
if timer = 0 then
-- timer has run to completion
state <= t31;
end if;
when t31 =>
...
end case;
timer := next_timer;
end if;
end process;

An alternative would be to write your own SUCCESSOR() function
and use that in place of 'SUCC. This function would be quite
clunky, but it would at least hide away all the messy detail
so that you can get the desired effect in your FSM.
--
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
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
N

Neha

Just a question: If i were to go on and type the same code for each
state, will the synthesized logic be lesser than if I had a counter?
The tool is doing one-hot encoding for this FSM
*Why is the encoding one-hot most of the times and rarely
binary?

Thanks,
Neha
(M.Tech Student)
 
M

Mike Treseler

Neha said:
Just a question: If i were to go on and type the same code for each
state, will the synthesized logic be lesser than if I had a counter?

No, the code is just easier to read.
Counters, shifters, states etc
as just variables that are updated
on every rising edge using different procedures.
See Amit's recent postings regarding
coding a shift register as a case.
The tool is doing one-hot encoding for this FSM
*Why is the encoding one-hot most of the times and rarely
binary?

Quartus and ISE default to "AUTO" encoding
which usually means binary for up to 4 states
and one-hot otherwise. There is only a very
small advantage for one-hot in the large cases
I have tested. On the rare occasion when I have
to encode a case, I use binary as
it is easier to keep track of.
But synthesis does a good job at this, so
I usually just leave it set to AUTO.

-- Mike Treseler
 
K

KJ

Neha said:
However, Xilinx ISE doesn't synthesize 'rightof or 'succ. Is there any
way to overcome this? I don't want to copy the same code for each
state.
Besides the work arounds that have been suggested, you should probably open
a web case to Xilinx to fix their tool to properly support this. Work
arounds are fine to get one going where the tool falls flat so your design
is not halted by this failure, but Xilinx should be held to task for not
supporting this perfectly valid language construct....and like all suppliers
they respond to complaints so even if there fix isn't in time for you on
this project, you'll be doing your part to help them improve their tool.
Down the road it will be helping others and maybe yourself in the future.

KJ
 
A

Andy

I wholeheartedly agree with Jonathan's use of a variable to hide/
protect the counter in the process that uses it. I would extend that
to the state as well if it is not accessed outside the process (which
I would consider poor design if it was).

Another approach to the timer/next_timer pair is to have a timer and a
timeout variable instead (note that timeout does not become a
register, it just uses a registered reference to timer).

And if you are having to load the timer from an integer constant, just
go ahead and make the timer an integer itself.

variable timeout : boolean;
variable timer : integer range 0 to MAX_TIME - 1;
....
elsif rising_edge(clk) then
timeout := timer - 1 < 0; -- reuse carry bit
timer := (timer - 1) mod MAX_TIME; -- rollover
end if;
case state is
when t0 =>
.....
state <= t1;
when t1 =>
..... make decision to go into timed state tt
state <= tt;
timer := DELAY;
when tt =>
if timeout then
-- timer has run to completion
state <= t31;
end if;
when t31 =>
...
end case;
end if;
 
M

Mike Treseler

Neha said:
I have an FSM with 32 states. States 0, 1 and 31 are unique, and the
rest are basically doing the same thing.
..so I wrote the code using case statements like this:
case state is
when t0=>--somecode....
state<=t1;
when t1=>--somecode....
state<=t2;
when t2 to t30=>
state<=state_type'succ(state) --or state<=state_type'rightof(state)
--somecode
when t31=>
state<=t0;
--somecode

After seeing the other examples, and
rereading your original question above,
It sounds to me that you might be able
to decode a rollover counter directly,
something like this:

http://home.comcast.net/~mike_treseler/cnt_decode.vhd


-- Mike Treseler
 
P

Paul Uiterlinden

Mike Treseler wrote:

After seeing the other examples, and
rereading your original question above,
It sounds to me that you might be able
to decode a rollover counter directly,
something like this:

http://home.comcast.net/~mike_treseler/cnt_decode.vhd

Which says:
cnt_v := cnt_v + 1;
case cnt_v is
when 0 | 1 =>
somecode;
when 31 =>
somecode;
cnt_v := 0;
when others => null;
end case;

Why not:
cnt_v := cnt_v + 1;
case cnt_v is
when 0 | 1 | 31 =>
somecode;
when others => null;
end case;
if cnt_v = 31 then
cnt_v := 0;
end if;

I would prefer that because "somecode" is not duplicated.
 
M

Mike Treseler

Paul said:
Which says:
cnt_v := cnt_v + 1;
case cnt_v is
when 0 | 1 =>
somecode;
when 31 =>
somecode;
cnt_v := 0;
when others => null;
end case;

Why not:
cnt_v := cnt_v + 1;
case cnt_v is
when 0 | 1 | 31 =>
somecode;
when others => null;
end case;
if cnt_v = 31 then
cnt_v := 0;
end if;

I would prefer that because "somecode" is not duplicated.

Very clean on the when line.
Oh, but now case 31 is duplicated.
I can't decide :)

Back to the salt mines.

-- Mike Treseler
 
M

Mike Treseler

Paul said:
I can. Didn't you see that "somecode" is actually 42 lines? ;-)

Unless it is a procedure id in a single process entity.
This may look inefficient, but it makes no difference
to synthesis.

-- Mike Treseler
 
P

Paul Uiterlinden

Mike said:
Unless it is a procedure id in a single process entity.

I don't want to play with you anymore. You are cheating.
Go back into your salt mines. ;-P
This may look inefficient, but it makes no difference
to synthesis.

Yep, even not for simulation.
 
N

Neha

I wholeheartedly agree with Jonathan's use of a variable to hide/
protect the counter in the process that uses it. I would extend that
to the state as well if it is not accessed outside the process (which
I would consider poor design if it was).

*** Why is it poor design to declare state as signal instead of
variable? It won't necessarily lead to better synthesis...and I
wouldn't be able to observe the state in simulation waveforms.
 
M

Mike Treseler

Neha said:
*** Why is it poor design to declare state as signal instead of
variable?
It isn't poor design, it is a different style of design.
It is easier for me to write sequential code
using functions and procedures.
For this style, variables are essential.
Many designers don't care about this at all,
and design with a netlist-oriented style.
This works fine also.
It won't necessarily lead to better synthesis...and I
wouldn't be able to observe the state in simulation waveforms.

This is not true. All of the waveforms labeled with _v
in the pdf below are modelsim waveforms.
http://home.comcast.net/~mike_treseler/uart_zoom.pdf

-- Mike Treseler
 
K

KJ

*** Why is it poor design to declare state as signal instead of
variable? It won't necessarily lead to better synthesis...and I
wouldn't be able to observe the state in simulation waveforms.

It's a matter of opinion whether or not hiding things within the
architecture of a given entity is 'poor design' or not. In my
opinion, the VHDL notion of design hierarchy is the entity, when a
particular entity/architecture has grown to be 'too big' or 'too
complicated' it should be re-factored and broken down into sub-
entities. Within a given entity/architecture though, my opinion is
that individual processes are all working towards the same goal and
should have access to everything so the notion of hiding things by
virtue of the scoping rules (i.e. variables are not accessible outside
that process) is counterproductive to getting a design task completed
because of the loss of visibility in the debug process. Hiding
signals by not making them available to sub-entities in a hierarchical
design (unless they are needed of course) accomplishes the same thing
without getting persnickety about the whole idea of localizing usage
of signals/variables.

The obvious downside (as you've already noticed) to variables is that
they can not be observed in wave windows, list windows, whatever after
the fact (i.e. you're trying to debug a problem and are working back
in time). They can be added and viewed going forward, but not going
back in time (at least not with Modelsim). That to me is a big
drawback, others don't mind recomputing (possibly incorrectly) the
value that a variable must have had based on the signals that can be
viewed. Again, that to me seems counterproductive to getting a task
completed. I do use variables, but not as extensively as others in
this group but my reason for using a variable has never been just
because I didn't want some other process in that same entity/
architecture to be able to access it.

KJ
 
M

Mike Treseler

KJ said:
But only if you wave the variables ahead of time. There is no
equivalent that I know of to "log -r /*" that will pick up variables
so that they can be waved at some later sim time and see the complete
history of that variable up to that sim time.

That is true.
log -r /*
covers the uut and testbench port only.
I have to log the process of interest to see the variables.

For your example I would have to say:
log /test_uart/dut/main/*
to cover the variables then
add wave test_uart/dut/main/*
to see the history.

I actually just add all the waves in a do file like this
http://home.comcast.net/~mike_treseler/uart.do
any time I run a sim.

-- Mike Treseler
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top