3521|1

6892

帖子

0

TA的资源

五彩晶圆(高级)

楼主
 

利用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
   );
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
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';
  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<='0';       
      elsif  (i2c_operate_state=x"01") then
         sck<='1';       
         i2c_operate_state<=x"02";   
      elsif  (i2c_operate_state=x"02") then
         sdata<='1';
         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"08";
             elsif (operate_cmd="01") then --write;
                i2c_operate_state<=x"31";
             end if;
             sdata<='1';
             i2c_operate_rd<='0';
             i2c_operate_byte_nums<=0;
      ------------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"0a";
     ------------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 
               i2c_operate_cnt<=0;
               i2c_operate_state<=x"0f";
             elsif (i2c_operate_cnt=7) then
               i2c_operate_cnt<=0;
               err<='1';
               ------err----
             else
               i2c_operate_cnt<=i2c_operate_cnt+1;
             end if;  
             i2c_operate_state<=x"22"; 
       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;
                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;
               i2c_operate_wr_data<=i2c_operate_data;
               i2c_operate_wr<='1';
              
             else
                i2c_operate_cnt<=i2c_operate_cnt+1;
                i2c_operate_state<=x"0f";
             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;
             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
                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';
             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";
      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;
此帖出自FPGA/CPLD论坛

最新回复

可以参考学习,很好!  详情 回复 发表于 2014-12-22 10:40
点赞 关注
 

回复
举报

18

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
可以参考学习,很好!
此帖出自FPGA/CPLD论坛
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表