custom types in process sensitivity list

R

Roger Dahl

Guest
Hi all,

I've just started playing around with VHDL and I'm having trouble
solving a particular problem.

I have two FSMs. FSM A is clocked at a slow speed and FSM B is clocked
at a fast speed. I would like FSM B to cycle through all its states
each time FSM A changes state. The states for each FSM is declared as
a type.

Is there a standard solution to this kind of problem?

One solution that I have been trying to implement involves having a
third process that sets a signal when FSM A changes state and clears
the signal when FSM B changes state. That signal would be used for
telling FSM B to start going.

I have tried to implement that process like this:

process(CurrentFSM_A_State, CurrentFSM_B_State)
begin
[if triggered by A, set signal. if triggered by B, clear signal]...
end process;

However, I am unable to determine within the process if it was
triggered by CurrentFSM_A_State or CurrentFSM_B_State. rising_edge()
etc doesn't work since the signals are types, not single signals.

Any help would be greatly appreciated.

Roger Dahl
 
Hi Roger

Is this intended for hardware, or just for simulation? If it is just for
simulation, then the simple answer is use the 'event attribute -

process(FSM_A_State , FSM_B_State)
begin
if (FSM_A_State'event) then

elsif (FSM_B_State'event) then

end if;
end process;

However, if you ever want to build hardware, then this will not work - could
you draw the schematic resulting from the above code? There are various
ideas for solving your problem -

Clock both FSMs at the faster clock, but use a clock enable to only activate
the slower FSM once per cycle of the faster one. I haven't tested the
following, but it should illustrate my idea -
type FSM_A_States is (FSM_A_State1 , FSM_A_State2 , FSM_A_State3 ,
Do_Cycle_Of_B)
type FSM_B_States is (FSM_B_State1 , FSM_B_State2 , FSM_B_State3)

and in your fsms:
process(Clock , Reset)
begin
if (Reset = 1) then
State_A = FSM_A_State1;
State_B = FSM_B_State1;
elsif (Rising_Edge(Clock)) then
if (State_A = Do_Cycle_Of_B) then
State_B <= Next_State_B;
end if;

State_A <= Next_State_A;
end if;
end process;

There are various horrible async. solutions, such as deriving the clock for
the slower FSM from some part of the faster FSM, but that would be truely
horrible... Try and keep everything synchrounous to a single clock.

HTH

Ian

--
Ian Poole, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * Perl * Tcl/Tk * Verification * Project Services


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


"Roger Dahl" <rdnews@dahlsys.com> wrote in message
news:db3559c4.0309282218.27813f6f@posting.google.com...
Hi all,

I've just started playing around with VHDL and I'm having trouble
solving a particular problem.

I have two FSMs. FSM A is clocked at a slow speed and FSM B is clocked
at a fast speed. I would like FSM B to cycle through all its states
each time FSM A changes state. The states for each FSM is declared as
a type.

Is there a standard solution to this kind of problem?

One solution that I have been trying to implement involves having a
third process that sets a signal when FSM A changes state and clears
the signal when FSM B changes state. That signal would be used for
telling FSM B to start going.

I have tried to implement that process like this:

process(CurrentFSM_A_State, CurrentFSM_B_State)
begin
[if triggered by A, set signal. if triggered by B, clear signal]...
end process;

However, I am unable to determine within the process if it was
triggered by CurrentFSM_A_State or CurrentFSM_B_State. rising_edge()
etc doesn't work since the signals are types, not single signals.

Any help would be greatly appreciated.

Roger Dahl
 
Roger Dahl wrote:

I have two FSMs. FSM A is clocked at a slow speed and FSM B is clocked
at a fast speed. I would like FSM B to cycle through all its states
each time FSM A changes state. The states for each FSM is declared as
a type.
Consider designing a single machine at the fast speed,
and adding synchronizers for the slow inputs.

-- Mike Treseler
 
Ian,

Thank you for taking the time to answer. I really appreciate it.

This is intended for hardware.

I hadn't considered that you can clock one FSM from another so this
was exactly the kind of insight I was looking for. However, your
solution doesn't bring me all the way there. I would like the fast FSM
to run on 1MHz and the slow one to run on 1Hz. So, I need to somehow
get rid of 999,995 cycles if I want to clock the slow FSM from the
fast one (which has 5 states). I was thinking of attempting to do that
by adding states that "loop" that many cycles. Would that be a good
way of doing it?

Is this intended for hardware, or just for simulation? If it is just for
simulation, then the simple answer is use the 'event attribute -

process(FSM_A_State , FSM_B_State)
begin
if (FSM_A_State'event) then

elsif (FSM_B_State'event) then

end if;
end process;

However, if you ever want to build hardware, then this will not work - could
you draw the schematic resulting from the above code?
That is a good point but some magic must already be going on in the
background here as the synthesizer somehow includes circuitry that
detects changes in the state types (which consist of multiple signals)
to trigger the process. It seems to me that the synthesizer might also
be able to generate circuitry to tell me which signal changed?

Thank you again for your advice,

Roger
 
Mike,

Thank you for your reply.

If FSM A and FSM B have 5 states each, would the design you're
suggesting cause the single FSM to have 5 x 5 = 25 states? If not,
could you describe the design more closely? After reading your reply,
I researched synchronizers, but I am unsure how they can help in this
design.

Thanks again,

Roger

Mike Treseler <mike.treseler@flukenetworks.com> wrote in message news:<3F785674.7020204@flukenetworks.com>...
Roger Dahl wrote:

I have two FSMs. FSM A is clocked at a slow speed and FSM B is clocked
at a fast speed. I would like FSM B to cycle through all its states
each time FSM A changes state. The states for each FSM is declared as
a type.

Consider designing a single machine at the fast speed,
and adding synchronizers for the slow inputs.

-- Mike Treseler
 
process(CurrentFSM_A_State, CurrentFSM_B_State)
begin
[if triggered by A, set signal. if triggered by B, clear signal]...
end process;
I would use two separate processes for the two state machines and check
state change of the slow FSM (A) in the fast FSM(B)

process (CurrentFSM_B)
case CurrentFSM_B_State is
when WAIT_FOR_A_CHANGE =>
if (PreFSM_A_State_In_B_Clk /= CurFSM_A_STATE_In_B_CLk) then
NextFSM_B <= FSM_B_STATE1;
else
NextFSM_B <= Current_FSM_B_State;
end if;

When FSM_B_STATE1 =>
NextFSM_B <= FSM_B_STATE2;
......
When FSM_B_STATE5 =>
NextFSM_B <= WAIT_FOR_A_CHANGE;
end case;

Jim Wu
jimwu88NOOOSPAM@yahoo.com (remove capital letters)
http://www.geocities.com/jimwu88/chips
 
Roger Dahl wrote:
Mike,

Thank you for your reply.

If FSM A and FSM B have 5 states each, would the design you're
suggesting cause the single FSM to have 5 x 5 = 25 states? If not,
could you describe the design more closely?
Yes, but I visualize it as a process with two
local variables. If one variable is a counter,
I would declare it as unsigned. If it is
pure state, I would declare a type enumeration.

After reading your reply,
I researched synchronizers, but I am unsure how they can help in this
design.

A three bit (two register) shift register is
standard practice for any input not already
synchronized to the system clock.

-- Mike Treseler
 
Jim,

I have implemented your excellent suggestion and it works beautifully.
The resulting code became very clean and simple with a basic structure
like the one I was trying to create.

Thank you,

Roger


"Jim Wu" <jimwu88NOOOOSPAM@yahoo.com> wrote in message news:<Ihqeb.14517$yU5.9541@nwrdny01.gnilink.net>...
process(CurrentFSM_A_State, CurrentFSM_B_State)
begin
[if triggered by A, set signal. if triggered by B, clear signal]...
end process;


I would use two separate processes for the two state machines and check
state change of the slow FSM (A) in the fast FSM(B)

process (CurrentFSM_B)
case CurrentFSM_B_State is
when WAIT_FOR_A_CHANGE =
if (PreFSM_A_State_In_B_Clk /= CurFSM_A_STATE_In_B_CLk) then
NextFSM_B <= FSM_B_STATE1;
else
NextFSM_B <= Current_FSM_B_State;
end if;

When FSM_B_STATE1 =
NextFSM_B <= FSM_B_STATE2;
......
When FSM_B_STATE5 =
NextFSM_B <= WAIT_FOR_A_CHANGE;
end case;

Jim Wu
jimwu88NOOOSPAM@yahoo.com (remove capital letters)
http://www.geocities.com/jimwu88/chips
 
Mike,

I'm curious about your solution. It looks like you have something in
mind where you code a 25 state FSM but simplify it using the local
variables and enumerations you mention? I would be interested in
seeing such a solution since seeing different solutions to the same
problem would help me gain perspective on the language.

Thanks,

Roger

Mike Treseler <mike.treseler@flukenetworks.com> wrote in message news:<3F7B0BC6.3020701@flukenetworks.com>...
Roger Dahl wrote:
Mike,

Thank you for your reply.

If FSM A and FSM B have 5 states each, would the design you're
suggesting cause the single FSM to have 5 x 5 = 25 states? If not,
could you describe the design more closely?

Yes, but I visualize it as a process with two
local variables. If one variable is a counter,
I would declare it as unsigned. If it is
pure state, I would declare a type enumeration.

After reading your reply,
I researched synchronizers, but I am unsure how they can help in this
design.


A three bit (two register) shift register is
standard practice for any input not already
synchronized to the system clock.

-- Mike Treseler
 
Roger Dahl wrote:
Mike,

I'm curious about your solution. It looks like you have something in
mind where you code a 25 state FSM but simplify it using the local
variables and enumerations you mention? I would be interested in
seeing such a solution since seeing different solutions to the same
problem would help me gain perspective on the language.
I'll bite.
A state machine that cycles through all states
without other output is a counter to me.
So here's an example of two synchronous
counters, one that counts every tick
and one that counts every 5th tick:

-- Mike Treseler


-- Fast and slow counters on the same clock
-- Mike Treseler Fri Oct 3 13:03:22 2003

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity two_counters is
generic (len : natural := 3; -- vector length
max : natural := 4); -- max count
port (
clk : in std_ulogic;
rst : in std_ulogic;
fast : out unsigned(len-1 downto 0);
slow : out unsigned(len-1 downto 0)
);
end two_counters;

architecture synth of two_counters is
subtype count_t is unsigned(len-1 downto 0);
constant init : unsigned := (count_t'range => '0');
begin
clked:process (clk, rst)
variable fast_v : count_t;
variable slow_v : count_t;
begin
values:if rst = '1' then
fast_v := init;
slow_v := init;
elsif rising_edge(clk) then
fast_v := fast_v + 1; -- fast counts every tick.
if fast_v > max then -- slow counts every 5 ticks
fast_v := init;
slow_v := slow_v + 1;
if slow_v > max then
slow_v := init;
end if;
end if;
end if values;
fast <= fast_v;
slow <= slow_v;
end process clked;
end synth;
 
-- rev 0.1 improved outputs

-- Fast and slow counters on the same clock
-- outputs corrected
-- Mike Treseler Fri Oct 3 13:58:00 2003
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity two_counters is
generic (len : natural := 3; -- vector length
max : natural := 4); -- max count
port (
clk : in std_ulogic;
rst : in std_ulogic;
fast : out unsigned(len-1 downto 0);
slow : out unsigned(len-1 downto 0)
);
end two_counters;

architecture synth of two_counters is
subtype count_t is unsigned(len-1 downto 0);
constant init : unsigned := (count_t'range => '0');
begin
clked:process (clk, rst)
variable fast_v : count_t;
variable slow_v : count_t;
begin
values:if rst = '1' then
fast_v := init;
slow_v := init;
fast <= fast_v;
slow <= slow_v;
elsif rising_edge(clk) then
fast <= fast_v;
slow <= slow_v;
fast_v := fast_v + 1; -- fast counts every tick.
if fast_v > max then -- slow counts every 5 ticks
fast_v := init;
slow_v := slow_v + 1;
if slow_v > max then
slow_v := init;
end if;
end if;
end if values;
end process clked;
end synth;
 

Welcome to EDABoard.com

Sponsor

Back
Top