⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.txt

📁 I2C core code in Hardware descrption language so as enable a cpld/fpga to be programmed for specific
💻 TXT
📖 第 1 页 / 共 2 页
字号:
--
-- VHDL Architecture i2c.i2c_core_v02.arc
--
-- Created:
--          by - Eli&Natalie.UNKNOWN (ELI)
--          at - 20:01:49 06/11/2008
--
-- using Mentor Graphics HDL Designer(TM) 2007.1 (Build 19)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

ENTITY i2c_core_v02 IS
  generic
    (
     CLK_FREQ : natural := 25000000
    ); 
  PORT
    ( 
     --INPUTS
     sys_clk  : IN     std_logic;
     sys_rst  : IN     std_logic;
     start    : IN     std_logic;
     stop     : IN     std_logic;
     read     : IN     std_logic;
     write    : IN     std_logic;
     send_ack : IN     std_logic;
     mstr_din : IN     std_logic_vector ( 7 DOWNTO 0 );
     slv_din  : IN     std_logic_vector ( 7 DOWNTO 0 );      
     slv_a0   : IN     std_logic;
     slv_a1   : IN     std_logic;
     slv_a2   : IN     std_logic;      
     slv_a3   : IN     std_logic;
     slv_a4   : IN     std_logic;
     slv_a5   : IN     std_logic;
     slv_a6   : IN     std_logic;
     reg_exist: IN     std_logic;            
     --OUTPUTS
     sda      : INOUT  std_logic;
     scl      : INOUT  std_logic;
     slv_read : OUT    std_logic;
     slv_write: OUT    std_logic;     
     slv_busy : OUT    std_logic; --slave is busy
     slv_int  : OUT    std_logic; --interrupt from the slave to its interface
     free     : OUT    std_logic;
     rec_ack  : OUT    std_logic;
     ready    : OUT    std_logic;
     mstr_slv : OUT    std_logic;
     mstr_dout: OUT    std_logic_vector( 7 downto 0 );
     slv_dout : OUT    std_logic_vector( 7 DOWNTO 0 )
    );
END ENTITY i2c_core_v02;

--
ARCHITECTURE arc OF i2c_core_v02 IS
  
  constant FRAME     : natural := 11; -- number of bits in frame: start, stop, 8 bits data, 1 bit acknoledge
  constant BAUD      : natural := 200000;
--  constant CLK_FREQ  : natural := 25000000;
  constant FULL_BIT  : natural := CLK_FREQ / BAUD;
  constant HALF_BIT  : natural := FULL_BIT / 2;
  constant GAP_WIDTH : natural := FULL_BIT * 2;
  
  signal i_mstr_slv : std_logic; --for master-slave arbitration 1 - master, 0 - slave
  signal i_free     : std_logic;
  signal i_ready    : std_logic;
  signal i_sda_mstr : std_logic;
  signal i_scl_mstr : std_logic;
  signal i_scl_cntr : natural range 0 to 511;
  signal i_bit_cntr_mstr : natural range 0 to 7;
  signal i_ack_mstr : std_logic;
  signal i_mstr_rd_data : std_logic_vector( 7 downto 0 );
  
  signal i_mstr_ad  : std_logic_vector( 7 downto 0 ); --latched address and data
  alias  fld_rd_wr  : std_logic is i_mstr_ad( 0 ); --1 - read, 0 - write
  
  -- slave signals 
  
  signal i_slv_sda_fall : std_logic;
  signal i_slv_sda_rise : std_logic;
  signal i_slv_scl_fall : std_logic;
  signal i_slv_scl_rise : std_logic;
  
  signal i_sda_sam : std_logic_vector( 1 downto 0 );
  signal i_scl_sam : std_logic_vector( 1 downto 0 );
  
  signal i_sda_slv : std_logic;
  
  signal i_slv_data     : std_logic_vector( 7 downto 0 );
  signal i_slv_addr     : std_logic_vector( 7 downto 0 );
  signal i_slv_reg_addr : std_logic_vector( 7 downto 0 );
  signal i_slv_bit_cnt  : natural range 0 to 10;
  signal i_slv_stop_bit : std_logic;
  signal i_slv_strt_bit : std_logic;
  signal i_slv_dout     : std_logic_vector( 7 downto 0 );  
  
  --address "1111111" not legal
  signal SLAVE_ADDR : std_logic_vector( 6 downto 0 );  
  
  type i2c_master_state is ( mstr_idle, mstr_start_cnt , mstr_active , mstr_wait_first_half , mstr_wait_second_half ,
                             mstr_wait_full , mstr_wait_ack , mstr_wait_ack_second_half , mstr_wait_ack_third_half ,
                             mstr_wait_ack_fourth_half , mstr_rd_wait_low , mstr_rd_wait_half , mstr_rd_read , mstr_stop ,
                             mstr_rd_wait_last_half , mstr_rd_wait_ack , mstr_rd_get_ack , mstr_restart , mstr_gap );
                             
  signal stm_mstr : i2c_master_state;
  
  type i2c_slave_state is ( slv_idle , slv_get_addr , slv_rd_wr , slv_read_reg_addr , slv_write_data , slv_send_addr_ack, slv_wait_ack , slv_send_data_ack ,
                            slv_wait_data_ack , slv_read_data , slv_get_data_ack , slv_get_wait_data_ack );
  signal stm_slv : i2c_slave_state;
  
BEGIN
  sda   <= i_sda_mstr when ( i_mstr_slv = '1' ) else i_sda_slv;
  scl   <= i_scl_mstr;
  free  <= i_free;
  ready <= i_ready;
  mstr_slv <= i_mstr_slv;
  
  arbitration:
  process( sys_clk , sys_rst )
    begin
      if ( sys_rst = '1' ) then
        i_mstr_slv <= '1';
       -- i_slv_stop_bit <= '0';
      elsif rising_edge( sys_clk ) then
        
        SLAVE_ADDR <= slv_a6 & slv_a5 & slv_a4 & slv_a3 & slv_a2 & slv_a1 & slv_a0;
        
        i_scl_sam( 0 ) <= scl;
        i_scl_sam( 1 ) <= i_scl_sam( 0 );
        
        i_sda_sam( 0 ) <= sda;
        i_sda_sam( 1 ) <= i_sda_sam( 0 );
        
        if ( sda = '0' ) and ( scl = '1' ) and ( stm_mstr = mstr_idle ) then
          i_mstr_slv <= '0'; --slave
        elsif ( i_slv_sda_rise = '1' ) and ( to_X01( scl ) = '1' ) then
          i_mstr_slv <= '1'; --master
        end if;
      end if;
    end process arbitration;
    
  i_slv_sda_fall <= not i_sda_sam( 0 ) and i_sda_sam( 1 );
  i_slv_sda_rise <= i_sda_sam( 0 ) and not i_sda_sam( 1 );    
  
  i_slv_scl_fall <= not i_scl_sam( 0 ) and i_scl_sam( 1 );
  i_slv_scl_rise <= i_scl_sam( 0 ) and not i_scl_sam( 1 );
  
  i_slv_stop_bit <= '1' when ( i_slv_sda_rise = '1' ) and ( to_X01( scl ) = '1' ) else '0'; 
  i_slv_strt_bit <= '1' when ( i_slv_sda_fall = '1' ) and ( to_X01( scl ) = '1' ) else '0';
  
  rec_ack <= not i_ack_mstr;
  
  i2c_master: 
  process( sys_clk , sys_rst )
    begin
      if ( sys_rst = '1' ) then
        stm_mstr   <= mstr_idle;
        i_free     <= '0';
        i_ready    <= '0';  
        i_sda_mstr <= 'Z';
        i_scl_mstr <= 'Z';
        i_scl_cntr <= 0;
        i_bit_cntr_mstr <= 7;
        i_ack_mstr <= '1';
        i_mstr_rd_data <= ( others => '0' ); 
        mstr_dout <= ( others => '0' ); 
        i_mstr_ad <= ( others => '0' );      
      elsif rising_edge( sys_clk ) then
        if ( i_mstr_slv = '1' ) then
          case stm_mstr is
          -------------------  
          when mstr_idle =>
            i_free <= '1';
            i_ready <= '0';
            i_sda_mstr <= 'Z';
            i_scl_mstr <= 'Z';                
            if ( start = '1' ) then
              stm_mstr <= mstr_start_cnt;
              i_free <= '0';          
            else
              stm_mstr <= mstr_idle;
            end if;
          -------------------
          when mstr_start_cnt =>
            i_sda_mstr <= '0';
            i_scl_mstr <= '1';
            if ( i_scl_cntr < HALF_BIT ) then
              i_scl_cntr <= i_scl_cntr + 1;
              stm_mstr <= mstr_start_cnt;
            else  
              i_scl_cntr <= 0;
              stm_mstr <= mstr_active;
              i_scl_mstr <= '0';
            end if;
          -------------------
          when mstr_active =>
            i_ready <= '1';   
            i_scl_mstr <= '0';
            i_sda_mstr <= '0';
            i_bit_cntr_mstr <= 7;
            if ( read = '1' ) then 
              stm_mstr <= mstr_rd_wait_low;
              i_ready <= '0';
            elsif ( write = '1' ) then
              i_mstr_ad <= mstr_din;
              i_ready <= '0';
              stm_mstr <= mstr_wait_first_half; 
            elsif ( stop = '1' ) then
              stm_mstr <= mstr_stop;
            elsif ( start = '1' ) then
              stm_mstr <= mstr_restart;
            end if;
          --------------------
          --####################
          --##### WRITE ########
          --####################
          when mstr_wait_first_half =>
            if ( i_scl_cntr < HALF_BIT ) then
              i_scl_mstr <= '0';
              i_scl_cntr <= i_scl_cntr + 1;
            else
              i_scl_cntr <= 0;
              stm_mstr <= mstr_wait_second_half;
              i_sda_mstr <= i_mstr_ad( i_bit_cntr_mstr );                     
            end if;
          --------------------
          when mstr_wait_second_half =>
            if ( i_scl_cntr < HALF_BIT ) then
              i_scl_cntr <= i_scl_cntr + 1;
              stm_mstr <= mstr_wait_second_half;
            else            
              i_scl_cntr <= 0;              
              stm_mstr <= mstr_wait_full;              
            end if;
          ---------------------
          when mstr_wait_full =>
            if ( i_scl_cntr < FULL_BIT ) then 
              i_scl_mstr <= '1';
              i_scl_cntr <= i_scl_cntr + 1;
              stm_mstr <= mstr_wait_full;
            else  
              i_scl_cntr <= 0;              
              if ( i_bit_cntr_mstr >= 1 ) then
                i_bit_cntr_mstr <= i_bit_cntr_mstr - 1;
                stm_mstr <= mstr_wait_first_half;
              elsif ( i_bit_cntr_mstr = 0 ) then
                --i_sda_mstr <= 'Z';              
                stm_mstr <= mstr_wait_ack;                
              end if;                                          
            end if;
          --------------------
          --####################
          --#### ACKNOWLEDGE ###
          --####################
          when mstr_wait_ack =>
            i_scl_mstr <= '0';
            if ( i_scl_cntr < HALF_BIT ) then
              i_scl_cntr <= i_scl_cntr + 1;
            else
              i_scl_cntr <= 0;
              i_sda_mstr <= 'Z';
              stm_mstr <= mstr_wait_ack_second_half;
            end if;
          --------------------
          when mstr_wait_ack_second_half => 
            if ( i_scl_cntr < HALF_BIT ) then
              i_scl_cntr <= i_scl_cntr + 1;
            else
              i_scl_cntr <= 0;
              i_sda_mstr <= 'Z';
              stm_mstr <= mstr_wait_ack_third_half;
            end if;               
          --------------------  
          when mstr_wait_ack_third_half =>
            i_scl_mstr <= '1';
            if ( i_scl_cntr < HALF_BIT ) then
              i_scl_cntr <= i_scl_cntr + 1;
            else
              i_scl_cntr <= 0;
              i_sda_mstr <= 'Z';
              i_ack_mstr <= sda;
              stm_mstr <= mstr_wait_ack_fourth_half;
            end if;        
          --------------------
          when mstr_wait_ack_fourth_half =>
            if ( i_scl_cntr < HALF_BIT ) then
              i_scl_cntr <= i_scl_cntr + 1;
            else
              i_scl_cntr <= 0;
              i_sda_mstr <= 'Z';
              stm_mstr <= mstr_active;
            end if;     
          --------------------
          --####################
          --###### READ ########
          --####################
          when mstr_rd_wait_low =>
            i_scl_mstr <= '0';
            i_sda_mstr <= 'Z';
            if ( i_scl_cntr < FULL_BIT ) then
              i_scl_cntr <= i_scl_cntr + 1;
              stm_mstr <= mstr_rd_wait_low;
            else                           
              i_scl_cntr <= 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -