EmbDev.net

Forum: FPGA, VHDL & Verilog Testing I2C on cyclone 2 board


Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:

Rate this post
0 useful
not useful
Hi Guys,

I need suggestion from you,

I have written code for I2C read and write, But i don't know i how can 
test the code on Cyclone ii ep2c20484c7 board. I tried to set up a 
eeprom ic on bread board. In that set up i am not able to identify 
whether the READ or WRITE are happened or not.

Please give me a suggestion to test my code. Buying an I2C slave device 
is a last option for me. So suggest me something else.

Thanks & Regards,
Hareesh.

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Hareesh M. wrote:
> Please give me a suggestion to test my code.
First step is to setup a simulation without any hardware. When this is 
working you can turn over to real life...

> In that set up i am not able to identify whether the READ or WRITE are
> happened or not.
How did you find that out? What does the logic analyzer say? Does the 
timing on that look OK?

Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Lothar M. wrote:
> Hareesh M. wrote:
>> Please give me a suggestion to test my code.
> First step is to setup a simulation without any hardware. When this is
> working you can turn over to real life...

 when i simulated the code in modelsim the waveforms looked fine.
>
>> In that set up i am not able to identify whether the READ or WRITE are
>> happened or not.
> How did you find that out? What does the logic analyzer say? Does the
> timing on that look OK?

But to verify the waveform i need to get the ack from slave right?


i have attached the modelsim waveform for your reference. It is write 
operation
Slave address: 0X53
Data : 0XAA

: Edited by User
Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Hareesh M. wrote:
> But to verify the waveform i need to get the ack from slave right?
No. Then you will see the master sending the first bits and you will 
also see how the slave responds (is there an ACK or not?). And even so 
you will see, whether the bus timing is correct or not.

BTW: your SDA line seems to change at the very same time with the SCL 
falling edge. Better would be to keep the SDA stable a little bit longer 
than SCL, so changes in SDA occur only while SCL is low.
See there chapter 2.3.1:
http://www.ti.com/lit/an/scaa106/scaa106.pdf
And overall see the I2C spec:
https://www.nxp.com/docs/en/user-guide/UM10204.pdf

: Edited by Moderator
Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:

Rate this post
0 useful
not useful
Lothar M. wrote:
> Hareesh M. wrote:
>> But to verify the waveform i need to get the ack from slave right?
> No. Then you will see the master sending the first bits and you will
> also see how the slave responds (is there an ACK or not?). And even so
> you will see, whether the bus timing is correct or not.
>
> BTW: your SDA line seems to change at the very same time with the SCL
> falling edge. Better would be to keep the SDA stable a little bit longer
> than SCL, so changes in SDA occur only while SCL is low.

i got your point, but the thing is im using case statement for fsm. I am 
not getting the idea for that.
> See there chapter 2.3.1:
> http://www.ti.com/lit/an/scaa106/scaa106.pdf
> And overall see the I2C spec:
> https://www.nxp.com/docs/en/user-guide/UM10204.pdf

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Hareesh M. wrote:
> i got your point, but the thing is im using case statement for fsm.
So simply add one state for that falling edge of SCL while SDA stays 
stable.

Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Lothar M. wrote:
> Hareesh M. wrote:
>> i got your point, but the thing is im using case statement for fsm.
> So simply add one state for that falling edge of SCL while SDA stays
> stable.

I have updated the code as per your suggestion.

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Whats that attachment?
Pls attach a VHDL file. Or severeal VHDL files. But no zip file or 
whatsoever.

: Edited by Moderator
Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:

Rate this post
0 useful
not useful
Lothar M. wrote:
> Whats that attachment?
> Pls attach a VHDL file. Or severeal VHDL files. But no zip file or
> whatsoever.
Library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
--use ieee.numeric_std.all;

entity i2c_read_write is
    
    generic ( 
            address : std_logic_vector(0 to 7):="10100110";
            data    : std_logic_vector(0 to 7):="10101010"
           
          );  
  
  port(
      i_inclk    : in std_logic; --Input clock 50mhz
      i_reset    : in std_logic; --Reset 
      
      start_bit   : out std_logic;
      ledred    : out std_logic_vector(7 downto 0):=(others =>'0');
      
      o_scl      : out std_logic; --I2C SCL line
      io_sda    : inout std_logic:='Z' --I2C SDA line
        
    );
end i2c_read_write;

architecture model of i2c_read_write is

  type states is(i2c_idle,i2c_start,i2c_sendaddress,i2c_sendaddress_0,i2c_sendaddress_1,i2c_addressack,i2c_addressack_0,i2c_addressack_1,i2c_data,i2c_senddata,i2c_senddata_0,i2c_dataack,i2c_dataack_0,i2c_dataack_1,i2c_dataack_2,i2c_stop,i2c_stop_0,i2c_stop_1,i2c_stop_2,i2c_stop_3);
  signal i2c_state : states:=i2c_idle;
  
  signal scl_line  : std_logic;
  signal sda_line  : std_logic;
  
  signal slave_address : std_logic_vector(0 to 7):=(others =>'0');
  
  signal data_bytes  : std_logic_vector(0 to 7):=(others =>'0');
  
  signal index_address  : integer range 0 to 7:=0;
  signal index_data  : integer range 0 to 7:=0;
  
  signal speed_counter : integer:=0;
  
  signal i2c_tic  : std_logic:='1';
  
  signal stop_bit : std_logic:='0';
  
  signal slaveack : std_logic:='1';
  signal dataack  : std_logic:='1';
  

  
begin



  slave_address <= address;
  data_bytes <= data;
  
  process(i_inclk)
  begin
    if(rising_edge(i_inclk))then  
      if(speed_counter=125)then  
        speed_counter <= 0;
        i2c_tic <= not(i2c_tic);
      else
        speed_counter <= speed_counter+1;
      end if;
    end if;
  end process;
  
  
  start_bit <= i2c_tic;
  
  process(i2c_tic,i_reset)
  begin
    if(rising_edge(i2c_tic))then
    
      case i2c_state is
      
        when i2c_idle => --Idle           
          scl_line <= '1';
          
          sda_line <= '1';
          i2c_state <= i2c_start;
        
        when i2c_start => --Start
          if(stop_bit='0')then
            scl_line <= '1';
            sda_line <= '0';  
            i2c_state <= i2c_sendaddress;
          else
            i2c_state <= i2c_idle;
          end if;
          
        when i2c_sendaddress => --Slave address
          scl_line  <= '0';
          i2c_state <= i2c_sendaddress_0;

        when i2c_sendaddress_0 => --8 bit address transmission
          scl_line <= '0';
          sda_line  <= slave_address(index_address);
          i2c_state <= i2c_sendaddress_1;
          
        when i2c_sendaddress_1 =>
          scl_line  <= '1';
          
          sda_line  <= slave_address(index_address);
          if(index_address<7)then
            index_address <= index_address+1;
            i2c_state <= i2c_sendaddress;                                                      
          else
            index_address <= 0;
            i2c_state <= i2c_addressack;
          end if;
          
        when i2c_addressack => --Slave address acknoweldgement 
          scl_line <= '0';
          i2c_state <= i2c_addressack_0;
        
        when i2c_addressack_0 =>  
          scl_line <= '0';
          
          slaveack <= sda_line;
          i2c_state <= i2c_addressack_1;
          
        when i2c_addressack_1 =>
          scl_line <= '1';
          if(slaveack = '0')then
            i2c_state <= i2c_data;
          else
            i2c_state <= i2c_stop;
          end if;
            
        when i2c_data => --Data transmission starts 
          scl_line <= '0';
          i2c_state <= i2c_senddata_0;
        
          when i2c_senddata_0 =>
          scl_line <= '0';
          sda_line  <= data_bytes(index_data);
          i2c_state <= i2c_senddata;
          
        when i2c_senddata => --Transmitting 8 bit data
          scl_line <= '1';
          
          if(index_data<7)then
            index_data <= index_data+1;
            i2c_state <= i2c_data;
          else
            index_data <= 0;
            i2c_state <= i2c_dataack_0;
          end if;
          
        when i2c_dataack_0 => --Data acknoweldgement
          scl_line <= '0';
          i2c_state <= i2c_dataack_1;
          
        when i2c_dataack_1 =>
          scl_line <= '0';

          dataack  <= sda_line;
          i2c_state <= i2c_dataack_2;
          
        when i2c_dataack_2 =>
          scl_line <= '1';
          
          if(dataack = '0')then
            i2c_state <= i2c_stop;
          else
            i2c_state <= i2c_stop;
          end if;        
                    
        when i2c_stop => --Stop bit      
          scl_line <= '0';
          i2c_state <= i2c_stop_0;
        
        when i2c_stop_0 =>
          scl_line <= '0';
          sda_line <= '0';
          i2c_state <= i2c_stop_1;
          
        when i2c_stop_1 =>
          scl_line <= '0';
          i2c_state <= i2c_stop_2;
          
        when i2c_stop_2 =>
          scl_line <= '1';
          i2c_state <= i2c_stop_3;
        
        when i2c_stop_3 =>
          sda_line <= '1';
          stop_bit <= '1';
          stop_bit <= '1';
          i2c_state <= i2c_idle;
          
        when others =>
          i2c_state <= i2c_idle;
        
      end case;
      
    end if;
  end process;
  
 o_scl  <= scl_line;
 io_sda <= 'Z' when sda_line='1' else '0';
 
  ledred <= data_bytes;
 
end model;


Author: Lothar M. (lkmiller) (Moderator)
Posted on:

Rate this post
0 useful
not useful
Hareesh M. wrote:
> I have updated the code as per your suggestion.
Ok, and now? How does the waveform look like? Whats the problem with it?

Hareesh M. wrote:
> Lothar M. wrote:
>> Pls attach a VHDL file.
Hmpf.... you know, what "to attach" means?

: Edited by Moderator
Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Lothar M. wrote:
> Hareesh M. wrote:
>> I have updated the code as per your suggestion.
> Ok, and now? How does the waveform look like? Whats the problem with it?
>
> Hareesh M. wrote:
>> Lothar M. wrote:
>>> Pls attach a VHDL file.
> Hmpf.... you know, what "to attach" means?

Sorry, I have attached the vhdl file.

Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:

Rate this post
0 useful
not useful
Hareesh M. wrote:
> Lothar M. wrote:
>> Hareesh M. wrote:
>>> I have updated the code as per your suggestion.
>> Ok, and now? How does the waveform look like? Whats the problem with it?
>>
But the thing is, I have a 265Kbit EEPROM. So to write something into it 
we need to give byte address. If i add that in my code also, the will 
become very large.

Author: Lothar M. (lkmiller) (Moderator)
Posted on:
Attached files:

Rate this post
1 useful
not useful
Hareesh M. wrote:
> Sorry, I have attached the vhdl file.
This is no VHDL file because it has no *.VHD or *.VHDL extension. See 
the difference between your attachment and mine...

Hareesh M. wrote:
> If i add that in my code also, the will become very large.
Indeed. But whats the problem with that?


This ist NOT a proper way to generate a clock on a FPGA:
      if(speed_counter=125)then  
        i2c_tic <= not(i2c_tic);
Use a clock manager or much better: use a clock enable instead! Best way 
for a beginner is to have only 1 clock throughout the whole design.
  -- clock divider to generate clock enable for I2C
  process(i_inclk)
  begin
    if rising_edge(i_inclk) then    -- the one and only clock
      if speed_counter=249 then  
        speed_counter <= 0;
        i2c_tic_enable <= '1';
      else
        speed_counter <= speed_counter+1;
        i2c_tic_enable <= '0';
      end if;
    end if;
  end process;
  
  
  start_bit <= i2c_tic;
  
  process(i_inclk)
  begin
    if rising_edge(i_inclk) then    -- the one and only clock
      if i2c_tic_enable <= '1' then -- this is the I2C clock enable
        case i2c_state is
    :
    :

And also you have the usual "off by one" problem: your prescaler divides 
by 252, not like you want by 250! Because from 0 to 125 there are 126 
clock cycles.

: Edited by Moderator

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig