[SOLVED] WARNING!!! extremely crude I2C design, those with weak stomachs beware

Status
Not open for further replies.

Mwnuk

Newbie level 6
Joined
Mar 7, 2013
Messages
11
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,283
Visit site
Activity points
1,363
So I am trying to create an I2C controller with a Nexys2 FPGA to interface with an ADC (digilent AD7991) I am trying to get accelerometer data from. This is my first attempt at this and I want to fully understand what is happening step by step so I created a VHDL design that does just that:

Code:
Library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.all;


Entity I2C_Controller IS
			PORT(
					clk : in std_logic;
					scl : out std_logic;
					sda : inout std_logic;
					switch1 : in std_logic;
					switch2 : in std_logic;
					LEDs : out std_logic_vector(7 downto 0)
				 );
END I2C_Controller;

Architecture fsmd of I2C_Controller IS

		signal slaveAddress_read : std_logic_vector(7 downto 0):= "01010011";
		signal slaveAddress_write : std_logic_vector(7 downto 0):= "01010010";
		signal registerSettings : std_logic_vector(7 downto 0):= "11110000";
		signal SCL_Clk : std_logic := '0';
		signal SCLout : std_logic := '1';
		signal clk_cnt : integer range 0 to 250 := 0;
		signal bitcount : integer range 0 to 7 := 0;
		signal data1 : std_logic_vector(7 downto 0) := "11011000";
		signal data2 : std_logic_vector(7 downto 0) := "00011011";
		signal DataIndicator : std_logic_vector(4 downto 0) := "00000";
		signal state : std_logic_vector(7 downto 0) := x"00";
		signal sda01 : std_logic := '1';
		signal slaveACK : std_logic := '0';
		signal errors : std_logic_vector(3 downto 0) := "0000";

BEGIN

sda <= '0' when sda01 = '0' else 'Z'; -- converts sda01 from 0 or 1 to 0 or Z
												  
scl <= '0' when SCLout = '0' else 'Z';

process(clk)
begin
		If rising_edge(clk) then
			if clk_cnt < 250 then
				clk_cnt <= clk_cnt +1;
			else
				clk_cnt <= 0;
			end if;
			
			if clk_cnt < 125 or clk_cnt = 125 then
				SCL_Clk <= '0';
			elsif clk_cnt > 125 then
				SCL_Clk <= '1';
			end if;
		end if;
end process;


PROCESS(SCL_Clk)
BEGIN


	if(rising_edge(SCL_Clk)) then
		CASE state IS
--------------------------------------------IDLE CONDITION													
		when x"00" =>  -- idle
			SCLout <= '1';	-- SCL = 1
			sda01 <= '1'; -- SDA = 1
			state <= x"01";
--------------------------------------------START CONDITION			
		when x"01" =>  -- start condition
			SCLout <= '1';	-- SCL stays 1 while
			sda01 <= '0'; -- SDA transitions low
			bitcount <= 7;
			state <= x"02";
--------------------------------------------WRITE ADDRESS 
		when x"02" =>  -- sda transition state
			SCLout <= '0';	-- when scl low
			sda01 <= slaveAddress_write(bitcount);
			state <= x"03";

		when x"03" =>  -- write address state prt2
			SCLout <= '1';
			sda01 <= slaveAddress_write(bitcount);
				if bitcount - 1 >= 0 then
					bitcount <= bitcount -1;
					state <= x"02";
				else
					bitcount <= 7;
					state <= x"04";
				end if;
----------------------------------------------SLAVE ACK			
		when x"04" =>  -- slave ack bit prt1
			SCLout <= '0';
			sda01 <= '1';
			state <= x"05";		

		when x"05" =>  -- slave ack bit prt2
			SCLout <= '1';	-- SCL = 1
			sda01 <= '1';
			slaveACK <= sda; -- 0 = ack, 1 = error
				if sda = '1' then
					state <= x"50";
					errors <= "1000";
				else 
					state <= x"06";
				end if;
------------------------------------------------WRITE TO REGISTER				
		when x"06" =>  -- sda transition state
			SCLout <= '0';	-- when scl low
			sda01 <= registerSettings(bitcount);
			state <= x"07";

		when x"07" =>  -- write register state prt2
			SCLout <= '1';
			sda01 <= '1';
				if bitcount - 1 >= 0 then
					bitcount <= bitcount -1;
					state <= x"06";
				else
					bitcount <= 7;
					state <= x"08";
				end if;
-----------------------------------------------SLAVE ACK
		when x"08" =>  -- slave ack bit prt1
			SCLout <= '0';	-- SCL = 1
			sda01 <= '1';
			state <= x"09";		

		when x"09" =>  -- slave ack bit prt2
			SCLout <= '1';	-- SCL = 1
			sda01 <= '1';
			slaveAck <= sda; -- 0 = ack, 1 = error
				if sda = '1' then
					state <= x"50";
					errors <= "0100";
				else 
					state <= x"10";
				end if;	
-----------------------------------------------STOP CONDITION

		when x"10" =>  -- stop
			SCLout <= '0';	-- SCL = 1
			sda01 <= '0'; -- SDA = 1
			state <= x"11";
			
		when x"11" =>  -- 
			SCLout <= '1';	-- SCL  1 while
			sda01 <= '0'; -- SDA stays low
			state <= x"12";

		when x"12" =>  -- stop
			SCLout <= '1';	-- SCL stays 1
			sda01 <= '1'; -- SDA transitions to 1
			state <= x"13";
------------------------------------------------START CONDITION
		when x"13" =>  -- idle
			SCLout <= '1';	-- SCL = 1
			sda01 <= '1'; -- SDA = 1
			state <= x"14";
		
		when x"14" =>  -- start condition
			SCLout <= '1';	-- SCL stays 1 while
			sda01 <= '0'; -- SDA transitions low
			bitcount <= 7;
			state <= x"15";
--------------------------------------------WRITE ADDRESS 
		when x"15" =>  -- sda transition state
			SCLout <= '0';	-- when scl low
			sda01 <= slaveAddress_read(bitcount);
			state <= x"16";

		when x"16" =>  -- write address state prt2
			SCLout <= '1';
			sda01 <= '1';
				if bitcount - 1 >= 0 then
					bitcount <= bitcount -1;
					state <= x"15";
				else
					bitcount <= 7;
					state <= x"17";
				end if;
----------------------------------------------SLAVE ACK			
		when x"17" =>  -- slave ack bit prt1
			SCLout <= '0';	-- SCL = 1
			sda01 <= '1';
			state <= x"18";		

		when x"18" =>  -- slave ack bit prt2
			SCLout <= '1';	-- SCL = 1
			slaveAck <= sda; -- 0 = ack, 1 = error
			bitcount <= 7;
				if slaveAck = '1' then
					state <= x"50";
					errors <= "0010";
				else 
					state <= x"21";
				end if;
			

------------------------------------------------read first byte from converter				
		when x"21" =>  -- sda transition state
			SCLout <= '0';	-- when scl low
			sda01 <= '1';
			state <= x"22";

		when x"22" =>  -- write register state prt2
			SCLout <= '1';
			sda01 <= '1';
				if bitcount - 1 >= 0 then
					data1(bitcount) <= sda;
					bitcount <= bitcount -1;
					state <= x"21";
				else
					data1(bitcount) <= sda;
					bitcount <= 7;
					state <= x"23";
				end if;
----------------------------------------------MASTER ACK			
		when x"23" =>  -- ack bit prt1
			SCLout <= '0';	-- SCL = 1
			sda01 <= '0'; -- SDA = 1
			state <= x"24";		

		when x"24" =>  -- ack bit prt2
			SCLout <= '1';	-- SCL = 1
			sda01 <= '0'; -- SDA = 
			bitcount <= 7;
			state <= x"25";
------------------------------------------------read second byte from converter				
		when x"25" =>  -- sda transition state
			SCLout <= '0';	-- when scl low
			sda01 <= '1';
			state <= x"26";

		when x"26" =>  -- loops back to stop condition to take
			SCLout <= '1';	-- another 12 bits of data
			sda01 <= '1';
				if bitcount - 1 >= 0 then
					data2(bitcount) <= sda;
					bitcount <= bitcount -1;
					state <= x"25";
				else
					data2(bitcount) <= sda;
					bitcount <= 7;
					state <= x"27";
				end if;	
				
----------------------------------------------MASTER NOACK			
		when x"27" =>  -- MASTER Noack bit prt1
			SCLout <= '0';	-- SCL = 0
			sda01 <= '1'; -- SDA = 1
			state <= x"28";		

		when x"28" =>  -- MASTER Noack bit prt2
			SCLout <= '1';	-- SCL = 1
			sda01 <= '1'; -- SDA = 1
			state <= x"10";


		when others =>
			SCLout <= '1';
			sda01 <= '1';
			state <= x"50";
		END CASE;
	end if;

end process;

process(clk)
BEGIN
if rising_edge(clk) then
	if switch1 = '1' and switch2 = '0' then	
		LEDs(7 downto 4) <= errors;
	elsif switch2 = '1' and switch1 = '0' then
		LEDs(7 downto 0) <= Data1;
	else
		LEDs(7 downto 0) <= Data2;
	end if;
end if;
end process;

 
end fsmd;

So to be clear the data is initialized to be non-zero for error testing purposes. Also I have it set to indicate if No Ack are received in any of the cases they are expected.

So what I receive is all zeros. which makes all error indicators show good but it also shows no data. in the first byte of data the first two bits should always be zeros then next two MSB are channel indicators so I should always receive a 1 for one of the two of them. This indicates that There is no data coming from the adc or that the line is always pulled down.



I did not program the slave into the test bench. It is simply to show that the master is transmitting what I am expecting it to transmit and as far as I can tell it is. If anyone can see what I may be doing wrong here please point me in the right direction.

thank you
M. Wnuk
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…