📄 i2c_s.vhd
字号:
-------------------------------------------------------------------------------
---- The module contains N accessable Registers;
---- when in read Process, all Registers are read at a time;
---- when in write Process, only the addressed register are Writeable.
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.STD_LOGIC_1164.ALL;
USE ieee.STD_LOGIC_arith.ALL;
USE ieee.STD_LOGIC_unsigned.ALL;
-------------------------------------------------------------------------------
entity i2c_new is
port
(
reset_n : in std_logic;
scl : in std_logic;
clk : in std_logic; --external clock,25mhz
sda : inout std_logic;
reg : out std_logic_vector(5 downto 0);
ctr0_out : out std_logic;
ctr1_out : out std_logic;
ctr2_out : out std_logic
);
end entity;
architecture behavioral of i2c_new is
-------------------------------------------------------------------------------
---- parameter declaration
-------------------------------------------------------------------------------
constant slave_addr : std_logic_vector(6 downto 0) := "0111000";
-------------------------------------------------------------------------------
---- state machine declaration
-------------------------------------------------------------------------------
constant idle_state : std_logic_vector(2 downto 0) := "000";
constant addr_state : std_logic_vector(2 downto 0) := "001";
constant write_state : std_logic_vector(2 downto 0) := "011";
constant read_state : std_logic_vector(2 downto 0) := "010";
constant offset_state : std_logic_vector(2 downto 0) := "100";
-------------------------------------------------------------------------------
---- signal declaration
-------------------------------------------------------------------------------
signal state : std_logic_vector(2 downto 0);
signal s_start : std_logic;
signal s_stop : std_logic;
signal r_start : std_logic_vector(2 downto 0);
signal r_stop : std_logic_vector(2 downto 0);
signal r_cnt : std_logic_vector(3 downto 0);
signal r_scl : std_logic_vector(2 downto 0);
signal r_addr : std_logic_vector(6 downto 0);
signal r_offaddr : std_logic_vector(7 downto 0);
signal rd_cnt : std_logic_vector(2 downto 0);
signal wr : std_logic;
signal rd : std_logic;
signal add_match : std_logic;
signal offadd_match : std_logic;
signal ack : std_logic;
signal s_sda : std_logic;
signal r_data : std_logic_vector(7 downto 0);
signal r_data_in1 : std_logic_vector(7 downto 0);
signal r_data_in2 : std_logic_vector(7 downto 0);
signal r_data_in3 : std_logic_vector(7 downto 0);
signal r_data_out1 : std_logic_vector(7 downto 0);
signal r_data_out2 : std_logic_vector(7 downto 0);
signal r_data_out3 : std_logic_vector(7 downto 0);
signal r_data_out4 : std_logic_vector(7 downto 0);
signal r_data_out5 : std_logic_vector(7 downto 0);
signal r_data_out6 : std_logic_vector(7 downto 0);
signal r_data_out7 : std_logic_vector(7 downto 0);
signal r_data_out8 : std_logic_vector(7 downto 0);
-------------------------------------------------------------------------------
begin
ctr0_out <= r_data_in2(7) or r_data_in2(6);
ctr1_out <= r_data_in2(5) or r_data_in2(4);
ctr2_out <= r_data_in2(3) or r_data_in2(2);
sda <= 'Z' when s_sda = '1' else -- tri-state generation
'0';
reg(5 downto 0) <= r_data_in2(7 downto 2);
-------------------------------------------------------------------------------
---- generate start ,stop signal
-------------------------------------------------------------------------------
process(reset_n,clk) --
begin
if(reset_n = '0') then
s_start <= '0';
s_stop <= '0';
r_start <= "000";
r_stop <= "111";
elsif(rising_edge(clk)) then
if(scl = '1')then
if(r_start = "100")then -- sda fall edge
s_start <= '1';
r_start <= r_start;
else
r_start <= r_start(1 downto 0)& sda;
s_start <= '0';
end if;
if(r_stop = "011")then --sda rise edge
s_stop <= '1';
r_stop <= r_stop;
else
r_stop <= r_stop(1 downto 0)& sda;
s_stop <= '0';
end if;
else
r_start <= "000";
s_start <= '0';
r_stop <= "111";
s_stop <= '0';
end if;
end if;
end process;
-------------------------------------------------------------------------------
---- judge adress
-------------------------------------------------------------------------------
process(reset_n,clk) --
begin
if(reset_n = '0' or s_stop = '1') then
r_cnt <= "0000";
r_scl <= "000";
r_addr <= "0000000";
r_offaddr <= "00000000";
rd_cnt <= "001";
wr <= '0';
rd <= '0';
add_match <= '0';
ack <= '0';
s_sda <= '1';
state <= idle_state;
elsif(rising_edge(clk)) then
case state is
when idle_state =>
if(s_start = '1')then
state <= addr_state;
else
state <= idle_state;
end if;
--------------------get adress---------------------------
when addr_state => --get address,and judge
if(s_start = '1') then
r_cnt <= "0000";
r_scl <= "000";
r_addr <= "0000000";
state <= addr_state;
elsif(r_scl = "011")then --scl rising edge
if(r_cnt < "0111")then
r_addr <= r_addr(5 downto 0) & sda; --get address
r_cnt <= r_cnt+1;
elsif(r_cnt = "0111")then --get read or write bit
r_cnt <= r_cnt+1;
if(sda = '1')then
wr <= '0';
rd <= '1';
else
wr <= '1';
rd <= '0';
end if;
end if;
elsif(r_scl = "110")then --scl fall edge
if(r_cnt = "1000")then -- generate ack signal
if(r_addr = slave_addr)then
add_match <= '1';
ack <= '0';
s_sda <= '0';
else
add_match <= '0';
ack <= '1';
s_sda <= '1';
end if;
r_cnt <= r_cnt+1;
elsif(r_cnt = "1001")then --clear all
r_cnt <= "0000";
ack <= '1';
s_sda <= '1';
r_addr <= "0000000";
if(add_match = '1')then
if(wr = '1' and rd = '0')then
state <= offset_state;
add_match <= '0';
wr <= '0';
rd <= '0';
elsif(wr = '0' and rd = '1')then
state <= read_state;
add_match <= '0';
wr <= '0';
rd <= '0';
end if;
else
state <= idle_state;
end if;
end if;
end if;
-------------------------get register address--------------------------------
when offset_state => --get register address
if(r_scl = "011")then
if(r_cnt < "1000")then
r_offaddr <= r_offaddr(6 downto 0) & sda;
r_cnt <= r_cnt+1;
end if;
elsif(r_scl = "110")then
if(r_cnt = "1000")then --8th clock fall edge
if(r_offaddr = X"01" or r_offaddr = X"02" or r_offaddr = X"03")then
r_cnt <= r_cnt+1;
ack <= '0';
s_sda <= '0';
else
ack <= '1';
s_sda <= '1';
r_offaddr <= "00000000";
r_cnt <= "0000";
state <= idle_state;
end if;
elsif(r_cnt = "1001")then
r_cnt <= "0000";
ack <= '1';
s_sda <= '1';
state <= write_state;
end if;
end if;
------------------------write---------------------------------
when write_state => --write
if(r_scl = "011")then
if(r_cnt < "1000")then
r_data <= r_data(6 downto 0) & sda;
r_cnt <= r_cnt+1;
end if;
elsif(r_scl = "110")then
if(r_cnt = "1000")then --8th clock fall edge
case r_offaddr is
when X"01" =>
r_data_in1 <= r_data;
when X"02" =>
r_data_in2 <= r_data;
when X"03" =>
r_data_in3 <= r_data;
when others =>
null;
end case;
r_cnt <= r_cnt+1;
ack <= '0';
s_sda <= '0';
elsif(r_cnt = "1001")then
r_offaddr <= "00000000";
r_data <= "00000000";
r_cnt <= "0000";
ack <= '1';
s_sda <= '1';
state <= idle_state;
end if;
end if;
-----------------------read------------------------------------
when read_state =>
if(r_cnt = "0000")then --load data
case rd_cnt is
when "001" =>
r_data <= r_data_out1;
when "010" =>
r_data <= r_data_out2;
when "011" =>
r_data <= r_data_out3;
when "100" =>
r_data <= r_data_out4;
when "101" =>
r_data <= r_data_out5;
when "110" =>
r_data <= r_data_out6;
when "111" =>
r_data <= r_data_out7;
when "000" =>
r_data <= r_data_out8;
when others =>
r_data <= "00000000";
end case;
s_sda <= r_data(7);
rd_cnt <= rd_cnt+1;
elsif(r_scl = "110")then
if(r_cnt < "1000")then
r_data <= r_data(6 downto 0) & '0';
s_sda <= r_data(7);
r_cnt <= r_cnt+1;
elsif(r_cnt = "1000")then --8th clock fall edge
r_cnt <= "0000";
if(sda = '1')then
state <= idle_state;
else
state <= write_state;
end if;
end if;
end if;
when others =>
null;
end case;
r_scl <= r_scl(1 downto 0) & scl;
end if;
end process;
end behavioral;
-------------------------------------------------------------------------------
---- end all
-------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -