blob: 99b179b7e078050224b0ba6a6635d334284999ab (
plain)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
|
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity i2C_master is
generic (
system_frequency : real := 50.0E6; -- 50 MHz
i2c_rate : real := 20.0E3 -- 20 kHz
);
port (
clk : in std_logic;
resetn : in std_logic;
go : in std_logic;
ready : out std_logic;
data_in : in std_logic_vector(23 downto 0); -- adress & command & data
ack : out std_logic;
-- i2c
i2c_scl : out std_logic; -- A6
i2c_sda : inout std_logic -- B6
);
end entity;
architecture rtl of i2c_master is
constant mod_ctr_tempo : positive := integer(system_frequency/(2.0*i2c_rate));
constant mod_ctr_bit : positive := 35;
type state is (wait_for_go, wait_for_i2clk, tx);
signal current_state : state;
signal next_state : state;
signal sdo : std_logic;
signal ctr_tempo : natural range 0 to mod_ctr_tempo-1;
signal end_tempo : std_logic;
signal ctr_bit : natural range 0 to mod_ctr_bit-1;
signal ack1 : std_logic;
signal ack2 : std_logic;
signal ack3 : std_logic;
signal reg_data : std_logic_vector(data_in'range);
signal cmd_data : std_logic_vector(1 downto 0);
signal cmd_bit : std_logic_vector(1 downto 0);
signal cmd_ack1 : std_logic_vector(1 downto 0);
signal cmd_ack2 : std_logic_vector(1 downto 0);
signal cmd_ack3 : std_logic_vector(1 downto 0);
signal sclk : std_logic;
signal i2c_clk : std_logic;
signal ready_i : std_logic;
begin
i2c_sda <= 'Z' when sdo = '1'
else '0';
i2c_scl <= '1' when sclk='1'
else not i2c_clk when (ctr_bit>=4 and ctr_bit <= 30)
else '0';
ack <= ack1 or ack2 or ack3;
end_tempo <= '0' when ctr_tempo< mod_ctr_tempo-1 else '1';
process(resetn, clk) is
begin
if resetn = '0' then
i2c_clk <= '0';
ctr_tempo <= 0;
ctr_bit <= 0;
reg_data <= (others => '0');
--sclk <= '1';
ACK1 <= '0';
ACK2 <= '0';
ACK3 <= '0';
ready <= '1';
current_state <= wait_for_go;
elsif rising_edge(clk) then
current_state <= next_state;
ready <= ready_i;
-- temporisation et i2_clk
if current_state = wait_for_go then
ctr_tempo <= 0;
i2c_clk <= '0';
elsif end_tempo='0' then
ctr_tempo <= ctr_tempo +1;
else
ctr_tempo <= 0;
i2c_clk <= not i2c_clk;
end if;
-- reg_data
case cmd_data is
when "10" => reg_data <= data_in;
when "11" => reg_data <= reg_data(22 downto 0)&'0';
when others => null;
end case;
-- ctr_bit
case cmd_bit is
when "10" => ctr_bit <= 0;
when "11" => if ctr_bit<mod_ctr_bit-1 then ctr_bit <= ctr_bit+1;
else ctr_bit <= 0;
end if;
when others => null;
end case;
-- ack1
case cmd_ack1 is
when "10" => ack1 <= '0';
when "11" => ack1 <= '1';
when others => null;
end case;
-- ack2
case cmd_ack2 is
when "10" => ack2 <= '0';
when "11" => ack2 <= '1';
when others => null;
end case;
-- ack1
case cmd_ack3 is
when "10" => ack3 <= '0';
when "11" => ack3 <= '1';
when others => null;
end case;
end if;
end process;
--------------------------------
-- FSM
-------------------------------
process(current_state, end_tempo, i2c_clk, go,reg_data(23), i2c_sda,ctr_bit) is
begin
next_state <= current_state;
ready_i <= '0';
cmd_ack1 <= "00";
cmd_ack2 <= "00";
cmd_ack3 <= "00";
cmd_bit <= "00";
cmd_data <= "00";
sdo <= '1';
sclk <= '0';
case current_state is
when wait_for_go => if go = '1' then next_state <=wait_for_i2clk;
end if;
ready_i <= '1';
cmd_bit <= "10";
cmd_data <= "10";
sclk <= '1';
when wait_for_i2clk => if i2c_clk='0' and end_tempo='1' then next_state <=tx;
end if;
cmd_ack1 <= "10";
cmd_ack2 <= "10";
cmd_ack3 <= "10";
sclk <= '1';
when tx => if ctr_bit< mod_ctr_bit-1 then
if i2c_clk='0' and end_tempo='1'then
cmd_bit <= "11";
end if;
elsif end_tempo='1'then
next_state <= wait_for_go;
end if;
case ctr_bit is
when 0 => sdo <= '1'; sclk <= '1';
-- start
when 1 => sdo <= '0'; sclk <= '0';
when 2 => sdo <= '0'; sclk <= '0';
-- slave address
when 3 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 4 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 5 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 6 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 7 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 8 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 9 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 10 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 11 => sdo <= '1'; -- ack
-- command
when 12 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
if i2c_sda='1' then cmd_ack1 <= "11" ;
else cmd_ack1 <= "10" ;
end if;
when 13 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 14 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 15 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 16 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 17 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 18 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 19 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 20 => sdo <= '1'; -- ack
-- data
when 21 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
if i2c_sda='1' then cmd_ack2 <= "11" ;
else cmd_ack2 <= "10" ;
end if;
when 22 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 23 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 24 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 25 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 26 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 27 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 28 => sdo <= reg_data(23);
if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
end if;
when 29 => sdo <= '1'; -- ack
--stop
when 30 => sdo <= '0';
if i2c_sda='1' then cmd_ack3 <= "11" ;
else cmd_ack3 <= "10" ;
end if;
sclk <= '0';
when 31 => sdo <= '0'; sclk <= '1';
when others => sdo <= '1'; sclk <= '1';
end case;
end case;
end process;
end architecture;
|