Delay in FSM using one process

  • Thread starter maurizio.gencarelli
  • Start date
M

maurizio.gencarelli

I have implemented the attached FSM code using one process. It seems
to work except that I am getting a 2 cycle clock delay between output
wr_fifo_en being aserted when frame_mrk goes high. The frame_mrk
indicates the beginning of signal which should be reflected in ouput
wr_fifo_data. This results in my fifo write enable, wr_fifo_en being
two clock cycles too late=> one cycle delay from input change to state
change, and the other from state change to output change. This
wouldn't be a problem if the wr_fifo_data output was delayed with
wr_fifo_en by 2 clock cycles so they line up=>shouldn't wr_fifo_data
be delayed w.r.t data because it is registered anyway?

Any ideas what I am doing wrong ?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity RX_FIFO_WR_CONTROL is
Port ( data_clk : in STD_LOGIC;
data:in STD_LOGIC_VECTOR (3 downto 0);
frame_mrk : in STD_LOGIC;
rxdv: in STD_LOGIC;
fifo_full : in STD_LOGIC;
frame_good: in STD_LOGIC;
frame_bad: in STD_LOGIC;
fifo_wr_data: out STD_LOGIC_VECTOR (4 downto 0);
wr_fifo_en : out STD_LOGIC;
rst: in STD_LOGIC;
prog_full_thresh: out std_logic_VECTOR(10 downto 0));
end RX_FIFO_WR_CONTROL;

architecture RTL of RX_FIFO_WR_CONTROL is


type fifo_cntrl_state is
(idle,write_fifo,over_flow,wait_end,read_frame_condition,write_frame_status);
signal state:fifo_cntrl_state;
signal ovr_flow: std_logic;



begin

prog_full_thresh<="11111111110";


process
(data_clk,rst,state,frame_mrk,rxdv,fifo_full,frame_good,frame_bad,data)
begin
if rst='1' then
state<=idle;
ovr_flow<='0';
wr_fifo_en<='0';
fifo_wr_data<="00000";

elsif rising_edge(data_clk) then

case state is
when idle =>
if frame_mrk='1' then
state<=write_fifo;
else
state<=idle;
end if;

fifo_wr_data(3 downto 0)<=data;
fifo_wr_data(4)<='0';
ovr_flow<='0';
wr_fifo_en<='0';

when write_fifo =>

wr_fifo_en<='1';
fifo_wr_data(3 downto 0)<=data;
fifo_wr_data(4)<=frame_mrk;
ovr_flow<='0';

if frame_mrk='0' then
state<= wait_end;
elsif fifo_full='1' then
state<= over_flow;
else
state<=write_fifo;
end if;


when over_flow=>
state<=wait_end;
fifo_wr_data(3 downto 0)<=data;
fifo_wr_data(4)<=frame_mrk;
ovr_flow<='1';
wr_fifo_en<='0';
when wait_end =>
if rxdv='0' then
state<=read_frame_condition;
else
state<=wait_end;
end if;

fifo_wr_data(3 downto 0)<=data;
fifo_wr_data(4)<=frame_mrk;
wr_fifo_en<='0';

when read_frame_condition =>
state<=write_frame_status;
wr_fifo_en<='0';
fifo_wr_data(4)<='0';
fifo_wr_data(3)<=ovr_flow;
fifo_wr_data(2)<=frame_good;
fifo_wr_data(1)<=frame_bad;
fifo_wr_data(0)<='0';

when write_frame_status =>
state<=idle;
wr_fifo_en<='1';
ovr_flow<='0';

when others =>
state <= idle;
fifo_wr_data(3 downto 0)<=data;
fifo_wr_data(4)<='0';
ovr_flow<='0';
wr_fifo_en<='0';

end case;
end if;
end process;

end RTL;
 
J

Jonathan Bromley

On Tue, 26 Jun 2007 17:49:05 -0700,
Any ideas what I am doing wrong ?

Some ideas, but I don't have the time to work through your FSM
in detail.
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

Oh dear. Please consider migrating to NUMERIC_STD if you
can possibly manage it. Soon.
process
(data_clk,rst,state,frame_mrk,rxdv,fifo_full,frame_good,frame_bad,data)

This is a straightforward clocked process, and should have
only (data_clk, rst) in its sensitivity list. The other items
are redundant, and may yield warnings in synthesis.
I have implemented the attached FSM code using one process. It seems
to work except that I am getting a 2 cycle clock delay between output
wr_fifo_en being aserted when frame_mrk goes high. The frame_mrk
indicates the beginning of signal which should be reflected in ouput
wr_fifo_data. This results in my fifo write enable, wr_fifo_en being
two clock cycles too late=> one cycle delay from input change to state
change, and the other from state change to output change. This
wouldn't be a problem if the wr_fifo_data output was delayed with
wr_fifo_en by 2 clock cycles so they line up=>shouldn't wr_fifo_data
be delayed w.r.t data because it is registered anyway?

