利用I2C总线读写AT24C512的FPGA原创代码

  根据上面一篇研究AT24C512的DATASHEET 心得,设计如下利用FPGA读写 AT24C512的原创代码。在本代码中,设计目的,根据指定的页地址,利用随机顺序读方式和页写方式操作AT24C512, 每次读写128字节,即一页数据。
  端口定义如下:
      clk: 时钟信号,设计为20MHZ;
      rst: 复位信号,设计为0复位,1不复位   
      clk200k: i2c总线读写时钟
      sck:  at24c512时钟控制线
     sdata: at24c512数据线
     page_addr: 读写的页地址
    operate_cmd: 读写命令;“00” 表示---读;“01”---表示写
    i2c_ram_rd: RAM读信号,该RAM存放从EEPROM读出的128字节数据
    i2c_ram_rd_addr: RAM读地址,该RAM存放从EEPROM读出的128字节数据
    i2c_ram_rd_data: RAM读数据,该RAM存放从EEPROM读出的128字节数据
    i2c_ram_wr:  RAM写信号,该RAM存放写入EEPROM的128字节数据
    i2c_ram_wr_addr:  RAM写地址,该RAM存放写入EEPROM的128字节数据
    i2c_ram_wr_data:  RAM写数据,该RAM存放写入EEPROM的128字节数据
    i2c_en: i2c模块读写使能信号,高有效
    update: 数据从EEProm读取完毕标志
   err: 从eeprom读取过程中出错故障指示
 
library ieee;
use ieee.std_logic_1164.all; 
use ieee.std_logic_arith.all;
use ieee.std_logic_signed.all;
entity i2c is
port
  (
   clk: in std_logic;
   rst: in std_logic;  
   
   clk200k: in std_logic;
   sck: out std_logic;
   sdata: inout std_logic;
   page_addr: in std_logic_vector(7 downto 0);
   operate_cmd: in std_logic_vector(1 downto 0);
   i2c_ram_rd: in std_logic;
   i2c_ram_rd_addr: in std_logic_vector(6 downto 0);
   i2c_ram_rd_data: out std_logic_vector(7 downto 0);
   i2c_ram_wr: in std_logic;
   i2c_ram_wr_addr: in std_logic_vector(6 downto 0);
   i2c_ram_wr_data: in std_logic_vector(7 downto 0);
   i2c_en: in std_logic;
   update: out std_logic ;
   err: out std_logic;
   rdy: out std_logic
   );
end i2c;
architecture arch_i2c of i2c is
component  altsyncram
 generic (
  operation_mode      : string;
  width_a        : natural;
  widthad_a       : natural;
  width_b        : natural;
  widthad_b       : natural;
  width_byteena_a      : natural;
  outdata_reg_b      : string;
  address_reg_b      : string;
  rdcontrol_reg_b      : string;
  read_during_write_mode_mixed_ports  : string;
  init_file       : string
 );
 port
  (
   wren_a   : in   std_logic ;
   clock0   : in   std_logic ;
   clock1   : in   std_logic ;
   address_a  : in   std_logic_vector (widthad_a-1 downto 0);
   address_b  : in   std_logic_vector (widthad_b-1 downto 0);
   rden_b   : in   std_logic ;
   q_b    : out std_logic_vector (width_b-1 downto 0);
   data_a   : in   std_logic_vector (width_a-1 downto 0)
   );
 end component;
constant i2c_device_rd:std_logic_vector(7 downto 0):=x"a1";
constant i2c_device_wr:std_logic_vector(7 downto 0):=x"a0";
signal i2c_operate_state: std_logic_vector(7 downto 0);
signal i2c_operate_cnt : integer range 0 to 7;
signal i2c_operate_byte_nums:integer range 0 to 127;
signal i2c_operate_data: std_logic_vector(7 downto 0);
signal i2c_operate_wr: std_logic;
signal i2c_operate_wr_addr: std_logic_vector(6 downto 0);
signal i2c_operate_wr_data: std_logic_vector(7 downto 0);
signal i2c_operate_rd: std_logic;
signal i2c_operate_rd_addr: std_logic_vector(6 downto 0);
signal i2c_operate_rd_data: std_logic_vector(7 downto 0);
begin
-----------filter cell data---------------------------------------
i2c_ram_rd_ins : altsyncram
 generic map
 (
  operation_mode       => "dual_port",
  width_a               => 8,
  widthad_a        => 7,
  width_b               => 8,
  widthad_b        => 7,
  width_byteena_a             => 1,
  outdata_reg_b       => "unregistered",
  address_reg_b       => "clock1",
  rdcontrol_reg_b             => "clock1",
  read_during_write_mode_mixed_pORts  => "old_data",
  init_file              =>"rx_data_ram.mif"
 )
 port map (
  wren_a         => i2c_operate_wr,      
  clock0         => clk,
  clock1         => clk,          
  address_a        => i2c_operate_wr_addr,  
  address_b        => i2c_ram_rd_addr,     
  rden_b         => i2c_ram_rd,           
  data_a         => i2c_operate_wr_data,    
  q_b                => i2c_ram_rd_data            
 );
 
i2c_ram_wr_ins : altsyncram
 generic map
 (
  operation_mode       => "dual_port",
  width_a               => 8,
  widthad_a        => 7,
  width_b               => 8,
  widthad_b        => 7,
  width_byteena_a             => 1,
  outdata_reg_b       => "unregistered",
  address_reg_b       => "clock1",
  rdcontrol_reg_b             => "clock1",
  read_during_write_mode_mixed_pORts  => "old_data",
  init_file              =>"rx_data_ram.mif"
 )
 port map (
  wren_a         => i2c_ram_wr,      
  clock0         => clk,
  clock1         => clk,          
  address_a        => i2c_ram_wr_addr,  
  address_b        => i2c_operate_rd_addr,     
  rden_b         => i2c_operate_rd,           
  data_a         => i2c_ram_wr_data,    
  q_b         => i2c_operate_rd_data            
 );
 
 i2c_operate: process(clk,rst)
  begin
  if (rst='0') then
      sck<='0';
      sdata<='Z';
      i2c_operate_wr_data<=(others=>'0');
      i2c_operate_wr_addr<=(others=>'0');
      i2c_operate_wr<='0';
      i2c_operate_rd_addr<=(others=>'0');
      i2c_operate_rd<='0';
      i2c_operate_state<=(others=>'0');
      update<='0';
      err<='0';
      rdy<='0';
  elsif clk'event and clk='1' then
    if (clk200k='1') then
  --------------start bit --------------------
      if (i2c_operate_state=x"00") then 
      --  if (i2c_en='1') then       
         if((operate_cmd="00") or  (operate_cmd="10") ) then
           i2c_operate_state<=x"01";
         end if;   
     --  end if;
         sck<='0';  
         sdata<='1';        
      elsif  (i2c_operate_state=x"01") then
         sck<='1';        
         i2c_operate_state<=x"02";    
      elsif  (i2c_operate_state=x"02") then
         sdata<='0';
         i2c_operate_byte_nums<=0;
         i2c_operate_state<=x"03"; 
 -------------Device addre. Firt Page addr Second addr--------------------
      elsif  (i2c_operate_state=x"03") then             
          sck<='0';
         if(i2c_operate_byte_nums=0) then
          i2c_operate_data<=i2c_device_wr;
         elsif (i2c_operate_byte_nums=1) then
          i2c_operate_data<=page_addr;
         elsif (i2c_operate_byte_nums=2) then
          i2c_operate_data<=x"00";
         end if;
         i2c_operate_cnt<=0;
         i2c_operate_state<=x"04";        
     elsif  (i2c_operate_state=x"04") then        
       ----bit data ready---
          sck<='0';    
          sdata<=i2c_operate_data(7);
          i2c_operate_data<=i2c_operate_data(6 downto 0) & '0';
          i2c_operate_state<=x"05";   
     elsif  (i2c_operate_state=x"05") then 
          sck<='1';
          if (i2c_operate_cnt=7) then
               i2c_operate_cnt<=0;            
               i2c_operate_state<=x"06"; 
          else
               i2c_operate_cnt<=i2c_operate_cnt+1;
               i2c_operate_state<=x"04";   -----clocked data
          end if;
     elsif  (i2c_operate_state=x"06") then
         -----check eeprom ack bit---       
          sck<='0';
          sdata<='Z';
          i2c_operate_state<=x"20"; 
     elsif  (i2c_operate_state=x"20") then
          sck<='1';                 
          if (sdata='0') then                
                if(i2c_operate_byte_nums=2) then
                  i2c_operate_byte_nums<=0;
                  i2c_operate_state<=x"07"; 
                  i2c_operate_rd_addr<=(others=>'0');
                  i2c_operate_rd<='1';              
               else
                  i2c_operate_byte_nums<=i2c_operate_byte_nums+1;
                  i2c_operate_state<=x"03"; 
               end if;
              i2c_operate_cnt<=0;
          elsif (i2c_operate_cnt=7) then
              i2c_operate_cnt<=0;
            --  err<='1';
              ------err------------------
          else
              i2c_operate_cnt<=i2c_operate_cnt+1;           
          end if;
       elsif  (i2c_operate_state=x"07") then
             sck<='0';
             if (operate_cmd="00") then ---read;
                i2c_operate_state<=x"23";
             elsif (operate_cmd="01") then --write;
                i2c_operate_state<=x"31";
             end if;
              
             i2c_operate_rd<='0';
             i2c_operate_byte_nums<=0;
       elsif  (i2c_operate_state=x"23") then
             sck<='0';
             sdata<='1';
             i2c_operate_state<=x"08";
      ------------read start bit----------------------
       elsif  (i2c_operate_state=x"08") then
             sck<='1';     
             i2c_operate_state<=x"09";
       elsif  (i2c_operate_state=x"09") then
             sdata<='0';
             i2c_operate_state<=x"0b";
     ------------tx device addre and control cmd------
       elsif  (i2c_operate_state=x"0b") then
             sck<='0';
             i2c_operate_data<=i2c_device_rd;
             i2c_operate_state<=x"0c";
             i2c_operate_cnt<=0;
       elsif  (i2c_operate_state=x"0c") then
             sck<='0';
             sdata<=i2c_operate_data(7);
             i2c_operate_data<=i2c_operate_data(6 downto 0) &  '0' ;
             i2c_operate_state<=x"0d";
       elsif  (i2c_operate_state=x"0d") then
             sck<='1';
             if (i2c_operate_cnt=7) then
                 i2c_operate_cnt<=0;
                 i2c_operate_state<=x"0e";
             else
                 i2c_operate_cnt<=i2c_operate_cnt+1;
                 i2c_operate_state<=x"0c";         
             end if;  
       elsif  (i2c_operate_state=x"0e") then
              sck<='0';
              sdata<='Z';
              i2c_operate_state<=x"21";   
       elsif  (i2c_operate_state=x"21") then
              sck<='1';
                      
             if (sdata='0') then 
               -- err<='1'; 
               i2c_operate_cnt<=0;
               i2c_operate_state<=x"22"; 
             elsif (i2c_operate_cnt=7) then
               i2c_operate_cnt<=0;
              -- err<='1';
               ------err----
             else
               i2c_operate_cnt<=i2c_operate_cnt+1;
             end if;           
       elsif (i2c_operate_state=x"22") then
             sck<='0';    
             i2c_operate_state<=x"0f";       
       elsif  (i2c_operate_state=x"0f") then  
             sck<='1';
             i2c_operate_data<=i2c_operate_data(6 downto 0) &  sdata ;
             i2c_operate_wr<='0';
             i2c_operate_state<=x"10";
             update<='0';
       elsif  (i2c_operate_state=x"10") then  
             sck<='0';
             if(i2c_operate_cnt=7) then
               i2c_operate_cnt<=0;          
               i2c_operate_wr_data<=i2c_operate_data;
               i2c_operate_wr<='1';
               i2c_operate_state<=x"24";
             else
                i2c_operate_cnt<=i2c_operate_cnt+1;
                i2c_operate_state<=x"0f";
             end if; 
       elsif (i2c_operate_state=x"24") then  
              if(i2c_operate_byte_nums=127) then
                  i2c_operate_state<=x"13";  
                  i2c_operate_byte_nums<=0;       
                  i2c_operate_wr_addr<=(others=>'0');  
                  update<='1';  
                  sdata<='1';         
               else
                  i2c_operate_byte_nums<=i2c_operate_byte_nums+1;
                  i2c_operate_wr_addr<=i2c_operate_wr_addr+"0000001";
                  i2c_operate_state<=x"11";
                  sdata<='0'; 
               end if;
    
    --------------------tx ACK bit=zero-------------------
       elsif  (i2c_operate_state=x"11") then  
             i2c_operate_wr<='0';
             sck<='1';       
             i2c_operate_state<=x"12";
       elsif  (i2c_operate_state=x"12") then  
             sck<='0';
             sdata<='Z';
             i2c_operate_state<=x"0f";    ----------receive next data
   ---------------------tx NO ACK bit=one------------------
       elsif  (i2c_operate_state=x"13") then 
             update<='0';
             i2c_operate_wr<='0';
             sck<='1';
             i2c_operate_state<=x"14";  
       elsif  (i2c_operate_state=x"14") then 
             sck<='0';
             sdata<='Z';
             i2c_operate_state<=x"15"; 
  ---------------------write operate------------------------ 
       elsif (i2c_operate_state=x"31") then 
             sck<='0';
             i2c_operate_data<=i2c_operate_rd_data;
           --  if (i2c_operate_rd_data="00001111") then
           --       err<='1';
           --  end if;
             i2c_operate_cnt<=0;
             i2c_operate_state<=x"32"; 
       elsif (i2c_operate_state=x"32") then 
             sck<='0';
             sdata<=i2c_operate_data(7);
             i2c_operate_data<=i2c_operate_data(6 downto 0) & '0';
             i2c_operate_state<=x"33"; 
             i2c_operate_rd<='0';
       elsif  (i2c_operate_state=x"33") then 
             sck<='1';
             if (i2c_operate_cnt=7) then 
                 i2c_operate_cnt<=0;
                 i2c_operate_state<=x"34"; 
                if (i2c_operate_rd_addr="1111111") then
                     i2c_operate_rd_addr<=(others=>'0');
                else
                     i2c_operate_rd_addr<=i2c_operate_rd_addr+"0000001"; 
                end if;
                i2c_operate_rd<='1';
                
             else
                 i2c_operate_cnt<=i2c_operate_cnt+1;
                 i2c_operate_state<=x"32"; 
             end if; 
       elsif  (i2c_operate_state=x"34") then 
             i2c_operate_rd<='0';
             sck<='0';
             sdata<='Z';
             i2c_operate_state<=x"35"; 
       elsif  (i2c_operate_state=x"35") then 
             sck<='1';        
             if (sdata='0') then
                i2c_operate_cnt<=0;            
                if ( i2c_operate_byte_nums=127) then
                     i2c_operate_byte_nums<=0;
                     i2c_operate_state<=x"15";   -----stop bit
                --     err<='1';
                else
                     i2c_operate_byte_nums<=i2c_operate_byte_nums+1;
                     i2c_operate_state<=x"31";
                end if;
                                  
             elsif (i2c_operate_cnt=7) then
                i2c_operate_cnt<=0;
               -- err<='1';
                ----err---
             else
                i2c_operate_cnt<=i2c_operate_cnt+1;
             end if;           
   --------------------stop bit -------------------------------------
       elsif  (i2c_operate_state=x"15") then 
             sdata<='0';
             sck<='0';
             rdy<='1';
             i2c_operate_state<=x"16";  
       elsif  (i2c_operate_state=x"16") then 
             sck<='1';
             i2c_operate_state<=x"17";  
      elsif  (i2c_operate_state=x"17") then 
             sdata<='1';
             i2c_operate_state<=x"18"; 
      elsif  (i2c_operate_state=x"18") then 
             sck<='0';
             i2c_operate_state<=x"00"; 
             rdy<='0';
            -- err<='1';
      else
             i2c_operate_data<=(others=>'0');
             i2c_operate_cnt<=0;
             i2c_operate_byte_nums<=0;
             i2c_operate_state<=x"00";
             sck<='1';
             sdata<='Z';      
       end if;
     end if;
   end if;
   end process i2c_operate;
   end arch_i2c;
原文地址:https://www.cnblogs.com/zcf287/p/2801193.html