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

📄 at24c02a.vhd

📁 AT24C02的应用例程
💻 VHD
字号:
-- AT24C02A.VHD
-- This model is not guaranteed to accurately model all behaviors of
-- the EEPROM and is not 'certified' by Atmel or Actel.
-- This model only simulates the behavior of an AT24C02A serial EEPROM partially
-- and is created to be used with Actel I2C design.
-- NOTE: WP behavior is not currently modeled; and this model assumes
-- correct protocol, it does not look for start/stop bits that pre-empt
-- or abort valid transfers - etc
--
------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity at24c02a is
port(reset_n : in    std_logic; -- active low reset (for simulation)
     sclk    : in    std_logic; -- serial data clock
     sdata   : inout std_logic; -- serial data
     A       : in    std_logic_vector(2 downto 0);
     wp      : in    std_logic
);   
end at24c02A;

architecture behav of at24c02a is

signal sdo    : std_logic;
signal val    : std_logic_vector(7 downto 0);
signal state  : std_logic_vector(3 downto 0);

begin

sdata <= '0' when (sdo = '0') else 'Z';  -- tristate driver

slv:process

TYPE jvarray is array(255 downto 0) of integer;
VARIABLE never, done  : BOOLEAN;
VARIABLE adr          : INTEGER;
VARIABLE mem          : jvarray;

begin
  sdo <= 'Z';        -- tri-sate
  val   <= "00000000"; -- shift register
  adr   := 0;          -- array address

  for x in 0 to 255 loop   -- initialize the array
   mem(x) := x;
  end loop;

  while (TRUE) loop

   state <= "0000";     -- idle

   wait until (sdata'event AND sdata = '0' AND sclk = '1');    -- start bit
 
   state <= "0001"; -- get device address

   for x in 0 to 7 loop                           -- get next 8 bits
    wait until (sclk'event and sclk = '1');      -- "Device Address"
    val <= val(6 downto 0) & sdata after 1 ns;
   end loop;

   wait until (sclk'event and sclk = '0');

   if (val(7 downto 1) = "1010" & A(2) & A(1) & A(0)) then 
       sdo <= '0' after 1 ns;  -- assert ACK
   end if;

   wait until (sclk'event and sclk = '0');
   sdo <= 'Z' after 1 ns;

   if (val = "1010" & A(2) & A(1) & A(0) & '0') then -- write

      state <= "0011"; -- write/get array address

      for x in 0 to 7 loop                           -- get next 8 bits
       wait until (sclk'event and sclk = '1');      -- "Array Address"
       val <= val(6 downto 0) & sdata after 1 ns;
      end loop;

      adr := conv_integer(val);               -- update array address
      wait until (sclk'event and sclk = '0');  
      sdo <= '0' after 1 ns;                -- assert ACK
      wait until (sclk'event and sclk = '0'); 
      sdo <= 'Z' after 1 ns;

      -- Now we see what happens; if data is low when sclk = '1', we may
      -- get a stop bit (data goes high before falling edge of sclk), or
      -- the first bit of a data byte (no change); if data is high at 
      -- this point, we may get a start bit (data goes low before falling
      -- edge on sclk), or it's the first bit of a data byte (no change).

      done := FALSE;

      while not(done) loop
      
        wait until (sclk'event and sclk = '1');

        if (sdata = '0') then
          wait until (sclk'event OR sdata'event); 
          if (sdata = '0') then  -- data byte

             state <= "0100"; -- get data btye

             val <= val(6 downto 0) & '0' after 1 ns;
             for x in 1 to 7 loop                           -- get next 7 bits
               wait until (sclk'event and sclk = '1');      -- "Data Byte"
               val <= val(6 downto 0) & sdata after 1 ns;
             end loop;
             mem(adr) := conv_integer(val);       -- write into memory
             if (adr = 255) then
                 adr := 0;
             else
                 adr := adr + 1;
             end if;
             wait until (sclk'event and sclk = '0');  
             sdo <= '0' after 1 ns;                       -- assert ACK
             wait until (sclk'event and sclk = '0'); 
             sdo <= 'Z' after 1 ns;
          else                                              -- stop bit (done)
             state <= "0101"; -- stop bit
             done := TRUE;
          end if;
        elsif (sdata = '1' or sdata = 'H') then
          wait until (sclk'event OR sdata'event);
          if (sdata = '1' or sdata = 'H') then  -- data byte
  
             state <= "0100"; -- get data byte

             val <= val(6 downto 0) & '1' after 1 ns;
             for x in 1 to 7 loop                            -- get next 7 bits
               wait until (sclk'event and sclk = '1');      -- "Data Byte"
               val <= val(6 downto 0) & sdata after 1 ns;
             end loop;
             mem(adr) := conv_integer(val);       -- write into memory
             if (adr = 255) then
                 adr := 0;
             else
                 adr := adr + 1;
             end if;
             wait until (sclk'event and sclk = '0');  
             sdo <= '0' after 1 ns;                       -- assert ACK
             wait until (sclk'event and sclk = '0'); 
             sdo <= 'Z' after 1 ns;
          else                                              -- start bit (seq read)

             state <= "0110"; -- start bit so get device address

             for x in 0 to 7 loop                           -- get next 7 bits
               wait until (sclk'event and sclk = '1');      -- Device Address
               val <= val(6 downto 0) & sdata after 1 ns;
             end loop;
             wait until (sclk'event and sclk = '0');  
             sdo <= '0' after 1 ns;                       -- assert ACK
             wait until (sclk'event and sclk = '0'); 
             sdo <= 'Z' after 1 ns;

             while not(done) loop

               state <= "0111"; -- read bytes

               val <= conv_std_logic_vector(mem(adr),8);
               for x in 0 to 7 loop                          -- send 8 bits
                 sdo <= val(7-x) after 1 ns;
                 wait until (sclk'event and sclk = '0');
               end loop;
               sdo <= 'Z';
               wait until (sclk'event and sclk = '1');    
               if (sdata = '0') then                        -- check ACK
                   if (adr = 255) then
                       adr := 0;
                   else
                       adr := adr + 1;
                   end if;
                   wait until (sclk'event and sclk = '0');
               else
                   state <= "1000"; -- read complete
                   done  := TRUE;
               end if;
            end loop;
          end if;
      end if;
    end loop;
   elsif(val = "1010" & A(2) & A(1) & A(0) & '1') then   -- read byte

      state <= "0010"; -- read byte

      val <= conv_std_logic_vector(mem(adr),8);
      for x in 0 to 7 loop                                -- send 8 bits
       sdo <= val(7-x) after 1 ns;
       wait until (sclk'event and sclk = '0');
      end loop;
      sdo <= 'Z';
   end if;

  end loop;
end process;  -- slv

end behav;

⌨️ 快捷键说明

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