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

📄 i2c.vhd

📁 I2C的VHDL源码
💻 VHD
字号:
----------------------------------------
--The I2C VHDL Module by Houdong--------
--created in 2007/11--------------------
--Copyright reserved--------------------
----------------------------------------

LIBRARY ieee;
USE IEEE.STD_LOGIC_1164.ALL; 
USE IEEE.STD_LOGIC_ARITH.ALL;
USE	IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY I2C IS
PORT
	(
		cp											:	IN		STD_LOGIC;
		mcu_scl										:	IN		STD_LOGIC;						--MCU IIC
		mcu_sda										:	INOUT	STD_LOGIC;
		test										:	OUT		std_logic;
		seg7_data									:	OUT		STD_LOGIC_VECTOR(0 TO 6);
		dot											:	OUT		STD_LOGIC;
		seg7_sel									:	OUT 	STD_LOGIC_VECTOR(3 DOWNTO 0);
		data										:	OUT		STD_LOGIC_VECTOR(7 DOWNTO 0)	--IIC DATA OUT
	);
END I2C;

ARCHITECTURE RTL OF I2C IS
SIGNAL 		data_tmp								:	STD_LOGIC_VECTOR(7 DOWNTO 0);			--VELO REG
SIGNAL 		clk_reg									:	STD_LOGIC;

CONSTANT	BASE_ADDRESS							:	std_logic_vector(7 DOWNTO 0):=X"92";	--BASE WRITE ADDRESS
CONSTANT	READ_ADDRESS							:	std_logic_vector(7 DOWNTO 0):=X"93";	--BASE READ	 ADDRESS

SIGNAL	data0,data1,data2,data3,disp_data			:	std_logic_vector(3 DOWNTO 0);
SIGNAL	sda_reg1,sda_reg2,sda_write,sda_read,scl	:	std_logic;
SIGNAL 	sda_shift,read_reg,offset_reg				:	std_logic_vector(7 DOWNTO 0);	
SIGNAL 	status_a,status_b,status_c					:	std_logic_vector(1 DOWNTO 0):="00";
SIGNAL 	ak,bus_sel,shift_sel,break,rw_flag			:	std_logic:='0';
SIGNAL 	counter										:	std_logic_vector(3 DOWNTO 0);
SIGNAL 	counter_test 								:	std_logic_vector(7 DOWNTO 0);
SIGNAL  start,rw_start,reset,clk,clear				:	std_logic;

BEGIN

------------------------------------------------------------------------bidir interface
mcu_sda<=
(ak AND sda_read) WHEN (bus_sel='1') ELSE
'Z';

sda_reg1<=
mcu_sda WHEN(bus_sel='0') ELSE
'X';

scl <= mcu_scl;
sda_write <= sda_reg1;

------------------------------------------------------------------------7SEG DISPLAY
PROCESS(cp)
VARIABLE div_clk		:	INTEGER RANGE 0 TO 1000;  
BEGIN
IF cp'event AND cp='1' THEN
	IF div_clk = 1000 THEN
		div_clk := 0;
	ELSE
		div_clk := div_clk + 1;
	END IF;

	IF div_clk <500 THEN
		clk <= '0';
	ELSE
		clk <= '1';
	END IF;		 
END IF;
END PROCESS;

PROCESS(clk,data0,data1,data2,data3)
VARIABLE sel_counter 	:	INTEGER RANGE 0 TO 3;
BEGIN
IF clk'event AND clk='1' THEN
	IF sel_counter = 3 THEN
		sel_counter := 0;
	ELSE
		sel_counter := sel_counter +1;
	END IF;
END IF;

CASE sel_counter IS
WHEN 0 => seg7_sel <= "1110";disp_data<=data0;dot<='0';
WHEN 1 => seg7_sel <= "1101";disp_data<=data1;dot<='1';
WHEN 2 => seg7_sel <= "1011";disp_data<=data2;dot<='0';
WHEN OTHERS => seg7_sel <= "0111";disp_data<=data3;dot<='0';
END CASE;
END PROCESS;

------------------------------------------------------------------------7SEG DECODE
PROCESS(disp_data)
BEGIN
CASE disp_data IS
WHEN X"0" => seg7_data <="1111110";
WHEN X"1" => seg7_data <="0110000";
WHEN X"2" => seg7_data <="1101101";
WHEN X"3" => seg7_data <="1111001";
WHEN X"4" => seg7_data <="0110011";
WHEN X"5" => seg7_data <="1011011";
WHEN X"6" => seg7_data <="1011111";
WHEN X"7" => seg7_data <="1110000";
WHEN X"8" => seg7_data <="1111111";
WHEN X"9" => seg7_data <="1111011";
WHEN OTHERS => seg7_data <="0000000";
END CASE;
END PROCESS;

------------------------------------------------------------------------generate the start or stop signal
PROCESS(scl,sda_write,status_a,reset)
BEGIN
IF status_a(1)='1' THEN
	status_a(0)<='0';
	ELSIF sda_write'event and sda_write='0' THEN
		IF scl='1' THEN
			status_a(0)<='1';
		END IF;
END IF;
END PROCESS;

PROCESS(scl,sda_write,status_a,reset,break)
BEGIN
IF status_a(1)='1' OR reset='0' THEN
	status_a(1)<='0';
	ELSIF break='1' THEN
		status_a(1)<='1';
		ELSIF sda_write'event and sda_write='1' THEN
			IF scl='1' THEN
				status_a(1)<='1';
			END IF;
END IF;
END PROCESS;

PROCESS(reset,scl,sda_write,counter_test)
BEGIN
IF (scl='1' AND counter_test =X"01") OR reset='0' THEN
	start<='0';
	ELSIF sda_write'event and sda_write='0' THEN
		IF scl='1' THEN
				start<='1';
		END IF;
END IF;
END PROCESS;

PROCESS(status_a,scl,start)
BeGIN
IF status_a="00" THEN
	rw_start<='0';
		ELSIF scl'event and scl='0' THEN
			IF start='1' THEN
			 rw_start<=NOT rw_start;
			END IF;
END IF;
END PROCESS;



-------------------------------------------------------------------------generate matching BASE address signal
-------------------------------------------------------------------------and write or read flag signal			
PROCESS(scl,status_a,counter,counter_test,rw_start,sda_shift)
BEGIN
IF status_a="00" THEN
	status_b<="00";
	rw_flag<='0';
	ELSIF scl'event and scl='0' THEN

	IF counter=X"7" AND counter_test<X"a" THEN
		IF sda_shift=BASE_ADDRESS THEN
			status_b(0)<='1';
		END IF;

		IF sda_shift/=BASE_ADDRESS THEN
			status_b(1)<='1';
		END IF;
    END IF;

	IF counter=x"7" AND rw_start='0' THEN
     	IF sda_shift=READ_ADDRESS THEN
			rw_flag<='1';
		END IF;		
	END IF;
END IF;
END PROCESS;
		
--------------------------------------------------------------------------generate matching REG address signal
PROCESS(scl,counter,counter_test,status_a,status_b,status_c,sda_shift)
BEGIN
IF status_a="00" THEN
	status_c<="00";
	ELSIF scl'event and scl='0' THEN
		IF counter=X"7" THEN	
			IF counter_test>X"09" AND counter_test < X"13" THEN
				IF (status_b(0)='1') THEN
					status_c(0)<='1';
					 offset_reg<=sda_shift;
				END IF;
				IF status_b(1)='1' THEN
					status_c(1)<='1';
				END IF;
			END IF;
		END IF;
END IF;
END PROCESS;

--------------------------------------------------------------------------sda WRITE shift 
PROCESS(scl,status_a,shift_sel,reset)
BEGIN 
IF reset='0' OR status_a="00" THEN
	sda_shift<=X"00";
	ELSIF scl'event and scl='1' THEN
			IF shift_sel='0' THEN
				sda_shift(0)<=sda_write;
				FOR i IN 1 TO 7 LOOP 
				sda_shift(i)<=sda_shift(i-1);
        		END LOOP;
			END IF;
END IF;
END PROCESS;

--------------------------------------------------------------------------sda READ shift 
PROCESS(scl,start,shift_sel,reset,read_reg,offset_reg,data_tmp)
BEGIN
IF shift_sel='0' THEN
					CASE offset_reg IS
					WHEN x"00" =>
						read_reg <= data_tmp;
					WHEN OTHERS => NULL;
				END CASE;
	ELSIF scl'event and scl='0' THEN
	    IF shift_sel='1' THEN
				sda_read<=read_reg(7);
				FOR i IN 1 TO 7 LOOP 
				read_reg(i)<=read_reg(i-1);
        		END LOOP;
				read_reg(0)<=read_reg(7);
		END IF;
END IF;
END PROCESS;
  	
--------------------------------------------------------------------------shift counter
PROCESS(scl,start,status_a)
BEGIN
IF status_a="00" OR start='1' THEN
	counter<="0000";
	ELSIF scl'event and scl='0' THEN
		IF counter=X"9" THEN
			counter<=X"1";
		ELSE
			counter<=counter+1;
		END IF;
END IF;
END PROCESS;

PROCESS(scl,status_a,reset)
BEGIN
IF status_a="00" OR reset='0' THEN
	counter_test<=X"00";
	ELSIF scl'event and scl='0' THEN
		counter_test<=counter_test+1;
END IF;
END PROCESS;

--------------------------------------------------------------------------generate ak signal
PROCESS(scl,status_a,counter,sda_shift)
BEGIN
IF status_a="00" THEN
	ak<='1';
	ELSIF scl'EVENT AND scl='0' THEN
		IF status_a(0)='1' THEN
			IF ((counter=X"7") AND status_b(0)='0' AND sda_shift=BASE_ADDRESS)
			OR ((counter=X"7") AND status_b(0)='1' AND status_c(0)='0')
			OR ((counter=X"7") AND status_b(0)='1' AND status_c(0)='1') THEN

					ak<='0';
				ELSE
					ak<='1';
				END IF;
		END IF;
END IF;
END PROCESS;

--------------------------------------------------------------------------generate break signal
PROCESS(scl,status_a,counter_test,sda_shift)
BEGIN
IF status_a="00" THEN
	break<='0';
	ELSIF scl'event AND scl='0' THEN
		IF (counter_test=X"08") AND (sda_shift/=X"92") THEN
					break<='1';
				ELSE
					break<='0';
		END IF;
END IF;
END PROCESS;

--------------------------------------------------------------------------generate shift sel signal
PROCESS(ak,scl,status_a,counter_test)
BEGIN
IF status_a="00" OR counter_test=X"26" THEN
	shift_sel<='0';
	ELSIF scl'event and scl='1' THEN
			shift_sel<=rw_flag;
END IF;
END PROCESS;			

---------------------------------------------------------------------------get parallel data byte
PROCESS(scl,shift_sel,status_b,status_c,rw_start,reset,offset_reg)
BEGIN
	IF scl'event and scl='0' THEN
		IF shift_sel='0' THEN	
			IF counter=X"7" AND status_b(0)='1' AND status_c(0)='1' AND rw_start='1' THEN
				CASE offset_reg IS
					WHEN x"00" =>
						data_tmp <= sda_shift;
					WHEN x"01" =>
						data0 <= sda_shift(3 DOWNTO 0);	
					WHEN x"02" =>
						data1 <= sda_shift(3 DOWNTO 0);	
					WHEN x"03" =>
						data2 <= sda_shift(3 DOWNTO 0);	
					WHEN x"04" =>
						data3 <= sda_shift(3 DOWNTO 0);																			
					WHEN OTHERS => NULL;
				END CASE;
			END IF;
		END IF;
	END IF;
END PROCESS;

reset<=(NOT break);
test <=  ak;
bus_sel<=shift_sel OR not ak;

data <= data_tmp;

END RTL;

⌨️ 快捷键说明

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