[SOLVED] I2c forADC ADS 1015 brakout board has this shifted SDA signal

Status
Not open for further replies.

kunal5959

Junior Member level 3
Joined
Jul 26, 2011
Messages
31
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Visit site
Activity points
1,644
I encounter this strange problem that my SDA signal is shifted by one SCl cyle and I cannot eliminate this error by any chance. I am using an ACTEL PROASIC3E Starter Kit and I want to access a ADS1015 breakout board that uses I2c bus to get command signals from FPGA.

I am poting my TOp module and Testbench code where i just trying to write som data and waiting for acknowledgement from the SLAVE(ADS1015 board). I have also attached this oscilloscope image where the white highlighting circle shows the shift of SDA towards right. That is the reason also my acknowledgement '0' from slave is received after 2 cycles and one can see the 'Z' state(marked with a green circle). Can anyone please assist me in understanding why the oscilloscope signal has a shift as compared to Modelsim simulation?

TOP module- Master code


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;


Code:
entity I2c_master is

  
  port(
    clk      : in    std_logic;         --system clock
    reset_n  : in    std_logic;         --active low reset
    SDA      : inout std_logic;         --data read from slave
    LED      : out   std_logic_vector(7 downto 0);
    I2CCLOCK : out   std_logic);
end i2c_master;

architecture logic of I2c_master is




  component countertest is
    port (Aclr   : in  std_logic;
           clock : in  std_logic;
           Q     : out std_logic_vector(7 downto 0)
           );
  end component;

  
  signal data_clk, i2c_clk,e_signal : std_logic                    := '1';  --clock edges for sda
  signal sda_out           : std_logic                    := '1';  --internal sda
  signal ledsig1           : std_logic_vector(7 downto 0);  --latched in address and read/write
  signal tx1               : std_logic_vector(7 downto 0) := "00000000";  --data received from slave MSB
  signal tx2               : std_logic_vector(7 downto 0) := "00000000";  --data received from slave LSB

  shared variable step : integer range 0 to 13;

begin




  --generate the timing for the bus clock (scl_clk) and the data clock (data_clk)

  process(data_clk, reset_n)

  begin
     
    if(reset_n = '1') then              --  reset asserted
      sda_out <= '1';  --- set sda pin to high impedance--- set scl pin to high impedance
      i2c_clk <= '1';
      
      
    elsif(data_clk'event and data_clk = '1') then

      case step is
          
        when 0 =>
          
          sda_out <= '1';
          i2c_clk <= '1';
          step    := step+1;
          
        when 1 =>
          sda_out <= '0';
           i2c_clk <= '0';
          step    := step+1;
          
    
          
        when 2 =>                       ---  1st write byte
        
          sda_out <= '1';

          step := step+1;
          
        when 3 =>
          
          sda_out <= '0';

          step := step+1;
          
          
        when 4 =>
          
          sda_out <= '0';

          step := step+1;
          
        when 5 =>
          
          sda_out <= '1';

          step := step+1;
          
        when 6 =>
          
          sda_out <= '0';

          step := step+1;
        when 7 =>
          
          sda_out <= '0';

          step := step+1;
        when 8 =>
          
          sda_out <= '0';

          step := step+1;

        when 9 =>
          
          sda_out <= '0';
         
         
          step := step+1;

          
        when 10 => 
          sda_out<='Z';
          step := step+1;
          

          when 11 =>     
             if SDA<='0' then
         LED(0) <='1';
         step := step+1;
         else 
         LED(1) <='1';
        
          end if;    
           
       
	    when 12 =>     
          sda_out<='0';
          i2c_clk<='1';      --stop Bit
          step := step+1;   

       when 13 =>     
          sda_out<='1';
          step:=0;   
       end case;
     end if;


  end process;




  process(data_clk)
  begin
    if (data_clk'event and data_clk = '0'and (step >= 2) and (step <= 13)) then

      I2CCLOCK <= not data_clk;
    else
      I2CCLOCK <= i2c_clk;
    end if;
  end process;


  SDA<=sda_out;
  data_clk <= ledsig1(7);
   countertesting : countertest port map (Clock => CLK, Aclr => reset_n, Q => ledsig1);

end logic;

TestBench code with first slave acknowledgement being sent in simulation


Code:
library ieee;
use ieee.std_logic_1164.all;

entity TB is
end TB;

architecture behavioral of TB is

component i2c_master
        -- ports
        port 
    (clk      : IN     STD_LOGIC;                    --system clock
    reset_n   : IN     STD_LOGIC;                    --active low reset
    SDA       : inout    std_logic;
     
    LED       : out std_logic_vector(7 downto 0); 
 I2CCLOCK : out std_logic);
    end component;

  signal clk:  std_logic := '0';
  --signal sw_write:  std_logic := '0';
  
  signal reset_n, I2CCLOCK:  std_logic := '1';

  signal SDA :std_logic:='1';
  SIGNAL  data_clk  :  STD_LOGIC:='0';                        --clock edges for sda
  SIGNAL  sda_out  :  STD_LOGIC ;                -- internal sda
  SIGNAL  data_tx :  std_logic_vector(7 DOWNTO 0);    -- latched in data to write to slave
  SIGNAL  data_rx_MSB   :  std_logic_vector(7 DOWNTO 0);    -- data received from slave MSB
  SIGNAL  data_rx_LSB   :  std_logic_vector(7 DOWNTO 0);     --data received from slave LSB
      --tracks bit number in transaction SIGNAL  stretch            			:  STD_LOGIC := '0';           --identifies if slave is stretching scl
 
begin
clock1 : process
  begin
  wait for 10 ns; clk  <= not clk;

  end process ;

  stimulus : process
  begin
    wait for 4040 ns; reset_n  <= '0';
    

    wait;
  end process;


writing : process
  begin
 wait for 60576 ns ; SDA <='0';


    wait;
  end process;
-- 

i2c_master_0 : i2c_master
        -- port map
        port map( 
            -- Inputs
            
            clk => clk,
                       reset_n => reset_n,
            SDA => SDA,
            LED=>open, 
            I2CCLOCK =>I2CCLOCK
        );
--SDA<=ADCoutput;
end behavioral;

Thanks in Advance,
Kunal


I Modelsim one can see I2CCLOCK and SDA which are the ports used for clock and data transaction on I2C bus. once can see that SDA has shifted by one cycle in Oscilloscope waveform image as compared to Modelsim Image.
 

Code:
  process(data_clk)
  begin
    if (data_clk'event and data_clk = '0'and (step >= 2) and (step <= 13)) then

      I2CCLOCK <= not data_clk;
    else
      I2CCLOCK <= i2c_clk;
    end if;
  end process;

First off this doesn't follow any known VHDL template for a flip-flop. Not sure what the tools did with this. You're trying to improperly gate a clock. Besides being a bad idea in an FPGA it's coded in a way that is probably not getting synthesized correctly.

I'm not a VHDL guru, but I suspect the step variable that you are using probably has something to do with the shift problem. I typically don't use variables except for rare instances where I might want a signal shared among multiple registers that is made up of combinational logic. Using it for an increment...not sure how that would behave. Perhaps one of the VHDL gurus will give some insight on the problem.

Regards
 


I actuallly see that i did a big mistake with the improper clock triggering actually i want to generate a I2CCLOCK with respect to i2c_clock signal such that it triggers in falling edge of the data_clk. I corrected the 2nd process
aS

Code:
  process(data_clk,i2c_clk)

  begin
   if (data_clk'event and data_clk = '0')then 
       if ((step >= 2) and (step <= 13))then
       I2CCLOCK <= not data_clk;
      else
      I2CCLOCK <= i2c_clk;
      end if;
     end if;
  end process;

this should work as a Dflip flop! but in my case it I2CCLOCK is not getting generated. considering other options, I am not able to understand how to generate I2CCLOCK as a combinational logic using when.... else statement because i get an error that it was used in VHDL version 2008 and is invalid here..
 


I'm not sure what you expect this to do...
You have data_clk being used as the clock to this register and as an enabled data input to the register, besides being a bad way to create a muliplexer (if that was the intent) you are also trying to get a clocked process to trigger on i2c_clk besides the edge triggered event. You really should use falling_edge (data_clk) instead of the data_clk'event and data_clk = '0' as the former is safer to use than the latter.

Are you sure you don't want just a plain old mux?
Code:
  I2CCLOCK <= not data_clk when ((step >= 2) and (step <= 13)) = '1' else i2c_clk;

Regards

- - - Updated - - -

I still think you should not use a variable for step, unless you're a VHDL expert I would avoid using variables for any reason. Any code that is synthesizable can be realized without using variables. I'm not an expert, but have designed a lot of ASICs and FPGAs using either VHDL or Verilog and I've never found a design where I had to use a variable. I've used them for convenience, but only where I know exactly what logic gets produced (namely a small shared blob of random combinational logic, e.g. an address decode). In your case you're trying to create a counter out of a variable, which I'm not sure will behave the way you expect.

Regards
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…