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

📄 i2c_7189.vhd

📁 这是一个用VHDL语言描述的I2C自动配置模块
💻 VHD
字号:
-- version 1.1
-- bug fixed: the last data cannot be send

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

use work.i2c.all;

entity i2c_7189 is
	port (
		clk : in std_logic;
		nReset : in std_logic;
		SCL : out std_logic;
		SDA : out std_logic;
		done : out std_logic);
end entity;

architecture rtl of i2c_7189 is
	constant SLAVE_ADDR : std_logic_vector(6 downto 0) := "0100000";
	constant CLK_CNT : unsigned(7 downto 0) := conv_unsigned(100, 8);  --Fc(MHz)*2-1
	constant delay_time : integer range 0 to 1000000000 :=10000;

	type c_state is (IDLE,INIT,START,SEND_ADR,SEND_DATA,ENDS);
	signal state : c_state;
	signal s_delay_cnt : integer range 0 to 1000000000;
	signal s_delay : std_logic;
	
	signal cmd_ack : std_logic;
	signal s_lack : std_logic;
	signal s_start, s_read, s_write, s_ack, s_stop : std_logic;
	signal s_data_r : std_logic_vector(7 downto 0);
	signal s_data_w : std_logic_vector(7 downto 0);
	
	signal s_addr : std_logic_vector(5 downto 0);
	signal s_q : std_logic_vector(7 downto 0);
	signal s_rom_q : std_logic_vector(7 downto 0);
	
--	signal nReset : std_logic;
	signal s_get : std_logic;
	signal s_SDA : std_logic;
	signal s_SCL : std_logic;
	signal s_ctrl_scl : std_logic;
	 	
	component rom7189 IS
		PORT
		(
			address		: IN STD_LOGIC_VECTOR (5 DOWNTO 0);
			clock		: IN STD_LOGIC ;
			q		: OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
		);
	END component;
	
begin
	u1: simple_i2c 
				port map (clk => clk, ena => '1', clk_cnt => clk_cnt, nReset => nReset,
									read => s_read, write => s_write, start => s_start, stop => s_stop, ack_in => s_ack, 
									cmd_ack => cmd_ack, Din => s_data_w, Dout => s_data_r, ack_out => s_lack,SCL => s_SCL, SDA => s_SDA);	
	u2: rom7189 
				port map (clock => clk, address => s_addr, q => s_q);
	
--	nReset <= Reset;
	SDA <= s_SDA when s_ctrl_scl = '0' else '1';
	SCL <= s_SCL when s_ctrl_scl = '0' else '1';
	
	process (clk,nReset,state)
	begin
		if nReset = '0' then
			s_ctrl_scl <= '0';
			state <= IDLE;
			s_start <= '0';
			s_read <= '0';
			s_write <='0';
			s_ack <= '0';
			s_stop <= '0';
			s_get <= '1';
			s_addr <= (others => '0');
			done <= '0';
		else
			
			if clk'event and clk = '1' then
				if s_get = '1' then
					s_rom_q <= s_q;
					s_addr <= s_addr + 1;
				end if;
				s_get <= '0';
				case state is
					when IDLE =>
						if s_delay = '1' then
							state <= INIT;
						end if;
					when INIT =>
						state <= SEND_ADR;
						s_start <= '1';
						s_read <= '0';
						s_write <= '1';
						s_ack <= '0';
						s_stop <= '0';
						s_Data_w <= (slave_addr & '0'); -- write to slave (R/W = '0')
					when START =>
						if cmd_ack = '1' then
							if s_rom_q = "10101010" then
								s_ctrl_scl <= '1';
								done <= '1';
								state <= ENDS;
							else
								state <= SEND_ADR;
								s_start <= '1';
								s_read <= '0';
								s_write <= '1';
								s_ack <= '0';
								s_stop <= '0';
								s_Data_w <= (slave_addr & '0'); -- write to slave (R/W = '0')
							end if;
						end if;
					when SEND_ADR =>
						if cmd_ack = '1' then
--							if s_lack = '1' then
--								state <= ENDS;
--							else
							   s_start <= '0';
							   s_read <= '0';
							   s_write <= '1';
							   s_ack <= '0';
							   s_stop <= '0';
							   s_data_w <= s_rom_q;
							   s_get <= '1';
							   state <= SEND_DATA;
--							end if;
						end if;
					when SEND_DATA =>
						if cmd_ack = '1' then
--							if s_lack = '1' then
--								state <= ENDS;
--							else
								s_start <= '0';
								s_read <= '0';
								s_write <= '1';
								s_ack <= '0';
								s_stop <= '1';
								s_data_w <= s_rom_q;
								s_get <= '1';
								state <= START;							
--							end if;
						end if;
					when others =>
						s_start <= '0';
						s_read <= '0';
						s_write <= '0';
						s_ack <= '0';
						s_stop <= '0';
				end case;
			end if;
		end if;
	end process;
	
--	process (clk)
--		variable rt : integer range 0 to 2000000 := 0;
--	begin
--	    if clk = '1' and clk'event then
--	        if rt < 1800000 then
--				rt := rt + 1;
--	        	nReset <= '0';
--	    	else
--	        	nReset <='1';
--			end if;
--	    end if;
--	end process;
	
	process (clk,nReset)
	begin
		if nReset = '0' then
			s_delay <= '0';
			s_delay_cnt <= 0;
		else
			if clk'event and clk = '1' then
				if s_delay_cnt /= delay_time then
					s_delay_cnt <= s_delay_cnt + 1;
					s_delay <= '0';
				else
					s_delay_cnt <= s_delay_cnt;
					s_delay <= '1'; 
				end if;
			end if;
		end if;
	end process;
end rtl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -