-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathi2c_controller.vhd
135 lines (121 loc) · 3.87 KB
/
i2c_controller.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
----------------------------------------------------------------------------------
--Code by: Zachary Rauen
--Date: 1/8/15
--Last Modified: 1/15/15
--
--Description: This takes in 16 bit data and displays them on an external display
-- using GPIO and I2C communication.
--
--Version: 2.1
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
entity i2c_controller is
Generic (slave_addr : std_logic_vector(6 downto 0) := "1110001");
Port ( Clock : in STD_LOGIC;
dataIn : in STD_LOGIC_VECTOR (15 downto 0);
oSDA : inout STD_LOGIC;
oSCL : inout STD_LOGIC);
end i2c_controller;
architecture Behavioral of i2c_controller is
component i2c_master IS
GENERIC(
input_clk : INTEGER := 100_000_000; --input clock speed from user logic in Hz
bus_clk : INTEGER := 400_000); --speed the i2c bus (scl) will run at in Hz
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --active low reset
ena : IN STD_LOGIC; --latch in command
addr : IN STD_LOGIC_VECTOR(6 DOWNTO 0); --address of target slave
rw : IN STD_LOGIC; --'0' is write, '1' is read
data_wr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); --data to write to slave
busy : OUT STD_LOGIC; --indicates transaction in progress
data_rd : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --data read from slave
ack_error : BUFFER STD_LOGIC; --flag if improper acknowledge from slave
sda : INOUT STD_LOGIC; --serial data output of i2c bus
scl : INOUT STD_LOGIC); --serial clock output of i2c bus
END component i2c_master;
signal regBusy,sigBusy,reset,enable,readwrite,nack : std_logic;
signal regData : std_logic_vector(15 downto 0);
signal dataOut : std_logic_vector(7 downto 0);
signal byteChoice : integer := 1;
signal byteChoiceMax : integer := 13;
signal initialCount : integer := 0;
type state_type is (start,write,stop);
signal State : state_type := start;
signal address : std_logic_vector(6 downto 0);
signal Cnt : integer := 16383;
begin
output: i2c_master
port map (
clk=>Clock,
reset_n=>reset,
ena=>enable,
addr=>address,
rw=>readwrite,
data_wr=>dataOut,
busy=>sigBusy,
data_rd=>OPEN,
ack_error=>nack,
sda=>oSDA,
scl=>oSCL);
StateChange: process (Clock)
begin
if rising_edge(Clock) then
case State is
when start =>
if Cnt /= 0 then
Cnt<=Cnt-1;
reset<='0';
State<=start;
enable<='0';
else
reset<='1';
enable<='1';
address<=slave_addr;
readwrite<='0';
State<=write;
end if;
when write=>
regBusy<=sigBusy;
regData<=dataIn;
if regBusy/=sigBusy and sigBusy='0' then
if byteChoice /= byteChoiceMax then
byteChoice<=byteChoice+1;
State<=write;
else
byteChoice<=8;
State<=stop;
end if;
end if;
when stop=>
enable<='0';
if regData/=dataIn then
State<=start;
else
State<=stop;
end if;
end case;
end if;
end process;
process(byteChoice,Clock)
begin
case byteChoice is
when 1 => dataOut <= x"76";
when 2 => dataOut <= x"76";
when 3 => dataOut <= x"76";
when 4 => dataOut <= x"7A";
when 5 => dataOut <= x"FF";
when 6 => dataOut <= x"77";
when 7 => dataOut <= x"00";
when 8 => dataOut <= x"79";
when 9 => dataOut <= x"00";
when 10 => dataOut <= x"0" & dataIn(15 downto 12);
when 11 => dataOut <= x"0" & dataIn(11 downto 8);
when 12 => dataOut <= x"0" & dataIn(7 downto 4);
when 13 => dataOut <= x"0" & dataIn(3 downto 0);
when others => dataOut <= x"76";
end case;
end process;
end Behavioral;