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

📄 i2c_s.vhd

📁 I2C Slave module The module contains N accessable Registers when in read Process, all Registers a
💻 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 + -