Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

I2C Slave to Avalon MM Master

Status
Not open for further replies.

lemart92

Newbie level 4
Joined
Sep 15, 2014
Messages
6
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
75
Hi All - I'm fairly new to vhdl and I need to add an avalon memory mapped master to an I2C slave block. I've looked through a few pages but nothing really explains it. It looks like it's not that bad but I'm not really that good yet on writing the state machines.My code is pasted below:

Code:
-- Define libraries used
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
USE ieee.std_logic_arith.all;
--use work.bud_lite_pkg.all;



ENTITY i2c_rcvr IS

    PORT (
        clk			: IN  std_logic;
    	resetn			: IN  std_logic;
    	ack_test		: OUT std_logic;
    	data_in			: IN  std_logic_vector(7 downto 0);			  -- status register to be read by uP
    	addr_reg        	: OUT std_logic_VECTOR(7 downto 0);
    	wr_rd   		: OUT std_logic;
    	scl			: IN  std_logic;
    	sda			: INOUT std_logic;
    	dout 			: OUT std_logic_vector(7 downto 0)			  -- data received over i2c data byte (write data from uP)

	-- interface for AvMM-master
	mstr_en_n 		: out std_logic;
	mstr_address 		: out std_logic_vector(10 downto 0);
	mstr_write_n 		: out std_logic;
	mstr_read_n 		: out std_logic;
	mstr_data_in 		: in  std_logic_vector(31 downto 0);
	mstr_data_out 		: out std_logic_vector(31 downto 0);
	mstr_waitrequest_n	: in std_logic

	);
END i2c_rcvr;


ARCHITECTURE rtl OF i2c_rcvr IS

CONSTANT cIDLE_CNT		       	: integer := 24;				-- was 4 
CONSTANT cSAMPLE		       	: integer := 18;
CONSTANT cDEVICE_EOF		        : integer := 6;  
CONSTANT cEOF		       		: integer := 9;   			-- 

CONSTANT cRESET				: STD_LOGIC := '0';	-- chip reset

CONSTANT cDADDR				: std_logic_vector(6 DOWNTO 0) := "1000011";		-- 0x43 BL i2c official device address

TYPE i2c_state_type IS (start,stop,dev_addr,local_addr,ack,write_data,read_data,no_ack); 

-- sequential signals
SIGNAL i2c_state       			: i2c_state_type;   


SIGNAL bit_cnt				: integer RANGE 0 TO 9;
SIGNAL idle_cnt				: integer RANGE 0 TO 24;			-- was 9
SIGNAL delay_cnt			: integer RANGE 0 TO 18;		-- min sample requirement
SIGNAL ack_flag				: std_logic;				-- ack
SIGNAL shift_reg			: std_logic_vector(8 downto 0);
SIGNAL start_flag			: std_logic;
SIGNAL stop_flag			: std_logic;
SIGNAL dout_s				: std_logic_vector(7 downto 0);
SIGNAL sda_in				: std_logic;
--SIGNAL active				: std_logic;
SIGNAL rd_flag				: std_logic;
SIGNAL wr_flag				: std_logic;


SIGNAL lcl_flag				: std_logic;
SIGNAL start_rst			: std_logic;
SIGNAL start_i				: std_logic;
SIGNAL stop_i				: std_logic;
--SIGNAL active_i				: std_logic;
SIGNAL data_in_reg			: std_logic_vector(7 downto 0);
SIGNAL data_in_reg_i			: std_logic_vector(7 downto 0);
SIGNAL ack_flag_i			: std_logic;	
SIGNAL ack_flag_reg			: std_logic;
SIGNAL no_ack_flag			: std_logic;

SIGNAL scl_rclock_edge			: std_logic;
SIGNAL scl_fclock_edge			: std_logic;
SIGNAL scl_clock_samp			: std_logic_vector(1 DOWNTO 0);
SIGNAL scl_rclk				: std_logic;
SIGNAL scl_fclk				: std_logic;


BEGIN


i2c_rcvr_fsm : PROCESS (resetn,scl_rclk,start_i,stop_i)

BEGIN
        IF(resetn= cRESET) THEN

           bit_cnt <= 8;
           no_ack_flag <= '0';
           delay_cnt <= cSAMPLE;
           ack_flag <= '0';
           stop_flag <= '0';
           start_flag <= '0';
           start_rst <= '0';
           rd_flag <= '0';
           wr_flag <= '0';
           lcl_flag <= '0';
           i2c_state <= start;
           dout_s <= (OTHERS => '0');
           dout <= (OTHERS => '0');
           ---shift_reg <= "000000000";
	   shift_reg <= (OTHERS => '0');
	   addr_reg <= (OTHERS => '0');

        
        ELSIF(rising_edge(scl_rclk)) THEN	-- was scl, now in 4Mhz domain
	    start_rst <= start_i;
	    
	    
	    
            CASE i2c_state IS
                WHEN start =>                                   	-- idle pattern	all one's					
           	     bit_cnt <= 8;
                     ack_flag <= '0';
                     dout_s <= (OTHERS => '0');
                     stop_flag <= '0';
                     start_flag <= '0';
                     rd_flag <= '0';
                     wr_flag <= '0';
                     --shift_reg <= "000000000"; 
                     shift_reg <= (OTHERS => '0');
                     
                     IF start_i = '1' THEN
                     shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
                        start_flag <= '1';
                        bit_cnt <= 7; 	
                        i2c_state <= dev_addr;
                     ELSE
                        i2c_state <= start;
                     END IF;
                                   
                    
                WHEN dev_addr =>
                     
                     start_flag <= '0';
                     
                     IF bit_cnt > 0 THEN
                        bit_cnt <= bit_cnt - 1;
                        shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
                        i2c_state <= dev_addr; 
                        IF (bit_cnt = 1 AND shift_reg(6 DOWNTO 0) = cDADDR) THEN
                           ack_flag <= '1'; 
                        ELSE
                           ack_flag <= '0';
                        END IF;
                      ELSE
                        IF ack_flag = '1' THEN
                        --IF shift_reg(7 DOWNTO 1) = cDADDR THEN -- removed 7-16-15
                           rd_flag <= shift_reg(0);		-- read or write operation
                           bit_cnt <= 8;
                           ack_flag <= '0'; 
                           i2c_state <= ack;
                        ELSE
                           shift_reg <= (OTHERS => '0');
                           i2c_state <= start;
                        END IF;
                     END IF;
                   
                   
 		WHEN ack =>  
 		     
 		     ack_flag <= '0';
                     
 		     IF rd_flag = '1' THEN
 		        --data_in_reg <= data_in;
 		        bit_cnt <= 7;
 		        i2c_state <= read_data;
 		     ELSIF start_i = '1' THEN
 		           bit_cnt <= 8;
 		           i2c_state <= dev_addr;
 		     ELSIF lcl_flag = '1' THEN
 		           bit_cnt <= 7;   -- was 8 
 		           shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
 		           i2c_state <= write_data;
 		     ELSIF wr_flag = '1' THEN
 		           wr_flag <= '0';
 		           shift_reg <= (OTHERS => '0');  -- new
 		           i2c_state  <= start;  	-- used to be stop for simulation     
 		     ELSE
 		           bit_cnt <= 7;
 		           i2c_state <= local_addr;
 		     END IF;
 		    
                     
                     
		WHEN local_addr =>
		  
                        ack_flag <= '0';
                        IF bit_cnt > 0 THEN
                           bit_cnt <= bit_cnt - 1;
                           shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
                           i2c_state <= local_addr;
                           if bit_cnt = 1 THEN
			      ack_flag <= '1';
			   end if;
                        ELSE
                           addr_reg <= shift_reg(7 DOWNTO 0);
                           bit_cnt <= 8;
                           ack_flag <= '0';
                           lcl_flag <= '1';
                           i2c_state <= ack;	
                        END IF;
                  
                        IF bit_cnt = 0 THEN
		           wr_flag <= '1';
                        END IF;
                
                
                WHEN read_data =>
                                
		  IF bit_cnt > 0 THEN
		     bit_cnt <= bit_cnt - 1;
		     -----data_in_reg <= data_in_reg(6 downto 0) & '1';
		     i2c_state <= read_data;
		  ELSE
		     bit_cnt <= 8;
		     rd_flag <= '0';
		     no_ack_flag <= '1';
		     i2c_state <= no_ack;
		  END IF;
                                             
                
                
      		WHEN write_data =>
      		
  		     ack_flag <= '0';
		     lcl_flag <= '0';
		     IF start_i = '1' THEN
		        shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
		        I2c_state <= dev_addr;
		        wr_flag <= '0';
		        bit_cnt <= 7;
		     ELSE
                       IF bit_cnt > 0 THEN
                          bit_cnt <= bit_cnt - 1;
                          shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
                          i2c_state <= write_data;
                          IF bit_cnt = 1 THEN
                             ack_flag <= '1';
			  END IF;
                       ELSE
                          dout <= shift_reg(7 DOWNTO 0);
                          ack_flag <= '0';  
                          bit_cnt <= 8;
                          i2c_state <= ack;
                       END IF;
                     END IF;
                                              
                
                WHEN no_ack =>
 		     rd_flag <= '0'; 
 		     no_ack_flag <= '0';
 		     ack_flag <= '0';			-- added 11/6/14 and change to start
 		     shift_reg <= (OTHERS => '0');	-- new
                     i2c_state <= start;		-- used to be stop for simulation
                     
                WHEN stop =>
                     
                     IF stop_i = '1' THEN
                        ack_flag <= '0';
			i2c_state <= start;
                     ELSE
                        i2c_state <= stop;
                     END IF;
                              
                WHEN OTHERS => i2c_state <= start;						-- go to bloody idle 

            END CASE;
        END IF; 
	   
END PROCESS i2c_rcvr_fsm; 



------------------------------------------------------------------------------
-- start condition detection,( good noise tolerance )
------------------------------------------------------------------------------
PROCESS (sda_in,start_rst,rd_flag,ack_flag)
  BEGIN
      IF (start_rst = '1' or rd_flag = '1' or ack_flag = '1' ) THEN
          start_i <= '0'; 
       
      ELSIF (sda_in'event AND sda_in = '0') THEN
          start_i <= scl; 
      END IF;
END PROCESS;


------------------------------------------------------------------------------
-- stop condition detection
PROCESS (resetn,scl,sda_in,start_i,rd_flag,no_ack_flag,ack_flag,lcl_flag,wr_flag)
  BEGIN
      IF resetn = cRESET or scl = '0' or start_i = '1' or rd_flag = '1' OR no_ack_flag = '1'
         or ack_flag = '1' or lcl_flag = '1' or wr_flag = '1' THEN
	 stop_i <= '0';
	
      ELSIF sda_in = '1' AND sda_in'event THEN
	  IF scl = '1' then
	     stop_i <= '1';
	  END IF;
      END IF;
END PROCESS;



PROCESS (resetn,clk)	-- was scl
  BEGIN
     IF resetn = cRESET THEN
        data_in_reg_i <= (OTHERS => '0');
        
     ELSIF(rising_edge(clk)) THEN
         IF ack_flag_reg = '1' THEN
            data_in_reg_i <= data_in;

         END IF;
     END IF;
END PROCESS;


--===========

PROCESS (resetn,scl_fclk)	-- was scl, now 4Mhz domain
  BEGIN
     IF resetn = cRESET THEN
        data_in_reg <= (OTHERS => '0');
        
     ELSIF(rising_edge(scl_fclk)) THEN
        IF rd_flag = '1' AND ack_flag_reg = '0' THEN
            data_in_reg <= data_in_reg (6 downto 0) & '1';
        ELSE
           data_in_reg <= data_in_reg_i;
         END IF;
     END IF;
END PROCESS;



PROCESS (resetn,scl_fclk)
  BEGIN
     IF resetn = cRESET THEN
        ack_flag_reg <= '0';
     
     ELSIF(rising_edge(scl_fclk)) THEN	
           ack_flag_reg <= ack_flag;
     END IF;
     
END PROCESS;      
     
PROCESS (resetn,clk)
  BEGIN
     IF resetn = cRESET THEN
        scl_clock_samp <= (OTHERS => '0');
        
     ELSIF(rising_edge(clk)) THEN
           scl_clock_samp <= scl_clock_samp(0) & scl;
     END IF;
     
END PROCESS;      

PROCESS (resetn,clk)
  BEGIN
     IF resetn = cRESET THEN
        scl_rclk <= '0';
        scl_fclk <= '0';
        
     ELSIF(falling_edge(clk)) THEN
           scl_rclk <= scl_rclock_edge;
           scl_fclk <= scl_fclock_edge;
     END IF;
     
END PROCESS;      


scl_rclock_edge <= '1' WHEN scl_clock_samp(1) = '0' AND scl_clock_samp(0) = '1' ELSE '0';
scl_fclock_edge <= '1' WHEN scl_clock_samp(1) = '1' AND scl_clock_samp(0) = '0' ELSE '0';


--active <= active_i;
--active <= ack_flag;

wr_rd <= rd_flag;


sda_in <= sda;

ack_test <= '1' WHEN (ack_flag_reg = '1' AND shift_reg(7 DOWNTO 1) = cDADDR) ELSE '0'; 

--sda <= '0' WHEN (ack_flag_reg = '1' AND shift_reg(7 DOWNTO 1) = cDADDR) ELSE data_in_reg(7) WHEN (rd_flag = '1' AND ack_flag_reg = '0') ELSE

sda <= '0' WHEN ack_flag_reg = '1'  ELSE data_in_reg(7) WHEN (rd_flag = '1' AND ack_flag_reg = '0') ELSE 'Z';



END rtl;
 

You should specify the problem you are facing. Please simulate your code using a test-bench and then verify if it is delivering the functionality it should. I am sure I2C slave Verilog/VHDL models are freely available which you can connect to your I2C master and then verify data exchange.
 
Hi All - I'm fairly new to vhdl and I need to add an avalon memory mapped master to an I2C slave block. I've looked through a few pages but nothing really explains it. It looks like it's not that bad but I'm not really that good yet on writing the state machines.My code is pasted below:

Code:
-- Define libraries used
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
USE ieee.std_logic_arith.all;
--use work.bud_lite_pkg.all;



ENTITY i2c_rcvr IS

    PORT (
        clk			: IN  std_logic;
    	resetn			: IN  std_logic;
    	ack_test		: OUT std_logic;
    	data_in			: IN  std_logic_vector(7 downto 0);			  -- status register to be read by uP
    	addr_reg        	: OUT std_logic_VECTOR(7 downto 0);
    	wr_rd   		: OUT std_logic;
    	scl			: IN  std_logic;
    	sda			: INOUT std_logic;
    	dout 			: OUT std_logic_vector(7 downto 0)			  -- data received over i2c data byte (write data from uP)

	-- interface for AvMM-master
	mstr_en_n 		: out std_logic;
	mstr_address 		: out std_logic_vector(10 downto 0);
	mstr_write_n 		: out std_logic;
	mstr_read_n 		: out std_logic;
	mstr_data_in 		: in  std_logic_vector(31 downto 0);
	mstr_data_out 		: out std_logic_vector(31 downto 0);
	mstr_waitrequest_n	: in std_logic

	);
END i2c_rcvr;


ARCHITECTURE rtl OF i2c_rcvr IS

CONSTANT cIDLE_CNT		       	: integer := 24;				-- was 4 
CONSTANT cSAMPLE		       	: integer := 18;
CONSTANT cDEVICE_EOF		        : integer := 6;  
CONSTANT cEOF		       		: integer := 9;   			-- 

CONSTANT cRESET				: STD_LOGIC := '0';	-- chip reset

CONSTANT cDADDR				: std_logic_vector(6 DOWNTO 0) := "1000011";		-- 0x43 BL i2c official device address

TYPE i2c_state_type IS (start,stop,dev_addr,local_addr,ack,write_data,read_data,no_ack); 

-- sequential signals
SIGNAL i2c_state       			: i2c_state_type;   


SIGNAL bit_cnt				: integer RANGE 0 TO 9;
SIGNAL idle_cnt				: integer RANGE 0 TO 24;			-- was 9
SIGNAL delay_cnt			: integer RANGE 0 TO 18;		-- min sample requirement
SIGNAL ack_flag				: std_logic;				-- ack
SIGNAL shift_reg			: std_logic_vector(8 downto 0);
SIGNAL start_flag			: std_logic;
SIGNAL stop_flag			: std_logic;
SIGNAL dout_s				: std_logic_vector(7 downto 0);
SIGNAL sda_in				: std_logic;
--SIGNAL active				: std_logic;
SIGNAL rd_flag				: std_logic;
SIGNAL wr_flag				: std_logic;


SIGNAL lcl_flag				: std_logic;
SIGNAL start_rst			: std_logic;
SIGNAL start_i				: std_logic;
SIGNAL stop_i				: std_logic;
--SIGNAL active_i				: std_logic;
SIGNAL data_in_reg			: std_logic_vector(7 downto 0);
SIGNAL data_in_reg_i			: std_logic_vector(7 downto 0);
SIGNAL ack_flag_i			: std_logic;	
SIGNAL ack_flag_reg			: std_logic;
SIGNAL no_ack_flag			: std_logic;

SIGNAL scl_rclock_edge			: std_logic;
SIGNAL scl_fclock_edge			: std_logic;
SIGNAL scl_clock_samp			: std_logic_vector(1 DOWNTO 0);
SIGNAL scl_rclk				: std_logic;
SIGNAL scl_fclk				: std_logic;


BEGIN


i2c_rcvr_fsm : PROCESS (resetn,scl_rclk,start_i,stop_i)

BEGIN
        IF(resetn= cRESET) THEN

           bit_cnt <= 8;
           no_ack_flag <= '0';
           delay_cnt <= cSAMPLE;
           ack_flag <= '0';
           stop_flag <= '0';
           start_flag <= '0';
           start_rst <= '0';
           rd_flag <= '0';
           wr_flag <= '0';
           lcl_flag <= '0';
           i2c_state <= start;
           dout_s <= (OTHERS => '0');
           dout <= (OTHERS => '0');
           ---shift_reg <= "000000000";
	   shift_reg <= (OTHERS => '0');
	   addr_reg <= (OTHERS => '0');

        
        ELSIF(rising_edge(scl_rclk)) THEN	-- was scl, now in 4Mhz domain
	    start_rst <= start_i;
	    
	    
	    
            CASE i2c_state IS
                WHEN start =>                                   	-- idle pattern	all one's					
           	     bit_cnt <= 8;
                     ack_flag <= '0';
                     dout_s <= (OTHERS => '0');
                     stop_flag <= '0';
                     start_flag <= '0';
                     rd_flag <= '0';
                     wr_flag <= '0';
                     --shift_reg <= "000000000"; 
                     shift_reg <= (OTHERS => '0');
                     
                     IF start_i = '1' THEN
                     shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
                        start_flag <= '1';
                        bit_cnt <= 7; 	
                        i2c_state <= dev_addr;
                     ELSE
                        i2c_state <= start;
                     END IF;
                                   
                    
                WHEN dev_addr =>
                     
                     start_flag <= '0';
                     
                     IF bit_cnt > 0 THEN
                        bit_cnt <= bit_cnt - 1;
                        shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
                        i2c_state <= dev_addr; 
                        IF (bit_cnt = 1 AND shift_reg(6 DOWNTO 0) = cDADDR) THEN
                           ack_flag <= '1'; 
                        ELSE
                           ack_flag <= '0';
                        END IF;
                      ELSE
                        IF ack_flag = '1' THEN
                        --IF shift_reg(7 DOWNTO 1) = cDADDR THEN -- removed 7-16-15
                           rd_flag <= shift_reg(0);		-- read or write operation
                           bit_cnt <= 8;
                           ack_flag <= '0'; 
                           i2c_state <= ack;
                        ELSE
                           shift_reg <= (OTHERS => '0');
                           i2c_state <= start;
                        END IF;
                     END IF;
                   
                   
 		WHEN ack =>  
 		     
 		     ack_flag <= '0';
                     
 		     IF rd_flag = '1' THEN
 		        --data_in_reg <= data_in;
 		        bit_cnt <= 7;
 		        i2c_state <= read_data;
 		     ELSIF start_i = '1' THEN
 		           bit_cnt <= 8;
 		           i2c_state <= dev_addr;
 		     ELSIF lcl_flag = '1' THEN
 		           bit_cnt <= 7;   -- was 8 
 		           shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
 		           i2c_state <= write_data;
 		     ELSIF wr_flag = '1' THEN
 		           wr_flag <= '0';
 		           shift_reg <= (OTHERS => '0');  -- new
 		           i2c_state  <= start;  	-- used to be stop for simulation     
 		     ELSE
 		           bit_cnt <= 7;
 		           i2c_state <= local_addr;
 		     END IF;
 		    
                     
                     
		WHEN local_addr =>
		  
                        ack_flag <= '0';
                        IF bit_cnt > 0 THEN
                           bit_cnt <= bit_cnt - 1;
                           shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
                           i2c_state <= local_addr;
                           if bit_cnt = 1 THEN
			      ack_flag <= '1';
			   end if;
                        ELSE
                           addr_reg <= shift_reg(7 DOWNTO 0);
                           bit_cnt <= 8;
                           ack_flag <= '0';
                           lcl_flag <= '1';
                           i2c_state <= ack;	
                        END IF;
                  
                        IF bit_cnt = 0 THEN
		           wr_flag <= '1';
                        END IF;
                
                
                WHEN read_data =>
                                
		  IF bit_cnt > 0 THEN
		     bit_cnt <= bit_cnt - 1;
		     -----data_in_reg <= data_in_reg(6 downto 0) & '1';
		     i2c_state <= read_data;
		  ELSE
		     bit_cnt <= 8;
		     rd_flag <= '0';
		     no_ack_flag <= '1';
		     i2c_state <= no_ack;
		  END IF;
                                             
                
                
      		WHEN write_data =>
      		
  		     ack_flag <= '0';
		     lcl_flag <= '0';
		     IF start_i = '1' THEN
		        shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
		        I2c_state <= dev_addr;
		        wr_flag <= '0';
		        bit_cnt <= 7;
		     ELSE
                       IF bit_cnt > 0 THEN
                          bit_cnt <= bit_cnt - 1;
                          shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
                          i2c_state <= write_data;
                          IF bit_cnt = 1 THEN
                             ack_flag <= '1';
			  END IF;
                       ELSE
                          dout <= shift_reg(7 DOWNTO 0);
                          ack_flag <= '0';  
                          bit_cnt <= 8;
                          i2c_state <= ack;
                       END IF;
                     END IF;
                                              
                
                WHEN no_ack =>
 		     rd_flag <= '0'; 
 		     no_ack_flag <= '0';
 		     ack_flag <= '0';			-- added 11/6/14 and change to start
 		     shift_reg <= (OTHERS => '0');	-- new
                     i2c_state <= start;		-- used to be stop for simulation
                     
                WHEN stop =>
                     
                     IF stop_i = '1' THEN
                        ack_flag <= '0';
			i2c_state <= start;
                     ELSE
                        i2c_state <= stop;
                     END IF;
                              
                WHEN OTHERS => i2c_state <= start;						-- go to bloody idle 

            END CASE;
        END IF; 
	   
END PROCESS i2c_rcvr_fsm; 



------------------------------------------------------------------------------
-- start condition detection,( good noise tolerance )
------------------------------------------------------------------------------
PROCESS (sda_in,start_rst,rd_flag,ack_flag)
  BEGIN
      IF (start_rst = '1' or rd_flag = '1' or ack_flag = '1' ) THEN
          start_i <= '0'; 
       
      ELSIF (sda_in'event AND sda_in = '0') THEN
          start_i <= scl; 
      END IF;
END PROCESS;


------------------------------------------------------------------------------
-- stop condition detection
PROCESS (resetn,scl,sda_in,start_i,rd_flag,no_ack_flag,ack_flag,lcl_flag,wr_flag)
  BEGIN
      IF resetn = cRESET or scl = '0' or start_i = '1' or rd_flag = '1' OR no_ack_flag = '1'
         or ack_flag = '1' or lcl_flag = '1' or wr_flag = '1' THEN
	 stop_i <= '0';
	
      ELSIF sda_in = '1' AND sda_in'event THEN
	  IF scl = '1' then
	     stop_i <= '1';
	  END IF;
      END IF;
END PROCESS;



PROCESS (resetn,clk)	-- was scl
  BEGIN
     IF resetn = cRESET THEN
        data_in_reg_i <= (OTHERS => '0');
        
     ELSIF(rising_edge(clk)) THEN
         IF ack_flag_reg = '1' THEN
            data_in_reg_i <= data_in;

         END IF;
     END IF;
END PROCESS;


--===========

PROCESS (resetn,scl_fclk)	-- was scl, now 4Mhz domain
  BEGIN
     IF resetn = cRESET THEN
        data_in_reg <= (OTHERS => '0');
        
     ELSIF(rising_edge(scl_fclk)) THEN
        IF rd_flag = '1' AND ack_flag_reg = '0' THEN
            data_in_reg <= data_in_reg (6 downto 0) & '1';
        ELSE
           data_in_reg <= data_in_reg_i;
         END IF;
     END IF;
END PROCESS;



PROCESS (resetn,scl_fclk)
  BEGIN
     IF resetn = cRESET THEN
        ack_flag_reg <= '0';
     
     ELSIF(rising_edge(scl_fclk)) THEN	
           ack_flag_reg <= ack_flag;
     END IF;
     
END PROCESS;      
     
PROCESS (resetn,clk)
  BEGIN
     IF resetn = cRESET THEN
        scl_clock_samp <= (OTHERS => '0');
        
     ELSIF(rising_edge(clk)) THEN
           scl_clock_samp <= scl_clock_samp(0) & scl;
     END IF;
     
END PROCESS;      

PROCESS (resetn,clk)
  BEGIN
     IF resetn = cRESET THEN
        scl_rclk <= '0';
        scl_fclk <= '0';
        
     ELSIF(falling_edge(clk)) THEN
           scl_rclk <= scl_rclock_edge;
           scl_fclk <= scl_fclock_edge;
     END IF;
     
END PROCESS;      


scl_rclock_edge <= '1' WHEN scl_clock_samp(1) = '0' AND scl_clock_samp(0) = '1' ELSE '0';
scl_fclock_edge <= '1' WHEN scl_clock_samp(1) = '1' AND scl_clock_samp(0) = '0' ELSE '0';


--active <= active_i;
--active <= ack_flag;

wr_rd <= rd_flag;


sda_in <= sda;

ack_test <= '1' WHEN (ack_flag_reg = '1' AND shift_reg(7 DOWNTO 1) = cDADDR) ELSE '0'; 

--sda <= '0' WHEN (ack_flag_reg = '1' AND shift_reg(7 DOWNTO 1) = cDADDR) ELSE data_in_reg(7) WHEN (rd_flag = '1' AND ack_flag_reg = '0') ELSE

sda <= '0' WHEN ack_flag_reg = '1'  ELSE data_in_reg(7) WHEN (rd_flag = '1' AND ack_flag_reg = '0') ELSE 'Z';



END rtl;


first - there is already an i2c slave free from altera you can use.
i used it in the past and it worked perfectly.

if you want to do your own i2c slave you will need to use template

you can get all the information how to do it from altera.

https://www.altera.com/support/support-resources/design-examples/intellectual-property/embedded/nios-ii/exm-avalon-memory-slave.html
 
first - there is already an i2c slave free from altera you can use.
i used it in the past and it worked perfectly.

if you want to do your own i2c slave you will need to use template

you can get all the information how to do it from altera.

https://www.altera.com/support/support-resources/design-examples/intellectual-property/embedded/nios-ii/exm-avalon-memory-slave.html

aruipksni - can you point me to the altera i2c slave that you used? I didn't find anything on their site.

Thanks for your suggestion.
 

You have design issues. I'm not going to go into much detail or specifying all the issues as I don't have time to examine the code that closely.

Minor stuff:
You have extra signals in your sensitivity list.
You're using the non-standard synopsys packages _unsigned and _arith (twice)

Architectural flaw:
You are generating clocks using flip-flops, that is okay in ASICs (where there's clock tree insertion), but not recommended in FPGAs.

Big fat no-no:
You've got asynchronous signals going into your FSM, that is used to make decisions on what is done to multiple signals, this can cause to outputs that are supposed to switch at the same time switch state with a 1 clock cycle skew between them.

Recommendation:
Use a single clock for the entire design, sample all the inputs with demet registers and run the design with an enable that is at the bit rate of the i2c.
 
You have design issues. I'm not going to go into much detail or specifying all the issues as I don't have time to examine the code that closely.

Minor stuff:
You have extra signals in your sensitivity list.
You're using the non-standard synopsys packages _unsigned and _arith (twice)

Architectural flaw:
You are generating clocks using flip-flops, that is okay in ASICs (where there's clock tree insertion), but not recommended in FPGAs.

Big fat no-no:
You've got asynchronous signals going into your FSM, that is used to make decisions on what is done to multiple signals, this can cause to outputs that are supposed to switch at the same time switch state with a 1 clock cycle skew between them.

Recommendation:
Use a single clock for the entire design, sample all the inputs with demet registers and run the design with an enable that is at the bit rate of the i2c.

Thanks for the detailed response ads-see. I'll go back and try to incorporate your suggestions.
 

aruipksni - can you point me to the altera i2c slave that you used? I didn't find anything on their site.

Thanks for your suggestion.

you can go to :

**broken link removed**


and d/l the ip.
 

you can go to :
**broken link removed**
and d/l the ip.

Just for my knowledge...
The above seems like an OpenCores IP which Altera has endorsed (correct me if I am wrong).

From your post in #3, I was thinking about the I2C slave being an ALtera Proprietary IP (like we have Xilinx IPs generated from Coregen).
 
Just for my knowledge...
The above seems like an OpenCores IP which Altera has endorsed (correct me if I am wrong).

From your post in #3, I was thinking about the I2C slave being an ALtera Proprietary IP (like we have Xilinx IPs generated from Coregen).

deer dpaul
you are 100% correct about this. this is adopted open ip core.

and i just checked my old files, and i found that i
was using my PIO/i2c code, so i wasn't using this
ip core, as i thought before (it's been a long time since i use it).

Touché !
 

If this is the same I2C core that was on opencores by some Richard guy, that core did have a bug that we found in some specific test cases (which I no longer recall). I'm not sure if the recent update addresses the issue we found or not (as I don't recall what the issue was in the first place!)
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top