Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
10 years ago

getting crazy with FSM in VHDL. The FSM runs weird and misbehavior

background:

To Let FPGA (cyclone 3) communication with a DSP board. i am trying to send three datas from DSP board to the FPGA board.

code:

library ieee;use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity dsp_com is port
(
     clock :   in std_logic;
	FPGA_CLK : out std_logic;
	led1: out std_logic_vector(3 downto 0) := (others => '1');
	Reset: in std_logic :='Z';	
    dsp_db   : inout std_logic_vector(12 downto 0) := (others =>'Z');
	dsp_db_output : out std_logic_vector(12 downto 0);
	dsp_db_input : in std_logic_vector(12 downto 0);	
	wr_en : out std_logic:='0';  -- initial state is input	
	FPGA_ACK : out std_logic := '0';  --default state is 0
	DSP_ACK : in std_logic := 'Z'
);
end dsp_com;
architecture FSM_Moore of dsp_com is
	TYPE State_type IS (S0, S1, S8, S9, S10, S11);  -- 12 States
	signal PresentState: State_type;
	signal s_DSP_ACK : std_logic ;
	signal s_Reset : std_logic;
	signal s_dsp_db_input : std_logic_vector(12 downto 0);
	
	signal Adc_address : std_logic_vector(3 downto 0);
	signal Adc_buffer : std_logic_vector(12 downto 0);
	signal data_from_dsp1 : std_logic_vector(3 downto 0);
	signal data_from_dsp2 : std_logic_vector(3 downto 0);			
	signal data_from_dsp3 : std_logic_vector(3 downto 0);
	
begin
	
--5k Hz signal work as FPGA_CLK
clkdsp :  process(clock)
			 variable count : integer range 0 to 2000 :=0;
			 variable n :std_logic := '0';
			 begin 
			 if rising_edge(clock) then
			 count := count + 1;
				if(count >= 2000) then
				n := not n;
				FPGA_CLK <= n ;
				count := 0;
				end if;
			end if;
		end process clkdsp;
		
	
	
synchronous : process(clock)
			begin
			 if rising_edge(clock)then
			 	s_DSP_ACK <= DSP_ACK;
			 	s_Reset <= Reset;
			 	s_dsp_db_input <= dsp_db_input;
			 else
			 	null;
			 end if;
 end process synchronous;
	
		
		
 --read the address and get the data	
--first:  process(clock,s_Reset)
--			begin 
--				if (s_Reset = '0') then
--				PresentState <= S0;
--				elsif rising_edge(clock) then		
--				PresentState <= PresentState;
--			end if;
--		   end process;
		
	
first : process(s_Reset, clock)
		begin		
		if (s_Reset = '0') then
		  PresentState <= S0;
		elsif(rising_edge(clock)) then
		
		case PresentState is
		
		when S0 => if s_DSP_ACK = '1' then PresentState <= S1;
			else PresentState <= S0; end if;			
			-- wr_en <= '0';	 -- input	
	-------------------------------single read ADC------------------------------------		 	
		when S1 => 
		if ((s_DSP_ACK = '0') and (s_dsp_db_input(3 downto 0) = "0100")) then PresentState <= S8;
		else  PresentState <= S1;end if;		 
		--	 wr_en <= '0';	 -- input	
			
--------------------------receive 3 datas in sequence ------------------------------------			
		when S8 => if s_DSP_ACK = '1' then  PresentState <= S9;
			else PresentState <= S8 ; end if;
		--	wr_en <= '0';	 -- input		
		when S9 => if s_DSP_ACK = '0' then  PresentState <= S10;
			else PresentState <= S9 ; end if;
	--		wr_en <= '0';	 -- input			
		when S10 => if s_DSP_ACK = '1' then  PresentState <= S11;
			else PresentState <= S10; end if;
		--	wr_en <= '0';	 -- input		
		when S11 => if s_DSP_ACK = '0' then PresentState <= S0;
			 else PresentState <= S11; end if;
		--	 wr_en <= '0';		
	   end case;
	   
	   end if;
		end process;	
		
	-- Output depends solely on the current state	
second :   process(PresentState, data_from_dsp1, data_from_dsp2, data_from_dsp3, s_dsp_db_input(3 downto 0))
	--variable DATA : std_logic_vector(12 downto 0);
		begin 
		case PresentState is
		when S0 => 
		FPGA_ACK <= '0';  
		led1 <= "0000";
		wr_en <= '0';	 -- input	
		-----------------get the adc-buffer--------------
		when S1 =>
		
		adc_address <= s_dsp_db_input(3 downto 0);  -- get the address
		FPGA_ACK <= '1';		
  	     led1 <= "0001";
		wr_en <= '0';	 -- input	
	----------------------------------------------	
------------------------------------------------
		when S8 =>
		FPGA_ACK <= '0';
		led1 <= "1000";	
		wr_en <= '0';	 -- input
		 
		when S9 =>
		FPGA_ACK <= '1';		
		data_from_dsp1(3 downto 0) <= s_dsp_db_input(3 downto 0);	
		if(data_from_dsp1 = "0101")then
		led1 <= "1001";		
		else
		led1 <= "0000";
		end if;
		wr_en <= '0';	 -- input
		
		when S10 =>
		FPGA_ACK <= '0';
		data_from_dsp2(3 downto 0) <= s_dsp_db_input(3 downto 0);			
		if(data_from_dsp2 ="0111")then
		led1 <= "1010";		
		else
		led1 <= "0000";
		end if;
		wr_en <= '0';	 -- input
	
		when S11 =>
		FPGA_ACK <= '1';		
		data_from_dsp3(3 downto 0) <= s_dsp_db_input(3 downto 0);
		if(data_from_dsp3 ="1000")then
		led1 <= "1011";		
		else
		led1 <= "0000";
		end if;
		wr_en <= '0';	 -- input
		end case;
			
		
		end process;		
			
end FSM_Moore ;	
	
	

i have already synchronize the input signals e.g. dsp_ack, and db_input to the FSM. this is the most frequency problem that cause FSM runs misbehavior

Issue:

issues:

when i debug the c program in DSP board and FPGA, every thing is ok ! FSM can switch to the next state according to the DSP_ACK.

but if i let the program run. i saw the state is alway stuck at S0 in FPGA, but for the DSP side, the code are still running.

anyone has any ideas to this problem?

appreciate for you guys' reply !

regard,

napon

6 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Can you scope out the DSP_ACK signal. Does it ever go high when the DSP program is running?

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Did you debug this in a testbench?

    Did you heed the synthesis warning about infered latches in your "second" process? you have signals here that are not set in all processes, which means latches will be infered (which are not a good idea).

    Other points of concern - why do you have an unused inout port?

    why do you have in ports that default to 'Z'?

    Why do you have a logic generated clock output?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    thanks for your reply!

    yep, it goes high. sorry that i can not scope the dsp_ack signal because of short of osilliscope.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    hallo tricky !

    thanks for your reply!

    1.sorry that i did not meantioned it clearly, i debug the program in CCS , namly i debug the C code in DSP, for the fpga, i don't know how to debug it like C language. do you know it ? testbench ?

    2.yes, i get some infered latched in my process. okay, i will eliminate the latches by giving the signals a default values at the beginning of process.

    3.for the inout port, it's a mistake.. should be deleted. because in the top level of my VHDL , i need to use the bidirectional ports to transfer the data. so i divided the inout ports to three signals , input and output and wr_en to control the bidirectional ports.

    4. i thought that all the input signals should be assigned to the default state 'Z'.. am i made a mistake ?

    5. i need th logic generated clock output as an interrrupt signal for the DSP board.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Input ports in VHDL do not need to be defaulted to 'Z'. Only inout ports can use 'Z'. The default will be overridden if it's connected to an internal signal. And logic inside an FPGA can only be '1' or '0' so will get changed at synthesis time.

    I was worried about FPGA_CLK because you called it CLK and thought you might be using it as a clock elsewhere in the FPGA. this is bad practice. If it's going off as an interrupt only, then it should be ok (but its bad naming to call it _CLK, better called _IRQ)

    Testbenches are code you have written (usually in HDL) to test the functionality of your VHDL code. It is NOT synthesised, it is run through a simulator. You can then check all the outputs from your code to ensure they behave as you expect. There are plenty of tutorials around on the internet about how to write testbenches.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    OK. IF you don't have a scope, please set up SignalTap in your FPGA design and monitor the DSP_ACK signal. You need to know whether that signal triggers high, because then you will know which part of your design to debug. Right now there is not enough information.