?? i2c_master.vhd
字號:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity I2C_Master is
Port ( clk : in std_logic;
rst : in std_logic;
sda : inout std_logic;
scl : inout std_logic;
temp_scl : out std_logic;
temp_sda : out std_logic;
busy : out bit;
cmd : in std_logic_vector(1 downto 0);
add : in std_logic_vector(7 downto 0);
data : out std_logic_vector(7 downto 0));
end I2C_Master;
architecture Behavioral of I2C_Master is
type state_type is ( -- state definitions
s_rst,s_init_rtc_rd,s_init_rtc_wr, -- reset state
s_idl,s_start,s_stop,s_write,s_read,s_writebyte,s_readbyte);--,s_write_rtc);
signal state: state_type; -- pointer to the state declaration
signal state_reg : integer range 0 to 6; -- State register is used to indicate State Status ie. Idl,Writebyte & Readbyte
signal opg_reg : integer range 0 to 6; -- operation reg is to assign diff call's in Writebyte & Readbyt
signal cmd_reg : integer range 0 to 10;
--signal write_rtc_reg : integer range 0 to 10;
signal s_clk : std_logic;
signal wr_ack : std_logic;
signal count: std_logic_vector(20 downto 0); -- count is used to reduce the system frequency
signal temp_data,temp_add,temp : std_logic_vector(7 downto 0); -- temp_data & temp_add is used to pass data & address to RTC
--signal temp_cmd : std_logic_vector(1 downto 0); -- temp_cmd is used to pass Command to RTC
signal delay_cnt: integer range 0 to 50;
signal i: integer range 0 to 10;
signal ack : bit;
begin
temp_scl <= scl;
temp_sda <= sda;
P1: process(rst,clk) --clk divider process
begin
if (rst = '1') then
count <= (others => '0');
s_clk<='0';
elsif (clk'event and clk = '1') then
--p_scl <= scl;
-- if(scl = '0')then
-- temp_scl <= '0';
-- else
-- temp_scl <= '1';
-- end if;
if (count = "000000000000110100000") then -- counter has been set to divide the frequency by 65K
count <= (others => '0');
s_clk <= '1';
else
count <= count + '1';
s_clk <='0';
end if;
end if;
end process;
P2: process(rst,s_clk)
begin
if(rst = '1')then
state <= s_rst;
scl <= 'Z';
sda <= 'Z';
cmd_reg <= 0;
delay_cnt <= 0;
i <= 0;
state_reg <= 0;
opg_reg <= 0;
--write_rtc_reg <= 0;
delay_cnt <= 0;
busy <= '0';
data <= (others => '0');
temp_data <= (others => '0');
temp_add <= (others => '0');
elsif s_clk'event and s_clk = '1' then
case state is
when s_rst =>
sda <= '0';
scl <= '0';
wr_ack <= '1';
cmd_reg <= 0;
delay_cnt <= 0;
i <= 0;
state_reg <= 0;
opg_reg <= 0;
--write_rtc_reg <= 0;
busy <= '0';
temp_data <= (others => '0');
temp_add <= (others => '0');
--data <= (others => '1');
state <= s_init_rtc_rd;
--state <= s_idl;
when s_init_rtc_rd =>
sda <= 'Z';
scl <= 'Z';
delay_cnt <= 0;
wr_ack <= '1';
i <= 0;
cmd_reg <= 0;
state_reg <= 5;
opg_reg <= 0;
--temp_data <= X"04";
--temp_data <= data;
--data <= "00000100";
temp <= temp_data and "00111000";
temp_add <= "00000000";
busy <= '1';
state <= s_readbyte;
when s_init_rtc_wr =>
sda <= 'Z';
scl <= 'Z';
delay_cnt <= 0;
wr_ack <= '1';
i <= 0;
cmd_reg <= 0;
state_reg <= 4;
opg_reg <= 0;
--temp_data <= X"04";
--temp_data <="00000100";
--data <= "00000100";
temp <= temp_data and "00111000";
temp_add <= "00000000";
busy <= '1';
state <= s_writebyte;
when s_idl=>
sda <= 'Z';
scl <= 'Z';
delay_cnt <= 0;
wr_ack <= '0';
i <= 0;
cmd_reg <= 0;
state_reg <= 1;
opg_reg <= 0;
--write_rtc_reg <= 0;
if(cmd = "01")then ------ Call to RTC_Writebyte
--temp_data <= data;
temp_data <= "00100010";
--temp <= data;
temp <= "00100101";
temp_add <= add;
busy <= '1';
state <= s_writebyte;
elsif(cmd = "10")then ------ Call to RTC_Readbyte
temp_data <= (others => '0');
--data <= X"00";
data <= "00000000";
temp_add <= add;
busy <= '1';
state <= s_readbyte;
elsif(cmd = "11")then
temp_data <= (others => '0');
temp_add <= (others => '0');
busy <= '1';
state <= s_rst;
else
temp_data <= (others => '0');
temp_add <= (others => '0');
busy <= '0';
state <= s_idl;
end if;
when s_start =>
busy <= '1';
i <= 0;
if(cmd_reg = 0)then
sda <= 'Z';
scl <= 'Z';
state <= s_start;
if(delay_cnt >= 40)then
delay_cnt <= 0;
cmd_reg <= cmd_reg + 1;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
elsif(cmd_reg = 1)then
sda <= '0';
scl <= 'Z';
state <= s_start;
if(delay_cnt >= 40)then
delay_cnt <= 0;
cmd_reg <= cmd_reg + 1;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
elsif(cmd_reg = 2)then
sda <= '0';
scl <= '0';
state <= s_start;
if(delay_cnt >= 40)then
delay_cnt <= 0;
cmd_reg <= cmd_reg + 1;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
else
sda <= '0';
scl <= '0';
cmd_reg <= 0;
if(state_reg = 2) then
state <= s_writebyte;
elsif(state_reg = 3) then
state <= s_readbyte;
else
state <= s_idl;
end if;
end if;
when s_stop =>
if(cmd_reg = 0)then
busy <= '1';
sda <= '0';
scl <= '0';
state <= s_stop;
if(delay_cnt >= 40) then
delay_cnt <= 0;
cmd_reg <= cmd_reg + 1;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
elsif(cmd_reg = 1) then
busy <= '1';
sda <= '0';
scl <= 'Z';
state <= s_stop;
if(delay_cnt >= 40) then
delay_cnt <= 0;
cmd_reg <= cmd_reg + 1;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
else --if(cmd_reg = 2)
busy <= '0';
sda <= 'Z';
scl <= 'Z';
if(cmd = "00")then
cmd_reg <= 0;
state <= s_idl;
else
state <= s_stop;
cmd_reg <= cmd_reg;
end if;
end if;
when s_write =>
busy <= '1';
case cmd_reg is
when 0 =>
i <= 0;
cmd_reg <= cmd_reg + 1;
state <= s_write;
when 1 =>
-- sda <= temp_data(7 - i);
if(temp_data(7 - i) = '1')THEN
sda <= 'Z';
else
sda <= '0';
end if;
if(delay_cnt >= 40) then
delay_cnt <= 0;
cmd_reg <= cmd_reg + 1;
state <= s_write;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
when 2 =>
sda <= sda;
scl <= 'Z';
if(delay_cnt >= 40) then
delay_cnt <= 0;
cmd_reg <= cmd_reg + 1;
state <= s_write;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
when others =>
scl <= '0';
if(delay_cnt >= 40) then
delay_cnt <= 0;
if(i < 7)then
sda <= sda;
cmd_reg <= 1;
i <= i + 1;
state <= s_write;
elsif(i = 7)then
sda <= wr_ack; ------------- pass ack or nack
cmd_reg <= 2;
i <= i + 1;
state <= s_write;
else
sda <= '0';
cmd_reg <= 0;
i <= 0;
if(state_reg = 2) then
state <= s_writebyte;
elsif(state_reg = 3) then
state <= s_readbyte;
else
state <= s_idl;
end if;
-- end if;
end if;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
end case;
when s_read =>
busy <= '1';
case cmd_reg is
when 0 =>
i <= 0;
temp_data <= (others => '0');
sda <= 'Z';
scl <= '0';
if(delay_cnt >= 40)then
delay_cnt <= 0;
cmd_reg <= cmd_reg + 1;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
state <= s_read;
when 1 =>
sda <= 'Z';
scl <= 'Z';
if(delay_cnt >= 40)then
delay_cnt <= 0;
cmd_reg <= cmd_reg + 1;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
state <= s_read;
when 2 =>
-- when 1 =>
scl <= 'Z';
-- sda <= 'Z';
if(sda = '1') then
-- temp_data(7 - i) <= sda;
temp_data(7 - i) <= '1';
else
temp_data(7 - i) <= '0';
end if;
cmd_reg <= cmd_reg + 1;
state <= s_read;
-- data <= temp_data;
when 3 =>
-- when 2 =>
scl <= '0';
temp_data <= temp_data;
if(i < 7)then
if(delay_cnt >= 40)then
delay_cnt <= 0;
cmd_reg <= 1;
i <= i + 1;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
i <= i;
end if;
state <= s_read;
else
i <= 0;
data <= temp_data;
state <= s_read;
if(ack = '1')then
cmd_reg <= 5;
else
cmd_reg <= 6;
end if;
end if;
when 5 =>
sda <= '0';
if(delay_cnt >= 40)then
delay_cnt <= 0;
cmd_reg <= 7;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
state <= s_read;
when 6 =>
sda <= 'Z';
if(delay_cnt >= 40) then
delay_cnt <= 0;
cmd_reg <= 7;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
state <= s_read;
when 7 =>
scl <= 'Z';
if(delay_cnt >= 40) then
delay_cnt <= 0;
cmd_reg <= cmd_reg + 1;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
end if;
state <= s_read;
when 8 =>
scl <= '0';
if(delay_cnt >= 40) then
delay_cnt <= 0;
cmd_reg <= 0;
if(state_reg = 2) then
state <= s_writebyte;
elsif(state_reg = 3) then
state <= s_readbyte;
else
state <= s_idl;
end if;
else
delay_cnt <= delay_cnt + 1;
cmd_reg <= cmd_reg;
state <= s_read;
end if;
when others =>
null;
end case;
when s_writebyte =>
busy <= '1';
delay_cnt <= 0;
i <= 0;
cmd_reg <= 0;
state_reg <= 2;
case opg_reg is
when 0 =>
opg_reg <= opg_reg + 1;
state <= s_start;
when 1 =>
--temp_data <= X"D0";
temp_data <= "11010000";
wr_ack <= 'Z';
opg_reg <= opg_reg + 1;
state <= s_write;
when 2 =>
temp_data <= temp_add;
wr_ack <= 'Z';
opg_reg <= opg_reg + 1;
state <= s_write;
when 3 =>
temp_data <= temp;
wr_ack <= 'Z';
opg_reg <= opg_reg + 1;
state <= s_write;
when others =>
state <= s_stop;
end case;
when s_readbyte =>
busy <= '1';
delay_cnt <= 0;
i <= 0;
cmd_reg <= 0;
state_reg <= 3;
case opg_reg is
when 0 =>
opg_reg <= opg_reg + 1;
state <= s_start;
when 1 =>
--temp_data <= X"D0";
temp_data <= "11010000";
wr_ack <= 'Z';
opg_reg <= opg_reg + 1;
state <= s_write;
when 2 =>
temp_data <= add;
opg_reg <= opg_reg + 1;
wr_ack <= 'Z';
state <= s_write;
when 3 =>
opg_reg <= opg_reg + 1;
wr_ack <= 'Z';
state <= s_start;
when 4 =>
--temp_data <= X"D1";
temp_data <= "11010001";
wr_ack <= 'Z';
opg_reg <= opg_reg + 1;
state <= s_write;
when 5 =>
ack <= '0';
temp_data <= (others => '0');
opg_reg <= opg_reg + 1;
state <= s_read;
when others =>
data <= temp_data;
if(state_reg = 5)then
state <= s_init_rtc_wr;
else
state <= s_stop;
end if;
end case;
end case;
end if;
end process;
end Behavioral;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -