Mwnuk
Newbie level 6
- Joined
- Mar 7, 2013
- Messages
- 11
- Helped
- 2
- Reputation
- 4
- Reaction score
- 2
- Trophy points
- 1,283
- 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:
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
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