📄 i2c.vhd
字号:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity i2c is
port(
clk: in std_logic;
nreset: in std_logic;
d:inout std_logic_vector(7 downto 0);
start,
stop,
read,
write: in std_logic;
-- load,
-- shift: out std_logic;
-- sdai:in std_logic;
SCL,
SDA: inout std_logic
);
end i2c;
architecture arc_i2c_core of i2c is
--signal for i2c_core
signal sclo,sdao:std_logic;
signal din:std_logic;
--signal dcnt:unsigned(2 downto 0);
signal iload,ishift:std_logic;
type cmds is (idle, start_a, start_b, start_c, start_d, stop_a, stop_b, stop_c, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d,ack_a,ack_b,ack_c,ack_d,nack_a,nack_b,nack_c,nack_d);
--state: 00000 00001 00010 00011 00100 00101 00110 00111 01000 01001 01010 01011 01100 01101 01110 01111 10000 10001 10010 10011 10100 10101 10110 10111
signal state:cmds;
--signal for p2s
signal shifter: std_logic_vector(7 downto 0);
signal sr: std_logic;
type state_type is( s0,s1,s2,s3,s4,s5,s6,s7,s8,s9);
signal state_p2s:state_type;
-- signal for s2p
signal shift:std_logic_vector(7 downto 0);
type state_type1 is(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9);
signal state_s2p:state_type1;
--signal for lacth_input data
signal sh: std_logic_vector(7 downto 0);
signal flag: std_logic;
begin
-- generate statemachine
--u1: p2s1 port map(clk=>clk,nreset=>nreset,data=>data_in,sr=>din);
--u2: latch1 port map(clk=>clk,nreset=>nreset,flag=>iflag,d=>din_in,q=>din);
-- generate statemachine
p1 : process (nreset,clk,state,start,read,write)
--variable nxt_state : cmds;
--variable icmd_ack, ibusy, store_sda : std_logic;
--variable itxd : std_logic;
--variable iload,ishift:std_logic;
variable iscl,isda:std_logic;
variable idcnt:unsigned(2 downto 0);
begin
-- generate regs
if (nReset = '0' ) then
state <= idle;
--cmd_ack <= '0';
--busy <= '0';
--txd <= '0';
--Dout <= '0';
scl<='1';
sda<='1';
--dcnt<="111";
--shift<='0';
--load<='0';
elsif (clk'event and clk = '1') then
--if (clk_en = '1') then
--state <= idle;
--busy <= ibusy;
--txd <= itxd;
--if (store_sda = '1') then
-- Dout <= SDA;--SDA;
--end if;
SCL<=sclo;
SDA<=sdao;
--load<=iload;
-- shift<=ishift;
--dcnt<=idcnt;
case state is
when idle=>
iscl:='0';
isda:='0';
if(start='1') then
state<=start_a;
elsif stop='1' then
state<=stop_a;
elsif read='1' then
idcnt:="111";
ishift<='1';
state<=rd_a;
else
idcnt:="111";
iload<='1';
state<=wr_a;
end if;
-- start
when start_a =>
iscl := '0'; -- keep SCL in same state (for repeated start)
isda := '1'; -- set SDA high
state <= start_b;
when start_b =>
iscl:='1';
isda:='1';
state <= start_c;
when start_c =>
iscl:='1';
isda:='0';
state <= start_d;
when start_d =>
iscl:='0';
isda:='0';
-- icmd_ack := '1';
--if core_ack='1' then
if read='1' then
idcnt:="111";
ishift<='1';
state<=rd_a;
else
idcnt:="111";
iload<='1';
state<=wr_a;
end if;
-- elsif core_ack='0' then
-- nxt_state:=start_
--ibusy := '0'; -- not busy when idle
-- stop
when stop_a =>
iscl:='0';
isda:='0';
state <= stop_b;
when stop_b =>
iscl:='1';
isda:='0';
state <= stop_c;
when stop_c =>
iscl:='1';
isda:='1';
-- nxt_state := stop_d;
-- when stop_d =>
state <= idle;
--ibusy := '0'; -- not busy when idle
-- read
when rd_a =>
iscl:='0';
isda:='1';--sda;
-- icmd_ack := '1';
state <= rd_b;
when rd_b =>
iscl:='1';
isda:='0';--sda;
state <= rd_c;
when rd_c =>
iscl:='1';
isda:='1';--sda;
state <=rd_d;
when rd_d =>
iscl:='0';
isda:='0';--sda;
-- icmd_ack := '1';
idcnt:=idcnt-1;
if stop='1' then
state<=nack_a;
elsif idcnt=0 then
state <= ack_a;
else
state<=rd_a;
end if;
-- write
when wr_a =>
iscl:='0';
isda:=din;
-- iflag<='0';
state <= wr_b;
when wr_b =>
iscl:='1';
-- isda:=din;
state <= wr_c;
when wr_c =>
iscl:='1';
-- isda:=din;
state <= wr_d;
when wr_d =>
iscl:='0';
-- isda:=din;
-- iflag<='1';
-- icmd_ack := '1';
idcnt:=idcnt-1;
if(idcnt=0) then
state <= ack_a;
-- iflag<='0';
else
state<=wr_a;
end if;
when ack_a=>
iscl:='0';
isda:='0';
state <= ack_b;
when ack_b=>
isda:='0';
iscl:='1';
state <= ack_c;
when ack_c=>
iscl:='0';
state <= ack_d;
when ack_d=>
isda:='0';
if stop='1' then
state<=stop_a;
elsif(write='1') then
state<=wr_a;
idcnt:="111";
iload<='1';
elsif(read='1') then
state<=rd_a;
idcnt:="111";
ishift<='1';
else
state<=idle;
end if;
when nack_a=>
iscl:='0';
isda:='1';
state <= nack_b;
when nack_b=>
isda:='1';
iscl:='1';
state <= nack_c;
when nack_c=>
isda:='1';
iscl:='0';
state <= nack_d;
when nack_d=>
isda:='1';
state<=stop_a;
end case;
sclo<=iscl;
sdao<=isda;
end if;
end process p1;
p2:process( nreset,en,d) --latch for input data
begin
if(nreset='0') then
sh<="00000000";
elsif en='1' then
--if flag='1' then
sh<=d;
-- end if;
end if;
end process p2;
p2s: process(clk)
begin
if(clk'event and clk='1') then
if(iload='1') then
shifter<=d;
--state_p2s<=s0;
case state_p2s is
when s0=>
sr<='0';
if(nreset='0') then
state_p2s<=s0;
else
state_p2s<=s1;
end if;
when s1=>
sr<=shifter(7);
if(nreset='0') then
state_p2s<=s0;
else
state_p2s<=s2;
end if;
when s2=>
sr<=shifter(6);
if(nreset='0') then
state_p2s<=s0;
else
state_p2s<=s3;
end if;
when s3=>
sr<=shifter(5);
if(nreset='0') then
state_p2s<=s0;
else
state_p2s<=s4;
end if;
when s4=>
sr<=shifter(4);
if(nreset='0') then
state_p2s<=s0;
else
state_p2s<=s5;
end if;
when s5=>
sr<=shifter(3);
if(nreset='0') then
state_p2s<=s0;
else
state_p2s<=s6;
end if;
when s6=>
sr<=shifter(2);
if(nreset='0') then
state_p2s<=s0;
else
state_p2s<=s7;
end if;
when s7=>
sr<=shifter(1);
if(nreset='0') then
state_p2s<=s0;
else
state_p2s<=s8;
end if;
when s8=>
sr<=shifter(0);
if(nreset='0') then
state_p2s<=s0;
else
state_p2s<=s1;
end if;
when s9=>
if(nreset='0') then
state_p2s<=s0;
else
state_p2s<=s1;
end if;
end case;
end if;
end if;
din<=sr;
end process p2s;
s2p:process(clk)
begin
if(clk'event and clk='1') then
if(ishift='1') then
case state_s2p is
when t0=>
if(nreset='0') then
state_s2p<=t0;
elsif nreset='1' then
state_s2p<=t1;
end if;
when t1=>
shift<=sda&shift(7 downto 1);
if(nreset='0') then
state_s2p<=t0;
elsif nreset='1' then
state_s2p<=t2;
end if;
when t2=>
shift<=sda&shift(7 downto 1);
if(nreset='0') then
state_s2p<=t0;
elsif nreset='1' then
state_s2p<=t3;
end if;
when t3=>
shift<=sda&shift(7 downto 1);
if(nreset='0') then
state_s2p<=t0;
elsif nreset='1' then
state_s2p<=t4;
end if;
when t4=>
shift<=sda&shift(7 downto 1);
if(nreset='0') then
state_s2p<=t0;
elsif nreset='1' then
state_s2p<=t5;
end if;
when t5=>
shift<=sda&shift(7 downto 1);
if(nreset='0') then
state_s2p<=t0;
elsif nreset='1' then
state_s2p<=t6;
end if;
when t6=>
shift<=sda&shift(7 downto 1);
if(nreset='0') then
state_s2p<=t0;
elsif nreset='1' then
state_s2p<=t7;
end if;
when t7=>
shift<=sda&shift(7 downto 1);
if(nreset='0') then
state_s2p<=t0;
elsif nreset='1' then
state_s2p<=t8;
end if;
when t8=>
shift<=sda&shift(7 downto 1);
if(nreset='0') then
state_s2p<=t0;
elsif nreset='1' then
state_s2p<=t9;
end if;
when t9=>
d<=shift;
if(nreset='0') then
state_s2p<=t0;
elsif nreset='1' then
state_s2p<=t1;
end if;
end case;
end if;
end if;
end process s2p;
end architecture arc_i2c_core;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -