📄 i2c.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 + -