📄 at24c02a.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 + -