You are quite right that you get two cycles of delay from
input change to output change. There MUST be at least one cycle,
of course, because the state machine is clocked. But you don't
need the second cycle of delay. Instead, you should write the
FSM so that (for example) an output that needs to be asserted in
state S1 should be driven high as a result of the TRANSITION to S1,
so that it is synchronous with S1 instead of one cycle late.

There are at least five sensible ways to do this.
I don't today have the stomach for the usual crusades
about which is the best, and which should be condemned
to be shackled to the walls of the dungeons of history
with the key thrown away.

Just a thought: Wouldn't it be fun if we could act like
the mediaeval church, and hold highbrow convocations at
which we could decide what coding styles were heretical?
Then we could impose "cruel and unusual" punishments for
violators, and I could join the RTL Inquisition and go
around subjecting people to public humiliation in various
interesting ways... oh yes, of course, we do that already,
it's called Usenet :)


(1) Classic 2-process Moore state machine
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Rewrite the state machine so that it manipulates only the
state signal. Write a second, combinational process that
decodes the state signal to create the outputs.

(2) Outputs as part of the state vector
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Instead of writing an enumeration type for the state,
write a bunch of STD_LOGIC_VECTOR constants. Make sure
that some of the bits of those constants exactly reflect
the output bits that you want as a function of the state.
Add further bits to the state vector to ensure that all
states have different state values (!). Pick off the
appropriate bits of state vector to provide your outputs.

(3) Registered-Mealy state machine with lookahead outputs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Go back to your existing FSM code, but rewrite it so that
when you transition to a given state, you also set up the
outputs as they WILL be in that new state. This is tedious
to code because it requires you to set up a state's outputs
on *every* transition into that state, from anywhere in
the state diagram not forgetting "to-self" transitions,
but it works well enough.

(4) Use a variable to hold the state vector
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Get rid of the state SIGNAL, and redefine it as a VARIABLE
inside the FSM clocked process. Rewrite the process as
TWO case statements. The first one performs all the state
transitions, the second calculates the outputs and drives
them on to signals.

process (clk, rst)
type state_type is (s1, s2, ...);
variable state: state_type;
begin
if rst = '1' then
state := <idle_state>;
outputs <= <reset output values>;
elsif rising_edge(clk) then
-- step 1: calculate next-state
case state is
when s1 =>
if <input conditions>
state := <different state>;
end if;
...
end case;
-- step 2: use next-state to determine next-outputs
case state is
when s1 =>
outputs <= <appropriate outputs for s1>;
...
end case;
end if;
end process;

(5) Don't use an explicit state machine at all
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Write code that uses various variables to keep track of the state
of your system, and to determine appropriate output values.
Once you've done all that, drive the chosen output values
on to your output signals. Method (4) is a useful special case of
this one. See Mike Treseler's website and posts for examples of
how to work this idea through in practice.
--
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.
 
M

Martin Thompson

I have implemented the attached FSM code using one process. It seems
to work except that I am getting a 2 cycle clock delay between output
wr_fifo_en being aserted when frame_mrk goes high. The frame_mrk
indicates the beginning of signal which should be reflected in ouput
wr_fifo_data. This results in my fifo write enable, wr_fifo_en being
two clock cycles too late=> one cycle delay from input change to state
change, and the other from state change to output change. This
wouldn't be a problem if the wr_fifo_data output was delayed with
wr_fifo_en by 2 clock cycles so they line up=>shouldn't wr_fifo_data
be delayed w.r.t data because it is registered anyway?

Any ideas what I am doing wrong ?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

OK so far...
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

Don't do this. Use ieee.numeric.std instead. There's many a thread
about it. Is this is template code?

type fifo_cntrl_state is
(idle,write_fifo,over_flow,wait_end,read_frame_condition,write_frame_status);
signal state:fifo_cntrl_state;
signal ovr_flow: std_logic;



begin

prog_full_thresh<="11111111110";


process
(data_clk,rst,state,frame_mrk,rxdv,fifo_full,frame_good,frame_bad,data)

It's a synchronous process with async reset, so you only need data_clk
and rst in your sentivity list.
begin
if rst='1' then
state<=idle;
ovr_flow<='0';
wr_fifo_en<='0';
fifo_wr_data<="00000";

elsif rising_edge(data_clk) then

case state is
when idle =>
if frame_mrk='1' then
state<=write_fifo;

You need to assert wr_fifo_en here if you want it to be
active on the next clock cycle after frame_mrk goes high.

and move the clearing of wr_fifo_en here from below (otherwise it will
always be cleared!)
state<=idle;
end if;

fifo_wr_data(3 downto 0)<=data;

You are writing your data here, so it *will* be updated for the next
clock cycle.
fifo_wr_data(4)<='0';
ovr_flow<='0';
wr_fifo_en<='0';

This clearing of wr_fifo_en needs to be moved up.

<snip>

Hope this helps!
Cheers,
Martin
 

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

No members online now.

Forum statistics

Threads
473,992
Messages
2,570,220
Members
46,807
Latest member
ryef

Latest Threads

Top