My FSM is jumping to an unreachable state

Guest
I am having a problem whereby my FSM is jumping back and forth between
two states, one of which is unreachable from that current state ie. in
the code below, it is jumping out of "check_da" state into
"check_protocol" state okay, but once it is in this state, it jumps
into "check_da" state which should be unreachable, then back to
"check_protocol" and so forth. For nibble_counter values not equal to
39->41,47->51 it should stay in "check_protocol" as indicated by
"when others=>next_state<=check_protocol;" declaration.

Any ideas why this occuring ?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.board_addresses.all;


entity Receiver is
Port ( rxd : in std_logic_vector (3 downto 0);
rst :in std_logic;
rxclk : in std_logic;
rxdv : in STD_LOGIC;
frame_bad : out std_logic;
frame_good : out std_logic;
frame_mrk : out std_logic;
crcgen_en: out std_logic:='0';
crcgen_rst:eek:ut std_logic:='0';
crc:in std_logic_vector (31 downto 0));
end Receiver;

architecture RTL of Receiver is

type receiver_state is
(idle,wait_till_one_nibble_before_sfd,start_crcgen,check_da,check_protocol,read_data_till_one_nibble_before_fcs,stop_crcgen,check_fcs,wait_end,frm_good,frm_bad);
signal current_state,next_state:receiver_state;
signal frame_mrk_i:std_logic:='0';
signal frame_good_i:std_logic:='0';
signal frame_bad_i:std_logic:='0';
signal crcgen_en_i:std_logic:='0';
signal crcgen_rst_i:std_logic:='0';
signal nibble_counter:integer range 0 to 4096;
signal ip_length:std_logic_vector (15 downto 0):="0000000000000000";
signal fcs_position:integer range 0 to 4096:=0;
signal err_flag:std_logic:='0';
signal nibble_counter_rst:std_logic:='0';
signal fcs:std_logic_vector (31 downto 0);
signal test:integer range 0 to 4096;

begin

state_flops: process (rxclk,rst,nibble_counter_rst)
begin
if (rising_edge(rxclk))then
if (rst = '1') then
current_state <= idle;
nibble_counter<=0;
elsif (nibble_counter_rst='1') then
current_state <= next_state;
nibble_counter<=0;
else
current_state <= next_state;
nibble_counter<=nibble_counter+1;
end if;
end if;
end process state_flops;

output_flops: process (rxclk,rst)
begin
if (rising_edge(rxclk))then
if (rst = '1') then
frame_mrk<='0';
frame_good<='0';
frame_bad<='0';
crcgen_en<='0';
crcgen_rst<='0';
else
frame_mrk<=frame_mrk_i;
frame_good<=frame_good_i;
frame_bad<=frame_bad_i;
crcgen_en<=crcgen_en_i;
crcgen_rst<=crcgen_rst_i;
end if;
end if;
end process output_flops;

output_comb: process (next_state)
begin
case next_state is
when idle=>
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='1';

when wait_till_one_nibble_before_sfd=>
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='0';

when start_crcgen=>
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='1';
crcgen_rst_i<='0';

when check_da=>
frame_mrk_i<='1';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='1';
crcgen_rst_i<='0';

when check_protocol=>
frame_mrk_i<='1';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='1';
crcgen_rst_i<='0';


when read_data_till_one_nibble_before_fcs=>
frame_mrk_i<='1';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='1';
crcgen_rst_i<='0';

when stop_crcgen=>
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='0';

when check_fcs=>
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='0';


when wait_end=>
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='0';

when frm_good=>
frame_mrk_i<='0';
frame_good_i<='1';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='0';

when frm_bad=>
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='1';
crcgen_en_i<='0';
crcgen_rst_i<='0';

when others=>
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='1';

end case;
end process output_comb;

next_state_comb:
process(current_state,rxclk,rxdv,nibble_counter,ip_length,rxd,crc,rst)

begin

if (rst='1') then

fcs<=(others=>'0');
ip_length<=(others=>'0');
fcs_position<=0;
err_flag<='0';
nibble_counter_rst<='0';

elsif rising_edge(rxclk) then



case current_state is
when idle =>
if rxdv='1' and rxd="0101" then
next_state <= wait_till_one_nibble_before_sfd;
nibble_counter_rst<='0';
else
nibble_counter_rst<='1';
end if;

when wait_till_one_nibble_before_sfd=>
if nibble_counter=13 then
next_state<=start_crcgen;
end if;

when start_crcgen=>
next_state<=check_da;

when check_da=>


case nibble_counter is

when 15=>
if rxd=board_mac_address(43 downto 40) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1'; next_state <= wait_end;
end if;
when 16=>
if rxd=board_mac_address(47 downto 44) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 17=>
if rxd=board_mac_address(35 downto 32) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 18=>
if rxd=board_mac_address(39 downto 36) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 19=>
if rxd=board_mac_address(27 downto 24) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 20=>
if rxd=board_mac_address(31 downto 28) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 21=>
if rxd=board_mac_address(19 downto 16) or rxd=x"F"
then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 22=>
if rxd=board_mac_address(23 downto 20) or rxd=x"F"
then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 23=>
if rxd=board_mac_address(11 downto 8) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 24=>
if rxd=board_mac_address(15 downto 12) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 25=>
if rxd=board_mac_address(3 downto 0)or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 26=>
if rxd=board_mac_address(7 downto 4) or rxd=x"F" then
err_flag<='0';
next_state <= check_protocol;
else
err_flag<='1';
next_state <= wait_end;
end if;

when others=>
next_state <=check_da;
err_flag<='0';
end case;


when check_protocol=>


case nibble_counter is
--only valid protocols are IP and ARP
when 39=>
if rxd="1000" then
next_state <= check_protocol;
err_flag<='0';
else
next_state <= wait_end;
err_flag<='1';
end if;

when 40=>
if rxd="0000" then
next_state <= check_protocol;
err_flag<='0';
else
next_state <= wait_end;
err_flag<='1';
end if;


when 41=>
if rxd="0110" then --Frame type is ARP, hence frame size is 60
bytes (data of 92 nibbles, type of 4 nibbles, 24 nibbles for dest and
source addresses)
fcs_position<=135; --fcs position will be a (frame size of
120 nibbles+32 nibbles for preample and sfd)-1
next_state <= read_data_till_one_nibble_before_fcs;
err_flag<='0';
elsif rxd="0000" then
fcs_position<=0;
next_state <= check_protocol;
err_flag<='0';
else
next_state <= wait_end;
err_flag<='1';
end if;

when 47=>
ip_length(11 downto 8)<=rxd;
next_state <= check_protocol;


when 48=>
ip_length(15 downto 12)<=rxd;
next_state <= check_protocol;


when 49=>
ip_length(3 downto 0)<=rxd;
next_state <= check_protocol;


when 50=>
ip_length(7 downto 4)<=rxd;
next_state <= check_protocol;


when 51=>
if ip_length<"0000000000101110" then --payload length under
minimum 46 bytes, frame size will be padded to 60 bytes
fcs_position<=135;
next_state<=read_data_till_one_nibble_before_fcs;
else
fcs_position<=conv_integer((ip_length+14)+(ip_length
+14)+16-1);--frame size will be 2* (ip_length+14) where 14 is for
preample in nibbles
next_state<=read_data_till_one_nibble_before_fcs;
end if;


when others=>
next_state <= check_protocol;
err_flag<='0';
end case;

when read_data_till_one_nibble_before_fcs=>
if nibble_counter=fcs_position-1 then
next_state<=stop_crcgen;
else
next_state<=read_data_till_one_nibble_before_fcs;
end if;


when stop_crcgen=>

if nibble_counter=fcs_position+7 then
next_state<=check_fcs;
else
next_state<=stop_crcgen;
end if;

fcs(31 downto 28)<=rxd;
fcs(27 downto 24)<=fcs(31 downto 28);
fcs(23 downto 20)<=fcs(27 downto 24);
fcs(19 downto 16)<=fcs(23 downto 20);
fcs(15 downto 12)<=fcs(19 downto 16);
fcs(11 downto 8)<=fcs(15 downto 12);
fcs(7 downto 4)<=fcs(11 downto 8);
fcs(3 downto 0)<=fcs(7 downto 4);

when check_fcs=>

if crc(31 downto 0)=fcs(31 downto 0) then
next_state<=frm_good;
else
next_state<=frm_bad;
end if;


when wait_end=>

if rxdv='0' then
if err_flag='1' then
next_state<=frm_bad;
else
next_state<=frm_good;
end if;
end if;

when frm_bad=>
next_state<=idle;

when frm_good=>
next_state<=idle;
when others =>
next_state <= idle;

end case;
end if;
end process next_state_comb;

end RTL;


Regards

Mario Gencarelli
Defence Science&Technology Organisation Salisbury
Australia
 
<maurizio.gencarelli@dsto.defence.gov.au> wrote in message
news:1182840046.020020.93380@d30g2000prg.googlegroups.com...
I am having a problem whereby my FSM is jumping back and forth between
two states, one of which is unreachable from that current state ie. in
the code below, it is jumping out of "check_da" state into
"check_protocol" state okay, but once it is in this state, it jumps
into "check_da" state which should be unreachable, then back to
"check_protocol" and so forth. For nibble_counter values not equal to
39->41,47->51 it should stay in "check_protocol" as indicated by
"when others=>next_state<=check_protocol;" declaration.

Any ideas why this occuring ?
If this is happening on a real board but not in simulation, then it is most
likely a timing problem, you need to perform static timing analysis.
Somewhat related would be if any of the inputs to the state machine are not
synchronized to the clock. This will eventually cause a timing problem when
that async input ends up violating the required setup time (as determined by
static timing analysis) and the design fails.

KJ
 
Hi Mario,

maurizio.gencarelli@dsto.defence.gov.au wrote:

I am having a problem whereby my FSM is jumping back and forth between
two states, one of which is unreachable from that current state ie. in
the code below, it is jumping out of "check_da" state into
"check_protocol" state okay, but once it is in this state, it jumps
into "check_da" state which should be unreachable, then back to
"check_protocol" and so forth. For nibble_counter values not equal to
39->41,47->51 it should stay in "check_protocol" as indicated by
"when others=>next_state<=check_protocol;" declaration.

Any ideas why this occuring ?
You're using separate synchronous processes to handle the current state and
compute the next state. This leads to a 2 clock cycles delay between next
state computation and current state update, instead of a single clock cycle
like you probably intended.

Let's assume current_state and next_state are both check_da. When
nibble_counter reaches 26 (clock cycle N) your next_state_comb process will
change next_state to check_protocol. At clock cycle N+1, current_state will
be updated to check_protocol by the state_flops process, but the
next_state_comb process will still see a current state equal to check_da.
nibble_counter will then be equal to 27, and thus next_state will be set to
check_da by the "when others" case.

You should either remove the next_state signal completely and move your next
state computation logic to the state_flops process, or make the
next_state_comb process asynchronous.

Best regards,

Laurent Pinchart
 
On Jun 26, 6:58 pm, Laurent Pinchart <laurent.pinch...@skynet.be>
wrote:
Hi Mario,

maurizio.gencare...@dsto.defence.gov.au wrote:
I am having a problem whereby my FSM is jumping back and forth between
two states, one of which is unreachable from that current state ie. in
the code below, it is jumping out of "check_da" state into
"check_protocol" state okay, but once it is in this state, it jumps
into "check_da" state which should be unreachable, then back to
"check_protocol" and so forth. For nibble_counter values not equal to
39->41,47->51 it should stay in "check_protocol" as indicated by
"when others=>next_state<=check_protocol;" declaration.

Any ideas why this occuring ?

You're using separate synchronous processes to handle the current state and
compute the next state. This leads to a 2 clock cycles delay between next
state computation and current state update, instead of a single clock cycle
like you probably intended.

Let's assume current_state and next_state are both check_da. When
nibble_counter reaches 26 (clock cycle N) your next_state_comb process will
change next_state to check_protocol. At clock cycle N+1, current_state will
be updated to check_protocol by the state_flops process, but the
next_state_comb process will still see a current state equal to check_da.
nibble_counter will then be equal to 27, and thus next_state will be set to
check_da by the "when others" case.

You should either remove the next_state signal completely and move your next
state computation logic to the state_flops process, or make the
next_state_comb process asynchronous.

Best regards,

Laurent Pinchart
Thanks for your comments.
I started with a next_state_comb process asynchronous but this caused
BIG problems ie. structure of my FSM was the text book standard
registered outputs with next_state look up to eliminate 1 clock cycle
delay due to registering, which seems to work okay if values ae not
temporary stored, ie. for given input conditions, outputs are
immediately set in each state, not stored and processed to set some
output condition. However, in my case signals such as ip_length which
built up from four rxd nibble values over 4 clock cycles and fcs which
is built up from 8 rxd nibbles over 8 clock cycles=> are stored. If I
make next_comb_process asynchronous, I get unpredicted results with
ip_length having rubbish values appear, resulting from changing values
between clock ?. I also get bit latch errors which I can not seem to
get rid of. By making the next_state_comb register based, I can
guarantee that ip_length and fcs etc update only on the clock edge and
eliminate all latch warnings.

Has anyone had this problem and can suggest a better way, other than
put all my code into one clocked process and live with the clock
delays between inputs and ouputs, it would be appreciated.

Cheers

Mario Gencarelli
Defence Science & Technology Organisation Salisbury
Australia
 
maurizio.gencarelli@dsto.defence.gov.au wrote:

Has anyone had this problem and can suggest a better way, other than
put all my code into one clocked process and live with the clock
delays between inputs and ouputs, it would be appreciated.
1. Right now you have two ticks of delay.
With a single process, there would only be one.
It is also much simpler to read.

2. Jumping to an illegal state is a sure
sign of an unsynchronized input.

-- Mike Treseler
 
On 26 Jun, 07:40, maurizio.gencare...@dsto.defence.gov.au wrote:
I am having a problem whereby my FSM is jumping back and forth between
two states, one of which is unreachable from that current state ie. in
the code below, it is jumping out of "check_da" state into
"check_protocol" state okay, but once it is in this state, it jumps
into "check_da" state which should be unreachable, then back to
"check_protocol" and so forth. For nibble_counter values not equal to
39->41,47->51 it should stay in "check_protocol" as indicated by
"when others=>next_state<=check_protocol;" declaration.

Any ideas why this occuring ?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.board_addresses.all;

entity Receiver is
Port ( rxd : in std_logic_vector (3 downto 0);
rst :in std_logic;
rxclk : in std_logic;
rxdv : in STD_LOGIC;
frame_bad : out std_logic;
frame_good : out std_logic;
frame_mrk : out std_logic;
crcgen_en: out std_logic:='0';
crcgen_rst:eek:ut std_logic:='0';
crc:in std_logic_vector (31 downto 0));
end Receiver;

architecture RTL of Receiver is

type receiver_state is
(idle,wait_till_one_nibble_before_sfd,start_crcgen,check_da,check_protocol,­read_data_till_one_nibble_before_fcs,stop_crcgen,check_fcs,wait_end,frm_goo­d,frm_bad);
signal current_state,next_state:receiver_state;
signal frame_mrk_i:std_logic:='0';
signal frame_good_i:std_logic:='0';
signal frame_bad_i:std_logic:='0';
signal crcgen_en_i:std_logic:='0';
signal crcgen_rst_i:std_logic:='0';
signal nibble_counter:integer range 0 to 4096;
signal ip_length:std_logic_vector (15 downto 0):="0000000000000000";
signal fcs_position:integer range 0 to 4096:=0;
signal err_flag:std_logic:='0';
signal nibble_counter_rst:std_logic:='0';
signal fcs:std_logic_vector (31 downto 0);
signal test:integer range 0 to 4096;

begin

state_flops: process (rxclk,rst,nibble_counter_rst)
begin
if (rising_edge(rxclk))then
if (rst = '1') then
current_state <= idle;
nibble_counter<=0;
elsif (nibble_counter_rst='1') then
current_state <= next_state;
nibble_counter<=0;
else
current_state <= next_state;
nibble_counter<=nibble_counter+1;
end if;
end if;
end process state_flops;

output_flops: process (rxclk,rst)
begin
if (rising_edge(rxclk))then
if (rst = '1') then
frame_mrk<='0';
frame_good<='0';
frame_bad<='0';
crcgen_en<='0';
crcgen_rst<='0';
else
frame_mrk<=frame_mrk_i;
frame_good<=frame_good_i;
frame_bad<=frame_bad_i;
crcgen_en<=crcgen_en_i;
crcgen_rst<=crcgen_rst_i;
end if;
end if;
end process output_flops;

output_comb: process (next_state)
begin
case next_state is
when idle=
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='1';

when wait_till_one_nibble_before_sfd=
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='0';

when start_crcgen=
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='1';
crcgen_rst_i<='0';

when check_da=
frame_mrk_i<='1';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='1';
crcgen_rst_i<='0';

when check_protocol=
frame_mrk_i<='1';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='1';
crcgen_rst_i<='0';

when read_data_till_one_nibble_before_fcs=
frame_mrk_i<='1';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='1';
crcgen_rst_i<='0';

when stop_crcgen=
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='0';

when check_fcs=
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='0';

when wait_end=
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='0';

when frm_good=
frame_mrk_i<='0';
frame_good_i<='1';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='0';

when frm_bad=
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='1';
crcgen_en_i<='0';
crcgen_rst_i<='0';

when others=
frame_mrk_i<='0';
frame_good_i<='0';
frame_bad_i<='0';
crcgen_en_i<='0';
crcgen_rst_i<='1';

end case;
end process output_comb;

next_state_comb:
process(current_state,rxclk,rxdv,nibble_counter,ip_length,rxd,crc,rst)

begin

if (rst='1') then

fcs<=(others=>'0');
ip_length<=(others=>'0');
fcs_position<=0;
err_flag<='0';
nibble_counter_rst<='0';

elsif rising_edge(rxclk) then

case current_state is
when idle =
if rxdv='1' and rxd="0101" then
next_state <= wait_till_one_nibble_before_sfd;
nibble_counter_rst<='0';
else
nibble_counter_rst<='1';
end if;

when wait_till_one_nibble_before_sfd=
if nibble_counter=13 then
next_state<=start_crcgen;
end if;

when start_crcgen=
next_state<=check_da;

when check_da=

case nibble_counter is

when 15=
if rxd=board_mac_address(43 downto 40) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1'; next_state <= wait_end;
end if;
when 16=
if rxd=board_mac_address(47 downto 44) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 17=
if rxd=board_mac_address(35 downto 32) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 18=
if rxd=board_mac_address(39 downto 36) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 19=
if rxd=board_mac_address(27 downto 24) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 20=
if rxd=board_mac_address(31 downto 28) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 21=
if rxd=board_mac_address(19 downto 16) or rxd=x"F"
then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 22=
if rxd=board_mac_address(23 downto 20) or rxd=x"F"
then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 23=
if rxd=board_mac_address(11 downto 8) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 24=
if rxd=board_mac_address(15 downto 12) or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 25=
if rxd=board_mac_address(3 downto 0)or rxd=x"F" then
err_flag<='0';
next_state <= check_da;
else
err_flag<='1';
next_state <= wait_end;
end if;
when 26=
if rxd=board_mac_address(7 downto 4) or rxd=x"F" then
err_flag<='0';
next_state <= check_protocol;
else
err_flag<='1';
next_state <= wait_end;
end if;

when others=
next_state <=check_da;
err_flag<='0';
end case;

when check_protocol=

case nibble_counter is
--only valid protocols are IP and ARP
when 39=
if rxd="1000" then
next_state <= check_protocol;
err_flag<='0';
else
next_state <= wait_end;
err_flag<='1';
end if;

when 40=
if rxd="0000" then
next_state <= check_protocol;
err_flag<='0';
else
next_state <= wait_end;
err_flag<='1';
end if;

when 41=
if rxd="0110" then --Frame type is ARP, hence frame size is 60
bytes (data of 92 nibbles, type of 4 nibbles, 24 nibbles for dest and
source addresses)
fcs_position<=135; --fcs position will be a (frame size of
120 nibbles+32 nibbles for preample and sfd)-1
next_state <= read_data_till_one_nibble_before_fcs;
err_flag<='0';
elsif rxd="0000" then
fcs_position<=0;
next_state <= check_protocol;
err_flag<='0';
else
next_state <= wait_end;
err_flag<='1';
end if;

when 47=
ip_length(11 downto 8)<=rxd;
next_state <= check_protocol;

when 48=
ip_length(15 downto 12)<=rxd;
next_state <= check_protocol;

when 49=
ip_length(3 downto 0)<=rxd;
next_state <= check_protocol;

when 50=
ip_length(7 downto 4)<=rxd;
next_state <= check_protocol;

when 51=
if ip_length<"0000000000101110" then --payload length under
minimum 46 bytes, frame size will be padded to 60 bytes
fcs_position<=135;
next_state<=read_data_till_one_nibble_before_fcs;
else
fcs_position<=conv_integer((ip_length+14)+(ip_length
+14)+16-1);--frame size will be 2* (ip_length+14) where 14 is for
preample in nibbles
next_state<=read_data_till_one_nibble_before_fcs;
end if;

when others=
next_state <= check_protocol;
err_flag<='0';
end case;

when read_data_till_one_nibble_before_fcs=
if nibble_counter=fcs_position-1 then
next_state<=stop_crcgen;
else
next_state<=read_data_till_one_nibble_before_fcs;
end if;

when stop_crcgen=

if nibble_counter=fcs_position+7 then
next_state<=check_fcs;
else
next_state<=stop_crcgen;
end if;

fcs(31 downto 28)<=rxd;
fcs(27 downto 24)<=fcs(31 downto 28);
fcs(23 downto 20)<=fcs(27 downto 24);
fcs(19 downto 16)<=fcs(23 downto 20);
fcs(15 downto 12)<=fcs(19 downto 16);
fcs(11 downto 8)<=fcs(15 downto 12);
fcs(7 downto 4)<=fcs(11 downto 8);
fcs(3 downto 0)<=fcs(7 downto 4);

when check_fcs=

if crc(31 downto 0)=fcs(31 downto 0) then
next_state<=frm_good;
else
next_state<=frm_bad;
end if;

when

read more ť...
A minor point is that the state_flops process only needs rxclock in
the sensitivity list as the resets, as coded, are both synchronous.
The other clocked process has async resets; did you mean that?

I tend to use a 3 process FSM;

P1: state <= next_state on rising_edge(clk)
P2: combinatorial state assignments:
CASE state IS
WHEN idle => IF condition_1 THEN
next_state <= state2;
ELSE
next_state <= idle;
END IF;
etc etc.
P3: assign o/ps depending on state, the o/ps can be registerd. (Helps
to avoid glitches as state changes via various inputs, can be critical
in gate level sims & real h/w, but often not seen in RTL).

Kev P
 

Welcome to EDABoard.com

Sponsor

Back
Top