UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor bartoszek
Visitor
1,425 Views
Registered: ‎04-23-2018

State machine - latches dependent on outputs states? unpredictable behaviour

Hello! I am implementing I2C interface on Artix7 in VHDL. My code is based on a state machine with 4x SCL frequency - four states per clk cycle. What I observed is that depending on outputs in state machine's states, code sometimes synthesizes well, sometimes not, i.e. I got transitions on SDA and SCL, but in another synthesis ports are constant '1's. I found out, that in case of this implementation, switching output of SDA to '0' except of '1' in one state decides. Whole code is written without latches, meeting clock constraints etc. Now this change makes me unable to finish I2C, as in the end of transmission, I cannot get working code with STOP condition. This is not the first situation with similar behaviour. All codes are written in VHDL, synthesized in ISE or Vivado (Spartan6, Artix7). My question is: why such a phenomena occurs? SDK does not give any additional warnings, no trims etc. What causes code once to be working, but tiny change makes it not working at all?
0 Kudos
8 Replies
Scholar richardhead
Scholar
1,408 Views
Registered: ‎08-01-2012

Re: State machine - latches dependent on outputs states? unpredictable behaviour

Can you post the code?
0 Kudos
Highlighted
Visitor bartoszek
Visitor
1,398 Views
Registered: ‎04-23-2018

Re: State machine - latches dependent on outputs states? unpredictable behaviour

Here you are.

I know it's a bit long and contains debug-comments as well as debug-loop - sorry for that. 

 

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;

--24Cxx Fmax = 100 kHz (up to 3,3V), p_ClockDivider sets ClockEEPROM always to 100 kHz
--Device address:		1 0 1 0 A2 A1 A0 RnW		when addressing memory array

entity EEPROM_24Cxx is
	Generic	(
			MEM_SIZE			:	INTEGER := 12;						--24C32: 12, 24C64: 13
			MEM_ADDR			:	STD_LOGIC_VECTOR := "001";		--I2C memory address
			CLOCK_FREQ			:	INTEGER := 100000000
			);
			
	Port	( 
			Reset 				:	in  STD_LOGIC;
			Clock				:	in  STD_LOGIC;
			
			f_MemBusy			:	out STD_LOGIC;
			f_DataReady			:	out STD_LOGIC;
			f_TransmissionTrig	:	in	STD_LOGIC;				--triggers I2C transmission
			f_TransmissionDone  :   out STD_LOGIC;
			f_TransmissionRnW	:	in	STD_LOGIC;				--0 - Write, 1 - Read
			DataAddr			:	in	 STD_LOGIC_VECTOR(MEM_SIZE-1 downto 0);
			DataIn				:	in  STD_LOGIC_VECTOR(7 downto 0);
			DataOut				:	out STD_LOGIC_VECTOR(7 downto 0);
			
			f_MemNotResponding	:	out STD_LOGIC;
			
			A					:	out STD_LOGIC_VECTOR(2 downto 0);
--			WP					:	out STD_LOGIC;
			SCL					:	out STD_LOGIC;			--max 100 kHz
			SDA					:	inout STD_LOGIC
			);
end EEPROM_24Cxx;

architecture Behavioral of EEPROM_24Cxx is

	constant	EEPROM_MAX_FREQ		:	INTEGER	:= 100000;
	constant	DIVIDER	: INTEGER	:= (integer(ceil(real(CLOCK_FREQ)/real(EEPROM_MAX_FREQ)))/8-1); -- 4 stany na 1 ck + polowa okresu --(integer(ceil(real(CLOCK_FREQ)/real(EEPROM_MAX_FREQ)))/2-1);
	
	constant	MEM_ADDR_MSB		:	STD_LOGIC_VECTOR(3 downto 0) := "1010";
	
    constant    MemAddr : STD_LOGIC_VECTOR(6 downto 0) := "1010001"; --MEM_ADDR_MSB & MEM_ADDR;
	
	type StateMem_type is (Idle, Start1, Start2, Addr1, Addr2, Addr3, Addr4, RnW1, RnW2, RnW3, RnW4, CheckAck1, CheckAck2, CheckAck3, CheckAck4,
									WriteAddr1, WriteAddr2, WriteAddr3, WriteAddr4, WriteAddr5, WriteAddr6, WriteAddr7, WriteAddr8, 
									WriteAddrAck1, WriteAddrAck2, WriteAddrAck3, WriteAddrAck4, WriteAddrAck20, WriteAddrAck21, WriteAddrAck22, WriteAddrAck23, WriteAddrAck24, 
									ReadDataStart1, ReadDataStart2, ReadDataStart3, 
									ReadDevAddr1, ReadDevAddr2, ReadDevAddr3, ReadDevAddr4, 
									ReadRnW1, ReadRnW2, ReadRnW3, ReadRnW4,
									ReadCheckAck1, ReadCheckAck2, ReadCheckAck3, ReadCheckAck4,
									ReadData1, ReadData2, ReadData3, ReadData4, WriteData1, WriteData2, WriteData3, WriteData4,
									WriteDataAck31, WriteDataAck32, WriteDataAck33, WriteDataAck34,
									StopReadAck, StopReadAck2, StopReadAck3, StopReadAck4, Stop1, Stop2, Stop3, Stop4, Stop5
									);
	signal StateMem				:	StateMem_type;
--    attribute fsm_encoding of StateMem : signal is "gray";	

	
	signal ClockEEPROM			:	STD_LOGIC := '0';			--4x SCL (StateMemHigh, StateMemLow)
	
	signal CounterBits			:	STD_LOGIC_VECTOR(4 downto 0) := (others => '0');

	signal f_MemBusy_int		:	STD_LOGIC := '0';
	signal f_DataReady_int		:	STD_LOGIC := '0';
	signal f_MemNotResponding_int	:	STD_LOGIC := '0';
	
	signal MemAck				:	STD_LOGIC := '0';
	signal RnW_int				:	STD_LOGIC := '0';
	--signal MemAddr				:	STD_LOGIC_VECTOR(6 downto 0) := MEM_ADDR_MSB & MEM_ADDR;
	
	signal DataAddr_int			:	STD_LOGIC_VECTOR(15 downto 0) := (others => '0');
	signal DataIn_int			:	STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
	signal DataOut_int			:	STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
	signal Countertymczasowy			:	STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
	
	
begin

				
p_MemData : process(Reset, Clock, ClockEEPROM, f_TransmissionTrig, DataAddr_int, DataIn_int)
begin
	if (Reset = '0') then
		--f_DataReady_int <= '0';
		SDA <= '1';
		SCL <= '1';
		MemAck <= '0';
		DataOut_int <= (others => '0');
		
--		MemAddr <= MEM_ADDR_MSB & MEM_ADDR;
	
	elsif (ClockEEPROM'Event and ClockEEPROM = '1') then
		--process defaults
--		RnW_int <= RnW_int;
--		DataAddr_int <= DataAddr_int;
--		DataIn_int <= DataIn_int;
--		DataOut_int <= DataOut_int;
		--f_DataReady_int <= '0';
		
		
		case StateMem is
		
			when Idle =>
				SDA <= 'Z'; --'1';
				SCL <= 'Z'; --'1';
--                        RnW_int <= RnW_int;
--                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
--				if (f_TransmissionTrig = '1') then
					DataAddr_int <= x"81AF"; --"0000" & DataAddr; --(15 downto MEM_SIZE => '0') x"FA0F"; --
					DataIn_int <= x"A9"; --DataIn; --x"85"; --x"FF"; --
					RnW_int <= '0'; --f_TransmissionRnW;
					if (Countertymczasowy = x"08") then
					   StateMem <= Start1;
					   Countertymczasowy <= (others => '0');
                    else
                        Countertymczasowy <= Countertymczasowy + 1;
                        StateMem <= Idle;
                    end if;
					
--				else
--					DataAddr_int <= x"80AF"; --(15 downto MEM_SIZE => '0') & DataAddr;
--					DataIn_int <= x"AA"; --DataIn;
--					RnW_int <= '0'; --f_TransmissionRnW;
--					StateMem <= Start1; --Idle;
--				end if;
				
			--I2C start sequence
			when Start1 =>
                    RnW_int <= RnW_int;
                    DataAddr_int <= DataAddr_int;
                    DataIn_int <= DataIn_int;
                    DataOut_int <= DataOut_int;
				SDA <= '0';
				SCL <= '1';
				CounterBits <= (others => '0');
				StateMem <= Start2;
				
			when Start2 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= '0';
				SCL <= '0';
				CounterBits <= (others => '0');
				StateMem <= Addr1;
				
			--I2C device addr
			when Addr1 =>
                    RnW_int <= RnW_int;
                    DataAddr_int <= DataAddr_int;
                    DataIn_int <= DataIn_int;
                    DataOut_int <= DataOut_int;
				SDA <= MemAddr(6 - to_integer(unsigned(CounterBits)));
				SCL <= '0';
				CounterBits <= CounterBits;
				StateMem <= Addr2;
				
			when Addr2 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= MemAddr(6 - to_integer(unsigned(CounterBits)));
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= Addr3;
				
			when Addr3 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= MemAddr(6 - to_integer(unsigned(CounterBits)));
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= Addr4;
				
			when Addr4 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= MemAddr(6 - to_integer(unsigned(CounterBits)));
				SCL <= '0';
				if (CounterBits < "00110") then
					CounterBits <= CounterBits + 1;
					StateMem <= Addr1;
				else
					CounterBits <= (others => '0');
					StateMem <= RnW1;
				end if;
			
			--I2C Read/Write
			when RnW1 =>
                    RnW_int <= RnW_int;
                    DataAddr_int <= DataAddr_int;
                    DataIn_int <= DataIn_int;
                    DataOut_int <= DataOut_int;
				SDA <= RnW_int; --'0'; --
				SCL <= '0';
				CounterBits <= (others => '0');
				StateMem <= RnW2;
				
			when RnW2 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= RnW_int; --'0'; --
				SCL <= '1';
				StateMem <= RnW3;
				CounterBits <= (others => '0');
				
			when RnW3 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= RnW_int; --'0'; --
				SCL <= '1';
				StateMem <= RnW4;
				CounterBits <= (others => '0');
				
			when RnW4 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= RnW_int; --'0'; --
				SCL <= '0';
				StateMem <= CheckAck1;
				CounterBits <= (others => '0');
				
			--I2C acknowledge check
			when CheckAck1 =>
                    RnW_int <= RnW_int;
                    DataAddr_int <= DataAddr_int;
                    DataIn_int <= DataIn_int;
                    DataOut_int <= DataOut_int;
--				MemAck <= SDA;
                SDA <= 'Z';
				SCL <= '0';
				StateMem <= CheckAck2;
				CounterBits <= (others => '0');
				
			when CheckAck2 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				MemAck <= SDA;
				SCL <= '1';
--				StateMem <= CheckAck3;
				CounterBits <= (others => '0');
				if (MemAck = '0') then
					StateMem <= CheckAck4;
				else
--					f_MemNotResponding_int <= '1';
					StateMem <= CheckAck3; --Idle;
				end if;
				
				--petla blokujaca przy braku potwierdzenia
			when CheckAck3 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				MemAck <= SDA;
				SCL <= '1';
				CounterBits <= (others => '0');
--				if (MemAck = '0') then
					StateMem <= CheckAck4;
--				else
----					f_MemNotResponding_int <= '1';
--					StateMem <= CheckAck3; --Idle;
--				end if;
				
			when CheckAck4 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				MemAck <= SDA;
				SCL <= '0';
				CounterBits <= (others => '0');
--				if (RnW_int = '0') then
--					StateMem <= Read1;
--				else
					StateMem <= WriteAddr1; --ok Idle; -- 
--				end if;
				
				
			--I2C memory addr write
			when WriteAddr1 =>
                    RnW_int <= RnW_int;
                    DataAddr_int <= DataAddr_int;
                    DataIn_int <= DataIn_int;
                    DataOut_int <= DataOut_int;
				SDA <= DataAddr_int(15 - to_integer(unsigned(CounterBits)));
				SCL <= '0';
				CounterBits <= CounterBits;
				StateMem <= WriteAddr2;
				
			when WriteAddr2 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= DataAddr_int(15 - to_integer(unsigned(CounterBits)));
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= WriteAddr3;
				
			when WriteAddr3 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= DataAddr_int(15 - to_integer(unsigned(CounterBits)));
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= WriteAddr4;
				
			when WriteAddr4 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= DataAddr_int(15 - to_integer(unsigned(CounterBits)));
				SCL <= '0';
				if (CounterBits < "00111") then --01000
					CounterBits <= CounterBits + 1;
					StateMem <= WriteAddr1;
				else
					StateMem <= WriteAddrAck1;
				end if;
					
			when WriteAddrAck1 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= 'Z';
				--MemAck <= SDA;
				SCL <= '0';
				StateMem <= WriteAddrAck2;
				CounterBits <= (others => '0');
				
			when WriteAddrAck2 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
--				SDA <= 'Z';
				MemAck <= SDA;
				SCL <= '1';
				StateMem <= WriteAddrAck3;
				CounterBits <= (others => '0');
				
			when WriteAddrAck3 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				MemAck <= SDA;
				SCL <= '1';
				CounterBits <= (others => '0');
				if (MemAck = '0') then --debug
					StateMem <= WriteAddr5; --WriteAddrAck4; --srednik
				else
--					f_MemNotResponding_int <= '1';
					StateMem <= WriteAddrAck4; --Idle; --  WriteAddrAck3; --Idle;
				end if;
				
			when WriteAddrAck4 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				MemAck <= MemAck;
				SDA <= 'Z';
				SCL <= '0';
				CounterBits <= (others => '0');
				if (MemAck = '0') then    --debug
					StateMem <= WriteAddr5;
				else
--					f_MemNotResponding_int <= '1';
					StateMem <= WriteAddrAck3; --Idle;
				end if;
				
			when WriteAddr5 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= DataAddr_int(7 - to_integer(unsigned(CounterBits))); --15
				SCL <= '0';
				CounterBits <= CounterBits;
				StateMem <= WriteAddr6;
				
			when WriteAddr6 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= DataAddr_int(7 - to_integer(unsigned(CounterBits)));
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= WriteAddr7;
				
			when WriteAddr7 =>
                                        RnW_int <= RnW_int;
                                        DataAddr_int <= DataAddr_int;
                                        DataIn_int <= DataIn_int;
                                        DataOut_int <= DataOut_int;
				SDA <= DataAddr_int(7 - to_integer(unsigned(CounterBits)));
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= WriteAddr8;
				
			when WriteAddr8 =>
                                        RnW_int <= RnW_int;
                                        DataAddr_int <= DataAddr_int;
                                        DataIn_int <= DataIn_int;
                                        DataOut_int <= DataOut_int;
				SDA <= DataAddr_int(7 - to_integer(unsigned(CounterBits)));
				SCL <= '0';
				if (CounterBits < "00111") then	--
					CounterBits <= CounterBits + 1;
					StateMem <= WriteAddr5;
				else
					CounterBits <= (others => '0');
					StateMem <= WriteAddrAck21; ---> trzy zera SCL Idle; --WriteAddrAck21; --
				end if;
					
--			when WriteAddrAck20 =>		--numeracja: drugie sprawdzanie, stany 1-4: 21, 22, 23, 24
--                                        RnW_int <= RnW_int;
--                                        DataAddr_int <= DataAddr_int;
--                                        DataIn_int <= DataIn_int;
--                                        DataOut_int <= DataOut_int;
--				SDA <= 'Z'; --'0';
--				SCL <= '0';
--				StateMem <= WriteAddrAck21;
--				CounterBits <= (others => '0');
				
			when WriteAddrAck21 =>		--numeracja: drugie sprawdzanie, stany 1-4: 21, 22, 23, 24
                                        RnW_int <= RnW_int;
                                        DataAddr_int <= DataAddr_int;
                                        DataIn_int <= DataIn_int;
                                        DataOut_int <= DataOut_int;
				SDA <= 'Z';
				SCL <= '0';
				StateMem <= WriteAddrAck22;
				CounterBits <= (others => '0');
				
			when WriteAddrAck22 =>
                                        RnW_int <= RnW_int;
                                        DataAddr_int <= DataAddr_int;
                                        DataIn_int <= DataIn_int;
                                        DataOut_int <= DataOut_int;
				MemAck <= SDA;
				SCL <= '1';
				StateMem <= WriteAddrAck23; --nie ok
				CounterBits <= (others => '0');
				
			when WriteAddrAck23 =>
                                        RnW_int <= RnW_int;
                                        DataAddr_int <= DataAddr_int;
                                        DataIn_int <= DataIn_int;
                                        DataOut_int <= DataOut_int;
				MemAck <= SDA;
				SCL <= '1';
				CounterBits <= (others => '0');
				if (MemAck = '0') then
					if (RnW_int = '0') then			--write data
						StateMem <= WriteData1; --WriteAddrAck24;
					elsif (RnW_int = '1') then		--read data    -- rozgalezienie read/write
						StateMem <= ReadDataStart1; --Start1; --
					end if;
				else
--					f_MemNotResponding_int <= '1';
					StateMem <= WriteAddrAck24; --Idle; Idle; --
				end if;
				
			when WriteAddrAck24 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
                MemAck <= MemAck;
                SDA <= 'Z';
				SCL <= '0';
				CounterBits <= (others => '0');
				
                if (MemAck = '0') then
                    if (RnW_int = '0') then            --write data
                        StateMem <= WriteData1; --WriteAddrAck24;
                    elsif (RnW_int = '1') then        --read data    -- rozgalezienie read/write
                        StateMem <= ReadDataStart1; --Start1; --
                    end if;
                else
--                    f_MemNotResponding_int <= '1';
                    StateMem <= WriteAddrAck23; --Idle;Idle; --
                end if;
                                
--				if (MemAck = '0') then
--					StateMem <= WriteData1;
--				else
--					f_MemNotResponding_int <= '1';
--					StateMem <= WriteAddrAck24; --Idle;
--				end if;
				
				
				--read: here device address one more time
--				start
--				device addr + R=1
--				ack check
--				read 8 bits
--				stop
				
			--I2C start sequence
			when ReadDataStart1 =>
                                                    RnW_int <= RnW_int;
                                                    DataAddr_int <= DataAddr_int;
                                                    DataIn_int <= DataIn_int;
                                                    DataOut_int <= DataOut_int;
				SDA <= '1';
				SCL <= '1';
				CounterBits <= (others => '0');
				StateMem <= ReadDataStart2;
				
			when ReadDataStart2 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= '0';
				SCL <= '1';
				CounterBits <= (others => '0');
				StateMem <= ReadDataStart3;
				
			when ReadDataStart3 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= '0';
				SCL <= '0';
				CounterBits <= (others => '0');
				StateMem <= ReadDevAddr1;
				
			--I2C device addr
			when ReadDevAddr1 =>
                                                    RnW_int <= RnW_int;
                                                    DataAddr_int <= DataAddr_int;
                                                    DataIn_int <= DataIn_int;
                                                    DataOut_int <= DataOut_int;
				SDA <= MemAddr(6 - to_integer(unsigned(CounterBits)));
				SCL <= '0';
				CounterBits <= CounterBits;
				StateMem <= ReadDevAddr2;
				
			when ReadDevAddr2 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= MemAddr(6 - to_integer(unsigned(CounterBits)));
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= ReadDevAddr3;
				
			when ReadDevAddr3 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= MemAddr(6 - to_integer(unsigned(CounterBits)));
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= ReadDevAddr4;
				
			when ReadDevAddr4 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= MemAddr(6 - to_integer(unsigned(CounterBits)));
				SCL <= '0';
				if (CounterBits < "00110") then
					CounterBits <= CounterBits + 1;
					StateMem <= ReadDevAddr1;
				else
					CounterBits <= (others => '0');
					StateMem <= ReadRnW1;
				end if;
			
			--I2C Read/Write
			when ReadRnW1 =>
                                                    RnW_int <= RnW_int;
                                                    DataAddr_int <= DataAddr_int;
                                                    DataIn_int <= DataIn_int;
                                                    DataOut_int <= DataOut_int;
				SDA <= '1'; --nRW;
				SCL <= '0';
				CounterBits <= (others => '0');
				StateMem <= ReadRnW2;
				
			when ReadRnW2 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= '1'; --nRW;
				SCL <= '1';
				StateMem <= ReadRnW3;
				CounterBits <= (others => '0');
				
			when ReadRnW3 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= '1'; --nRW;
				SCL <= '1';
				StateMem <= ReadRnW4;
				CounterBits <= (others => '0');
				
			when ReadRnW4 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= '1'; --nRW;
				SCL <= '0';
				StateMem <= ReadCheckAck1;
				CounterBits <= (others => '0');
				
			--I2C acknowledge check
			when ReadCheckAck1 =>
                                                    RnW_int <= RnW_int;
                                                    DataAddr_int <= DataAddr_int;
                                                    DataIn_int <= DataIn_int;
                                                    DataOut_int <= DataOut_int;
			    SDA <= 'Z';
				--MemAck <= SDA;
				SCL <= '0';
				StateMem <= ReadCheckAck2;
				CounterBits <= (others => '0');
				
			when ReadCheckAck2 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				MemAck <= SDA;
				SCL <= '1';
--				StateMem <= ReadCheckAck3;
				CounterBits <= (others => '0');
				if (MemAck = '0') then
					StateMem <= ReadData1;
				else
--					f_MemNotResponding_int <= '1';
					StateMem <= ReadCheckAck3; --Idle;
				end if;
				
			when ReadCheckAck3 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				MemAck <= SDA;
				SCL <= '1';
				CounterBits <= (others => '0');
--				StateMem <= ReadCheckAck4;
                if (MemAck = '0') then
                    StateMem <= ReadData1;
                else
--                    f_MemNotResponding_int <= '1';
                    StateMem <= ReadCheckAck4; --Idle;
                end if;
				
			when ReadCheckAck4 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				MemAck <= SDA;
				SCL <= '0';
				CounterBits <= (others => '0');
				if (MemAck = '0') then
					StateMem <= ReadData1;
				else
--					f_MemNotResponding_int <= '1';
					StateMem <= ReadCheckAck4; --Idle;
				end if;
				
			when ReadData1 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				DataOut_int(7 - to_integer(unsigned(CounterBits))) <= SDA;
				SCL <= '0';
				CounterBits <= CounterBits;
				StateMem <= ReadData2;
				
			when ReadData2 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				DataOut_int(7 - to_integer(unsigned(CounterBits))) <= SDA;
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= ReadData3;
				
			when ReadData3 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				DataOut_int(7 - to_integer(unsigned(CounterBits))) <= SDA;
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= ReadData4;
				
			when ReadData4 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				DataOut_int(7 - to_integer(unsigned(CounterBits))) <= SDA;
				SCL <= '0';
				if (CounterBits < "0111") then
					CounterBits <= CounterBits + 1;
					StateMem <= ReadData1;
				else
--					f_DataReady_int <= '1';
					CounterBits <= (others => '0');
					StateMem <= StopReadAck; --Stop1;
				end if;
				
				
				
			--I2C data write
			when WriteData1 =>
                                                    RnW_int <= RnW_int;
                                                    DataAddr_int <= DataAddr_int;
                                                    DataIn_int <= DataIn_int;
                                                    DataOut_int <= DataOut_int;
				SDA <= DataIn_int(7 - to_integer(unsigned(CounterBits)));
				SCL <= '0';
				CounterBits <= CounterBits;
				StateMem <= WriteData2;
				
			when WriteData2 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= DataIn_int(7 - to_integer(unsigned(CounterBits)));
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= WriteData3;
				
			when WriteData3 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= DataIn_int(7 - to_integer(unsigned(CounterBits)));
				SCL <= '1';
				CounterBits <= CounterBits;
				StateMem <= WriteData4;
				
			when WriteData4 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= DataIn_int(7 - to_integer(unsigned(CounterBits)));
				SCL <= '0';
				if (CounterBits < "0111") then  --1000
					CounterBits <= CounterBits + 1;
					StateMem <= WriteData1;
				else
					CounterBits <= (others => '0');
					StateMem <= WriteDataAck31; --Idle;-- here
				end if;
				
			when WriteDataAck31 =>		--numeracja: trzecie sprawdzanie
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
                SDA <= 'Z';
--				MemAck <= SDA;
				SCL <= '0';
--				if (MemAck = '0') then
--				    StateMem <= Idle; -- Stop1;StopReadAck; -- 
--                else
--				    StateMem <= WriteDataAck31; --Idle; --
--				end if;
				StateMem <= WriteDataAck32; --Idle; --
				CounterBits <= (others => '0');
				
			when WriteDataAck32 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
--                SDA <= 'Z';
                MemAck <= SDA;
				SCL <= '1';
				StateMem <= WriteDataAck33;
				CounterBits <= (others => '0');
				
			when WriteDataAck33 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				MemAck <= SDA;
				SCL <= '1';
				CounterBits <= (others => '0');
				if (MemAck = '0') then
					StateMem <= Idle; --StopReadAck; --Stop1; --WriteDataAck34; --Stop2; --
				else
--					f_MemNotResponding_int <= '1';
					StateMem <= WriteDataAck34; --Idle; --Stop1; --Idle; --WriteDataAck34; --Stop2; --Idle; --WriteDataAck34; --WriteDataAck33;
				end if;
				
			when WriteDataAck34 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				MemAck <= MemAck;
				SDA <= 'Z';
				SCL <= '0';
				CounterBits <= (others => '0');
--				if (MemAck = '0') then
					StateMem <= Stop2; --Idle; --chyba ok, trzyma ack w dole po przejsciu do idle
--				else
----					f_MemNotResponding_int <= '1';
--					StateMem <= WriteDataAck34; --debugStop1; --
--				end if;
				
				
			--I2C stop sequence
			when StopReadAck =>
                                                    RnW_int <= RnW_int;
                                                    DataAddr_int <= DataAddr_int;
                                                    DataIn_int <= DataIn_int;
                                                    DataOut_int <= DataOut_int;
				SDA <= '0';
				SCL <= '0';
				CounterBits <= (others => '0');
				StateMem <= StopReadAck2;
				
			when StopReadAck2 =>
                                                    RnW_int <= RnW_int;
                                                    DataAddr_int <= DataAddr_int;
                                                    DataIn_int <= DataIn_int;
                                                    DataOut_int <= DataOut_int;
				SDA <= 'Z';
				SCL <= '1';
				CounterBits <= (others => '0');
				StateMem <= StopReadAck3;
				
			when StopReadAck3 =>
                                                    RnW_int <= RnW_int;
                                                    DataAddr_int <= DataAddr_int;
                                                    DataIn_int <= DataIn_int;
                                                    DataOut_int <= DataOut_int;
				SDA <= '1';
				SCL <= '1';
				CounterBits <= (others => '0');
				StateMem <= Stop2; --StopReadAck4;
				
			when StopReadAck4 =>
                                                    RnW_int <= RnW_int;
                                                    DataAddr_int <= DataAddr_int;
                                                    DataIn_int <= DataIn_int;
                                                    DataOut_int <= DataOut_int;
				SDA <= 'Z';
				SCL <= '0';
				CounterBits <= (others => '0');
				StateMem <= Stop1;
				
--			when StopReadAck =>
--                                                    RnW_int <= RnW_int;
--                                                    DataAddr_int <= DataAddr_int;
--                                                    DataIn_int <= DataIn_int;
--                                                    DataOut_int <= DataOut_int;
--				SDA <= 'Z';
--				SCL <= '0';
--				CounterBits <= (others => '0');
--				StateMem <= StopReadAck2;
				
--			when StopReadAck2 =>
--                                                    RnW_int <= RnW_int;
--                                                    DataAddr_int <= DataAddr_int;
--                                                    DataIn_int <= DataIn_int;
--                                                    DataOut_int <= DataOut_int;
--				SDA <= 'Z';
--				SCL <= '1';
--				CounterBits <= (others => '0');
--				StateMem <= StopReadAck3;
				
--			when StopReadAck3 =>
--                                                    RnW_int <= RnW_int;
--                                                    DataAddr_int <= DataAddr_int;
--                                                    DataIn_int <= DataIn_int;
--                                                    DataOut_int <= DataOut_int;
--				SDA <= 'Z';
--				SCL <= '1';
--				CounterBits <= (others => '0');
--				StateMem <= Stop4; --StopReadAck4;
				
--			when StopReadAck4 =>
--                                                    RnW_int <= RnW_int;
--                                                    DataAddr_int <= DataAddr_int;
--                                                    DataIn_int <= DataIn_int;
--                                                    DataOut_int <= DataOut_int;
--				SDA <= 'Z';
--				SCL <= '0';
--				CounterBits <= (others => '0');
--				StateMem <= Stop1;
				
			when Stop1 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= '0';
				SCL <= '0';
				CounterBits <= (others => '0');
				StateMem <= Stop2; --Idle; --
				
			when Stop2 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= '0';
				SCL <= '1';
				CounterBits <= (others => '0');
				StateMem <= Stop3; --Idle; --
				
			when Stop3 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= '1';
				SCL <= '1';
				CounterBits <= (others => '0');
				StateMem <= Idle; --Stop4;
				
			when Stop4 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= '1';
				SCL <= '1';
				CounterBits <= (others => '0');
				StateMem <= Stop5;
				
			when Stop5 =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= '1';
				SCL <= '1';
				CounterBits <= (others => '0');
				StateMem <= Idle;
				
				--Idle; --
				
			when others =>
                                                        RnW_int <= RnW_int;
                                                        DataAddr_int <= DataAddr_int;
                                                        DataIn_int <= DataIn_int;
                                                        DataOut_int <= DataOut_int;
				SDA <= '1';
				SCL <= '1';
				CounterBits <= (others => '0');
				StateMem <= Idle;
		
		end case;
		
	end if;
end process p_MemData;	

p_Flagger : process(Reset, Clock, StateMem, CounterBits)
begin
	if (Reset = '0') then
		f_MemBusy_int <= '0';
		
	elsif (Clock'Event and Clock = '1') then
	
		case StateMem is
			when Idle =>
				f_MemBusy_int <= '0';
				f_TransmissionDone <= '0';
				f_DataReady_int <= '0';
				
			when StopReadAck =>
				f_MemBusy_int <= '1';
				f_TransmissionDone <= '0';
				--if (CounterBits = "01110") then
                f_DataReady_int <= '1';
                
			when Stop5 =>
				f_MemBusy_int <= '1';
				f_TransmissionDone <= '1';
				--if (CounterBits = "01110") then
                f_DataReady_int <= '0';
                
--			when ReadData4 =>
--				f_MemBusy_int <= '1';
--				--if (CounterBits = "01110") then
--                f_DataReady_int <= '1';
				--else
				--	f_DataReady_int <= '0';
				--end if;
				
				
			when others =>
				f_MemBusy_int <= '1';
				f_TransmissionDone <= '0';
				f_DataReady_int <= '0';
			
		end case;
	end if;
	
end process p_Flagger;


p_ClockDivider : process(Reset, Clock)
	variable CounterDivider : INTEGER := 0;
begin
	if (Reset = '0') then
		CounterDivider := 0;
		ClockEEPROM <= '0';
		
	elsif (Clock'Event and Clock = '1') then
		if (CounterDivider = DIVIDER) then
			ClockEEPROM <= not ClockEEPROM;
			CounterDivider := 0;
		else
			CounterDivider := CounterDivider + 1;
		end if;
	end if;
	
end process p_ClockDivider;

A <= MEM_ADDR;
DataOut <= DataOut_int;

f_MemBusy <= f_MemBusy_int;
f_DataReady <= f_DataReady_int;
f_MemNotResponding <= f_MemNotResponding_int;

end Behavioral;
0 Kudos
Scholar richardhead
Scholar
1,371 Views
Registered: ‎08-01-2012

Re: State machine - latches dependent on outputs states? unpredictable behaviour

One Big issue - You have a generated clock. Using logic to generate clocks is generally bad as your new clock can have high skew and be heavily affected by temperature, voltage etc. It is much better to use a clock enable rather than a generated clock.

 

 

Visitor bartoszek
Visitor
1,363 Views
Registered: ‎04-23-2018

Re: State machine - latches dependent on outputs states? unpredictable behaviour

Can this make so big troubles? As I wrote, changing ex. SDA to '0' in StopReadAck2 makes no transitions, while SDA <= '1' behaves as expected from the code.
I know it is not a clear solution, but code doesn't work even as a standalone machine writing to EEPROM, not as a part of bigger system.
0 Kudos
Visitor bartoszek
Visitor
1,345 Views
Registered: ‎04-23-2018

Re: State machine - latches dependent on outputs states? unpredictable behaviour

Another question arises - how to clock a state machine with ~100 kHz clock in FPGA? It is much slower than what I can achieve with ClockingWizard from 100 MHz source.

0 Kudos
Mentor hgleamon1
Mentor
1,338 Views
Registered: ‎11-14-2011

Re: State machine - latches dependent on outputs states? unpredictable behaviour

@richardhead already answered that for you. Use a clock enable instead.
----------
"That which we must learn to do, we learn by doing." - Aristotle
0 Kudos
Visitor bartoszek
Visitor
1,264 Views
Registered: ‎04-23-2018

Re: State machine - latches dependent on outputs states? unpredictable behaviour

Okay, I changed state switching to code below (with TickEEPROM as EN), what resulted in synthesized registers with EN (checked it in synthesized schematic).

Signal TickEEPROM is generated as '1' for 1ck as below. 

Result is the same as with previous code - code latches in the same place.

According to your advice, I wondered how to use clock enable directly on SCL, but I can't actually imagine now how to generate and synchronise 100 kHz clock with state machine. Anybody could give another clue?

 

			when Start1 =>
                    RnW_int <= RnW_int;
                    DataAddr_int <= DataAddr_int;
                    DataIn_int <= DataIn_int;
                    DataOut_int <= DataOut_int;
				SDA <= '0';
				SCL <= '1';
				CounterBits <= (others => '0');
--				StateMem <= Start2;
                if (TickEEPROM = '1') then
                    StateMem <= Start2;
                else
                    StateMem <= Start1;
                end if;
				
			when Start2 =>
                        RnW_int <= RnW_int;
                        DataAddr_int <= DataAddr_int;
                        DataIn_int <= DataIn_int;
                        DataOut_int <= DataOut_int;
				SDA <= '0';
				SCL <= '0';
				CounterBits <= (others => '0');
--				StateMem <= Addr1;
                if (TickEEPROM = '1') then
                    StateMem <= Addr1;
                else
                    StateMem <= Start2;
                end if;
p_ClockDivider : process(Reset, Clock)
	variable CounterDivider : INTEGER range 0 to DIVIDER := 0;
begin
	if (Reset = '0') then
		CounterDivider := 0;
		ClockEEPROM <= '0';
		
	elsif (Clock'Event and Clock = '1') then
		if (CounterDivider = DIVIDER) then
			TickEEPROM <= '1';
			CounterDivider := 0;
		else
			TickEEPROM <= '0';
			CounterDivider := CounterDivider + 1;
		end if;
	end if;
	
end process p_ClockDivider;
0 Kudos
Scholar richardhead
Scholar
1,193 Views
Registered: ‎08-01-2012

Re: State machine - latches dependent on outputs states? unpredictable behaviour

If SCL is only 100Kz you should be able to sample that with your system clock (assuming safe CDC). Then you can use an edge detector to generate the enable for your registers.

0 Kudos