69 i2c_slave : process
70 variable v_addr_byte : std_logic_vector(7 downto 0);
71 variable v_rw : std_logic := '0';
72 variable v_reg_addr : integer range 0 to 255;
73 variable v_reg_inc : integer range 0 to 255;
74 variable v_data_h : std_logic_vector(7 downto 0);
75 variable v_data_l : std_logic_vector(7 downto 0);
76 variable v_data_16 : std_logic_vector(15 downto 0);
77 variable v_stop_seen : boolean;
78 variable v_start_seen : boolean;
79 variable v_mack : std_logic;
80 variable v_send_byte : std_logic_vector(7 downto 0);
81
82 begin
84
85
86 loop
87
88
89
90
91
92
93
95 wait until falling_edge(sda) and scl = '1';
97
98
99
100
101
102
103 for i in 7 downto 0 loop
104 wait until rising_edge(scl);
105 v_addr_byte(i) := sda;
106 end loop;
107
109
110 if v_addr_byte(7 downto 1) = I2C_ADDR then
111
113 wait until falling_edge(scl);
116 wait until rising_edge(scl);
119 wait until falling_edge(scl);
121
122
123
124
125
126
127 for i in 7 downto 0 loop
128 wait until rising_edge(scl);
129 v_addr_byte(i) := sda;
130 end loop;
131
133 v_reg_addr := to_integer(unsigned(v_addr_byte));
135 v_reg_inc := v_reg_addr;
137 wait until falling_edge(scl);
138
141 wait until rising_edge(scl);
144
145 wait until falling_edge(scl);
146 v_stop_seen := false;
147
148 v_rw := '0';
149
150 while not v_stop_seen loop
151
152
153
154
155
156
158 for i in 7 downto 0 loop
159 if v_rw = '0' then
160 wait until rising_edge(scl);
161 debug_state <= "DATAH CLK NUM i=" & integer'image(i);
163 wait until rising_edge(sda) or falling_edge(sda) or falling_edge(scl);
166 v_stop_seen := true;
168 exit;
169
171 v_start_seen := true;
173 exit;
174
175 end if;
176 else
178 end if;
179
180 else
181 if i /= 7 then
182 wait until falling_edge(scl);
183 end if;
184 debug_state <= "RDATAH CLK NUM i=" & integer'image(i);
187
188 if i = 0 then
189 wait until falling_edge(scl);
190 end if;
191 end if;
192
193
194
195 end loop;
196
197
198
199 if v_stop_seen then
200 exit;
201 end if;
202
203
204
205
206
207 if v_start_seen then
208 v_start_seen := false;
210
211 for i in 7 downto 0 loop
212 wait until rising_edge(scl);
213 debug_state <= "ADDR_R CLK NUM i=" & integer'image(i);
214 v_addr_byte(i) := sda;
215
216 wait until rising_edge(sda) or falling_edge(sda) or falling_edge(scl);
217
220 v_stop_seen := true;
222 exit;
223
225 v_start_seen := true;
227 exit;
228
229 end if;
230 else
232 end if;
233
234 end loop;
235
236
237
238 if v_addr_byte(0) = '1' then
239 v_rw := '1';
240 else
241 v_rw := '0';
242 end if;
244
245
246 wait for 0.4 us;
249 wait until rising_edge(scl);
252 wait until falling_edge(scl);
253
254 next;
255
256 end if;
257
258
259
260
261
262 if v_rw = '0' then
263
265
267
270
271 wait until rising_edge(scl);
274 else
276 wait until rising_edge(scl);
279 else
280 exit;
281 end if;
282
283
284 end if;
285
286 wait until falling_edge(scl);
287
288
289
290
291
293
294 for i in 7 downto 0 loop
295 if v_rw = '0' then
296 wait until rising_edge(scl);
297
299 debug_state <= "DATAL CLK NUM i=" & integer'image(i);
300
301 wait until rising_edge(sda) or falling_edge(sda) or falling_edge(scl);
302
305 v_stop_seen := true;
307 exit;
308
310
311 v_start_seen := true;
313 exit;
314
315 end if;
316 else
318 end if;
319 else
320 if i /= 7 then
321 wait until falling_edge(scl);
322 end if;
323 debug_state <= "R2DATAH CLK NUM i=" & integer'image(i);
325 if i = 0 then
326 wait until falling_edge(scl);
327 end if;
328 end if;
329
330 end loop;
331
332 if v_rw = '0' then
333
335
337
340
341 wait until rising_edge(scl);
344 else
347 wait until rising_edge(scl);
350 else
351 exit;
352 end if;
353
354
355 end if;
356
357
358 wait until falling_edge(scl);
360
361 v_data_16 := v_data_h & v_data_l;
363
364 if v_reg_inc = 255 then
365 v_reg_inc := 0;
366 else
367 v_reg_inc := v_reg_inc + 1;
368 end if;
369
371 end loop;
372 end if;
373
374 end loop;
375
376 end process i2c_slave;
string( 1 to 20) :=( others => ' ') debug_state
integer range 0 to 255:= 0 read_reg_addr
reg_map_t :=( 16#00#=> x"823A", 16#0D#=> x"0008", others => x"CACA") regs_core
integer range 0 to 255 s_reg_addr
I2C_ADDR std_logic_vector( 6 downto 0) := "1011100"