利用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;
|