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

📄 i2c_master.vhd

📁 I2C program (Inter IC bus)
💻 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 + -