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_rstut 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
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_rstut 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