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: 
Highlighted
Visitor musaozturk
Visitor
5,969 Views
Registered: ‎08-27-2012

i2c master problem

Hi, I am trying to send data to MCP4725  DAC by using a simple and self-written i2c protocol but I could not reach my goal whatever I try. I get no errors.

Can someone help me get through this?

Thx in advance.

I am using Spartan 3E-nexys2 1200k board and here my code:

----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

 

entity I2C_master is
port (clkin : in std_logic;
scl : out std_logic;
sda : inout std_logic);
end I2C_master;

architecture Behavioral of I2C_master is

signal state, state_temp : unsigned (4 downto 0) := "00000";
signal ack, clk, clkout, sda_sent, sda_received : std_logic;
constant device_addr : std_logic_vector (10 downto 0) := "11000000000";
constant din : std_logic_vector (11 downto 0) := x"000";

 

begin


----clock generation, using standart mode up to 100Kbits
CLOCK_GEN: process (clkin)
variable counter : integer := 0;
begin
if rising_edge(clkin) then
if counter = 500 then
counter := 0;
clkout <= '1';
else
clkout <= '0';
counter := counter +1;
end if;
end if;
end process;

--din generator
--DIN_GEN: process (state)
--begin
-- if state = idle then
-- din <= din + 1;
-- end if;
--end process;


--write
DATA_WRITE: process(clkout, sda_received )
variable count : integer;
begin

if rising_edge (clkout) then

--start
if state = 0 then
clk <= '1';
sda_sent <= '1';
state <= state + 1;

elsif state = 1 then
sda_sent <= '0';
state <= state + 1;
clk <= '0';

--first 7 bits of address
elsif state >= 2 and state <= 8 then
clk <= '1';
count := conv_integer(state);
sda_sent <= device_addr(12-count);
state_temp <= state + 1;
state <= "11111";

--write command inserted
elsif state = 9 then
clk <= '1';
sda_sent <= '0';
state_temp <= state + 1;
state <= "11111";

--ack1 received
elsif state = 10 then
clk <= '1';
ack <= '1';
if sda_received = '0' then --ack1 received
ack <= '0';
state_temp <= state + 1;
state <= "11111";
else
clk <= '0';
state <= "00000";
end if;

--remaining 4 bits of address
elsif state >= 11 and state <= 14 then
clk <= '1';
count := conv_integer(state);
sda_sent <= device_addr(14-count);
state_temp <= state + 1;
state <= "11111";

--first 4 data bits
elsif state >= 15 and state <= 18 then
clk <= '1';
count := conv_integer(state);
sda_sent <= din(26-count);
state_temp <= state + 1;
state <= "11111";

--ack2 received
elsif state = 19 then
clk <= '1';
ack <= '1';
if sda_received = '0' then --ack2 received
ack <= '0';
state_temp <= state + 1;
state <= "11111";
else
clk <= '0';
state <= "00000";
end if;

--remaining 8 bits of data
elsif state >= 20 and state <= 27 then
clk <= '1';
count := conv_integer(state);
sda_sent <= din(27-count);
state_temp <= state + 1;
state <= "11111";

--ack3 received
elsif state = 28 then
clk <= '1';
ack <= '1';
if sda_received = '0' then --ack3 received
ack <= '0';
state_temp <= state + 1;
state <= "11111";
else
clk <= '0';
state <= "00000";
end if;

--stop
elsif state = 29 then
clk <= '1';
sda_sent <= '0';
state <= state + 1;

elsif state = 30 then
clk <= '1';
sda_sent <= '1';
state <= "00000";

-----------------------------------
--wait option, to pull clock to zero
elsif state = 31 then
state <= state_temp;
clk <= '0';

end if;
end if;
end process;

sda_received <= sda when ack = '1' else 'Z';
sda <= sda_sent;
scl <= clk;

end Behavioral;

0 Kudos
3 Replies
Instructor
Instructor
5,961 Views
Registered: ‎07-21-2009

Re: i2c master problem

1.  It is difficult to read code which is not formatted to be readable.  Please, either use the code insertion button, or use the fixed-pitch COURIER NEW font for the source code.

 

2.  You have posted perhaps 100 lines of code without describing the problem for which we should be searching.  Please describe the problem.  "It does not work" is not a very good description.

 

3.  Have you simulated your design?  If not, this can be a valuable debugging tool for this application.

4.  Have you applied an oscilloscope to the I2C signals?    If not, this can be a valuable debugging tool for this application.

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
0 Kudos
Visitor musaozturk
Visitor
5,951 Views
Registered: ‎08-27-2012

Re: i2c master problem

Thx for the reply.

1- My code is readable actually but when I paste it it becomes like that. So I attached .vhd file. I am basically trying to send hex"000" to 12-bit DAC mcp4725 which uses i2c interface and see 0 (zero) at the analog output. I use standart mode up to 100Kbits. 

 

2- Sorry for the lack of info, but I myself am not sure about the problem. I assigned scl and sda to leds and increase the period for debugging. The signal sequence is just as I expect. However when it comes to the real hardware application I do not see the expected output. Maybe I am doing something wrong with the hardware. Do I need to use pull-ups (or something similar) for pmod pins (JA, spartan3E-nexys2)? Also I am not comfortable with INOUT pin. Did I make some mistake when using inout?

 

3- I tried but I am not good at analyzing simulations. I will try chipscope.

 

4- I do not have an oscilloscope right now (I am in summer break) so I could not try it yet. 

 

0 Kudos
Instructor
Instructor
5,947 Views
Registered: ‎07-21-2009

Re: i2c master problem

You have a number of problems.

Have you read through some of the previous user forum threads discussing I2C?

 

In the New Users Forum README thread, you will find this:

 

Common Interfaces and FPGA techniques:

I2C basics link#1 link#2 code examples   I2C spec Rev 4  wiki articles: I2C  SMBus  MDIO  SPD  EDID

 

I assigned scl and sda to leds and increase the period for debugging. The signal sequence is just as I expect. However when it comes to the real hardware application I do not see the expected output. Maybe I am doing something wrong with the hardware. Do I need to use pull-ups (or something similar) for pmod pins (JA, spartan3E-nexys2)? Also I am not comfortable with INOUT pin. Did I make some mistake when using inout?

 

  • In I2C interfaces, SDA is always a bidirectional signal.
  • SCL may also be bidirectional, if clock stretching is supported.
  • When the master is not driving the signal, the master must release the signal.  This is missing from your code.
  • SDA is an open-drain (open-collector) signal.  When driven LOW, it is driven actively.  It is never driven HIGH.
  • An external pullup resistor provides the HIGH level (typically 4.7K - 10K ohms).
  • FPGA internal pullups are too weak for I2C signaling.
  • Without the conforming signal levels and standard, the I2C slave device cannot signal ACK or NACK.  Do you understand why?
  • Is there a source for the signal sda_received in your code?

This should help you for a while.  The signaling levels/drive problem cannot be understood using ChipScope, as ChipScope does not directly access external signals or pins.

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
0 Kudos