OpenCores
URL https://opencores.org/ocsvn/i2c/i2c/trunk

Subversion Repositories i2c

[/] [i2c/] [trunk/] [rtl/] [vhdl/] [I2C.VHD] - Blame information for rev 76

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 10 rherveille
--
2
-- Simple I2C controller
3
--
4
-- 1) No multimaster
5
-- 2) No slave mode
6
-- 3) No fifo's
7
--
8
-- notes:
9
-- Every command is acknowledged. Do not set a new command before previous is acknowledged.
10
-- Dout is available 1 clock cycle later as cmd_ack
11
--
12
 
13
library ieee;
14
use ieee.std_logic_1164.all;
15
use ieee.std_logic_arith.all;
16
 
17
package I2C is
18
        component simple_i2c is
19
        port (
20
                clk : in std_logic;
21
                ena : in std_logic;
22
                nReset : in std_logic;
23
 
24
                clk_cnt : in unsigned(7 downto 0);      -- 4x SCL
25
 
26
                -- input signals
27
                start,
28
                stop,
29
                read,
30
                write,
31
                ack_in : std_logic;
32
                Din : in std_logic_vector(7 downto 0);
33
 
34
                -- output signals
35
                cmd_ack : out std_logic;
36
                ack_out : out std_logic;
37
                Dout : out std_logic_vector(7 downto 0);
38
 
39
                -- i2c signals
40
                SCL : inout std_logic;
41
                SDA : inout std_logic
42
        );
43
        end component simple_i2c;
44
end package I2C;
45
 
46
 
47
library ieee;
48
use ieee.std_logic_1164.all;
49
use ieee.std_logic_arith.all;
50
 
51
entity simple_i2c is
52
        port (
53
                clk : in std_logic;
54
                ena : in std_logic;
55
                nReset : in std_logic;
56
 
57
                clk_cnt : in unsigned(7 downto 0);      -- 4x SCL
58
 
59
                -- input signals
60
                start,
61
                stop,
62
                read,
63
                write,
64
                ack_in : std_logic;
65
                Din : in std_logic_vector(7 downto 0);
66
 
67
                -- output signals
68
                cmd_ack : out std_logic;
69
                ack_out : out std_logic;
70
                Dout : out std_logic_vector(7 downto 0);
71
 
72
                -- i2c signals
73
                SCL : inout std_logic;
74
                SDA : inout std_logic
75
        );
76
end entity simple_i2c;
77
 
78
architecture structural of simple_i2c is
79
        component i2c_core is
80
        port (
81
                clk : in std_logic;
82
                nReset : in std_logic;
83
 
84
                clk_cnt : in unsigned(7 downto 0);
85
 
86
                cmd : in std_logic_vector(2 downto 0);
87
                cmd_ack : out std_logic;
88
                busy : out std_logic;
89
 
90
                Din : in std_logic;
91
                Dout : out std_logic;
92
 
93
                SCL : inout std_logic;
94
                SDA : inout std_logic
95
        );
96
        end component i2c_core;
97
 
98
        -- commands for i2c_core
99
        constant CMD_NOP        : std_logic_vector(2 downto 0) := "000";
100
        constant CMD_START      : std_logic_vector(2 downto 0) := "010";
101
        constant CMD_STOP       : std_logic_vector(2 downto 0) := "011";
102
        constant CMD_READ       : std_logic_vector(2 downto 0) := "100";
103
        constant CMD_WRITE      : std_logic_vector(2 downto 0) := "101";
104
 
105
        -- signals for i2c_core
106
        signal core_cmd : std_logic_vector(2 downto 0);
107
        signal core_ack, core_busy, core_txd, core_rxd : std_logic;
108
 
109
        -- signals for shift register
110
        signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
111
        signal shift, ld : std_logic;
112
 
113
        -- signals for state machine
114
        signal go, host_ack : std_logic;
115
begin
116
        -- hookup i2c core
117
        u1: i2c_core port map (clk, nReset, clk_cnt, core_cmd, core_ack, core_busy, core_txd, core_rxd, SCL, SDA);
118
 
119
        -- generate host-command-acknowledge
120
        cmd_ack <= host_ack;
121
 
122
        -- generate go-signal
123
        go <= (read or write) and not host_ack;
124
 
125
        -- assign Dout output to shift-register
126
        Dout <= sr;
127
 
128
        -- assign ack_out output to core_rxd (contains last received bit)
129
        ack_out <= core_rxd;
130
 
131
        -- generate shift register
132
        shift_register: process(clk)
133
        begin
134
                if (clk'event and clk = '1') then
135
                        if (ld = '1') then
136
                                sr <= din;
137
                        elsif (shift = '1') then
138
                                sr <= (sr(6 downto 0) & core_rxd);
139
                        end if;
140
                end if;
141
        end process shift_register;
142
 
143
        --
144
        -- state machine
145
        --
146
        statemachine : block
147
                type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
148
                signal state : states;
149
                signal dcnt : unsigned(2 downto 0);
150
        begin
151
                --
152
                -- command interpreter, translate complex commands into simpler I2C commands
153
                --
154
                nxt_state_decoder: process(clk, nReset, state)
155
                        variable nxt_state : states;
156
                        variable idcnt : unsigned(2 downto 0);
157
                        variable ihost_ack : std_logic;
158
                        variable icore_cmd : std_logic_vector(2 downto 0);
159
                        variable icore_txd : std_logic;
160
                        variable ishift, iload : std_logic;
161
                begin
162
                        -- 8 databits (1byte) of data to shift-in/out
163
                        idcnt := dcnt;
164
 
165
                        -- no acknowledge (until command complete)
166
                        ihost_ack := '0';
167
 
168
                        icore_txd := core_txd;
169
 
170
                        -- keep current command to i2c_core
171
                        icore_cmd := core_cmd;
172
 
173
                        -- no shifting or loading of shift-register
174
                        ishift := '0';
175
                        iload := '0';
176
 
177
                        -- keep current state;
178
                        nxt_state := state;
179
                        case state is
180
                                when st_idle =>
181
                                        if (go = '1') then
182
                                                if (start = '1') then
183
                                                        nxt_state := st_start;
184
                                                        icore_cmd := CMD_START;
185
                                                elsif (read = '1') then
186
                                                        nxt_state := st_read;
187
                                                        icore_cmd := CMD_READ;
188
                                                        idcnt := "111";
189
                                                else
190
                                                        nxt_state := st_write;
191
                                                        icore_cmd := CMD_WRITE;
192
                                                        idcnt := "111";
193
                                                        iload := '1';
194
                                                end if;
195
                                        end if;
196
 
197
                                when st_start =>
198
                                        if (core_ack = '1') then
199
                                                if (read = '1') then
200
                                                        nxt_state := st_read;
201
                                                        icore_cmd := CMD_READ;
202
                                                        idcnt := "111";
203
                                                else
204
                                                        nxt_state := st_write;
205
                                                        icore_cmd := CMD_WRITE;
206
                                                        idcnt := "111";
207
                                                        iload := '1';
208
                                                end if;
209
                                        end if;
210
 
211
                                when st_write =>
212
                                        if (core_ack = '1') then
213
                                                idcnt := dcnt -1;       -- count down Data_counter
214
                                                icore_txd := sr(7);
215
                                                if (dcnt = 0) then
216
                                                        nxt_state := st_ack;
217
                                                        icore_cmd := CMD_READ;
218
                                                else
219
                                                        ishift := '1';
220
--                                                      icore_txd := sr(7);
221
                                                end if;
222
                                        end if;
223
 
224
                                when st_read =>
225
                                        if (core_ack = '1') then
226
                                                idcnt := dcnt -1;       -- count down Data_counter
227
                                                ishift := '1';
228
                                                if (dcnt = 0) then
229
                                                        nxt_state := st_ack;
230
                                                        icore_cmd := CMD_WRITE;
231
                                                        icore_txd := ack_in;
232
                                                end if;
233
                                        end if;
234
 
235
                                when st_ack =>
236
                                        if (core_ack = '1') then
237
                                                -- generate command acknowledge signal
238
                                                ihost_ack := '1';
239
 
240
                                                -- Perform an additional shift, needed for 'read' (store last received bit in shift register)
241
                                                ishift := '1';
242
 
243
                                                -- check for stop; Should a STOP command be generated ?
244
                                                if (stop = '1') then
245
                                                        nxt_state := st_stop;
246
                                                        icore_cmd := CMD_STOP;
247
                                                else
248
                                                        nxt_state := st_idle;
249
                                                        icore_cmd := CMD_NOP;
250
                                                end if;
251
                                        end if;
252
 
253
                                when st_stop =>
254
                                        if (core_ack = '1') then
255
                                                nxt_state := st_idle;
256
                                                icore_cmd := CMD_NOP;
257
                                        end if;
258
 
259
                                when others => -- illegal states
260
                                        nxt_state := st_idle;
261
                                        icore_cmd := CMD_NOP;
262
                        end case;
263
 
264
                        -- generate registers
265
                        if (nReset = '0') then
266
                                core_cmd <= CMD_NOP;
267
                                core_txd <= '0';
268
 
269
                                shift <= '0';
270
                                ld <= '0';
271
 
272
                                dcnt <= "111";
273
                                host_ack <= '0';
274
 
275
                                state <= st_idle;
276
                        elsif (clk'event and clk = '1') then
277
                                if (ena = '1') then
278
                                        state <= nxt_state;
279
 
280
                                        dcnt <= idcnt;
281
                                        shift <= ishift;
282
                                        ld <= iload;
283
 
284
                                        core_cmd <= icore_cmd;
285
                                        core_txd <= icore_txd;
286
 
287
                                        host_ack <= ihost_ack;
288
                                end if;
289
                        end if;
290
                end process nxt_state_decoder;
291
 
292
        end block statemachine;
293
 
294
end architecture structural;
295
 
296
 
297
--
298
--
299
-- I2C Core
300
--
301
-- Translate simple commands into SCL/SDA transitions
302
-- Each command has 5 states, A/B/C/D/idle
303
--
304
-- start:       SCL     ~~~~~~~~~~\____
305
--      SDA     ~~~~~~~~\______
306
--               x | A | B | C | D | i
307
--
308
-- repstart     SCL     ____/~~~~\___
309
--      SDA     __/~~~\______
310
--               x | A | B | C | D | i
311
--
312
-- stop SCL     ____/~~~~~~~~
313
--      SDA     ==\____/~~~~~
314
--               x | A | B | C | D | i
315
--
316
--- write       SCL     ____/~~~~\____
317
--      SDA     ==X=========X=
318
--               x | A | B | C | D | i
319
--
320
--- read        SCL     ____/~~~~\____
321
--      SDA     XXXX=====XXXX
322
--               x | A | B | C | D | i
323
--
324
 
325
-- Timing:              Normal mode     Fast mode
326
-----------------------------------------------------------------
327
-- Fscl         100KHz          400KHz
328
-- Th_scl               4.0us           0.6us   High period of SCL
329
-- Tl_scl               4.7us           1.3us   Low period of SCL
330
-- Tsu:sta              4.7us           0.6us   setup time for a repeated start condition
331
-- Tsu:sto              4.0us           0.6us   setup time for a stop conditon
332
-- Tbuf         4.7us           1.3us   Bus free time between a stop and start condition
333
--
334
 
335
library ieee;
336
use ieee.std_logic_1164.all;
337
use ieee.std_logic_arith.all;
338
 
339
entity i2c_core is
340
        port (
341
                clk : in std_logic;
342
                nReset : in std_logic;
343
 
344
                clk_cnt : in unsigned(7 downto 0);
345
 
346
                cmd : in std_logic_vector(2 downto 0);
347
                cmd_ack : out std_logic;
348
                busy : out std_logic;
349
 
350
                Din : in std_logic;
351
                Dout : out std_logic;
352
 
353
                SCL : inout std_logic;
354
                SDA : inout std_logic
355
        );
356
end entity i2c_core;
357
 
358
architecture structural of i2c_core is
359
        constant CMD_NOP        : std_logic_vector(2 downto 0) := "000";
360
        constant CMD_START      : std_logic_vector(2 downto 0) := "010";
361
        constant CMD_STOP       : std_logic_vector(2 downto 0) := "011";
362
        constant CMD_READ       : std_logic_vector(2 downto 0) := "100";
363
        constant CMD_WRITE      : std_logic_vector(2 downto 0) := "101";
364
 
365
        type cmds is (idle, start_a, start_b, start_c, start_d, stop_a, stop_b, stop_c, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d);
366
        signal state : cmds;
367
        signal SDAo, SCLo : std_logic;
368
        signal txd : std_logic;
369
        signal clk_en, slave_wait :std_logic;
370
        signal cnt : unsigned(7 downto 0) := clk_cnt;
371
begin
372
        -- whenever the slave is not ready it can delay the cycle by pulling SCL low
373
        slave_wait <= '1' when ((SCLo = '1') and (SCL = '0')) else '0';
374
 
375
        -- generate clk enable signal
376
        gen_clken: process(clk, nReset)
377
        begin
378
                if (nReset = '0') then
379
                        cnt <= (others => '0');
380
                        clk_en <= '1'; --'0';
381
                elsif (clk'event and clk = '1') then
382
                        if (cnt = 0) then
383
                                clk_en <= '1';
384
                                cnt <= clk_cnt;
385
                        else
386
                                if (slave_wait = '0') then
387
                                        cnt <= cnt -1;
388
                                end if;
389
                                clk_en <= '0';
390
                        end if;
391
                end if;
392
        end process gen_clken;
393
 
394
        -- generate statemachine
395
        nxt_state_decoder : process (clk, nReset, state, cmd, SDA)
396
                variable nxt_state : cmds;
397
                variable icmd_ack, ibusy, store_sda : std_logic;
398
                variable itxd : std_logic;
399
        begin
400
 
401
                nxt_state := state;
402
 
403
                icmd_ack := '0'; -- default no acknowledge
404
                ibusy := '1'; -- default busy
405
 
406
                store_sda := '0';
407
 
408
                itxd := txd;
409
 
410
                case (state) is
411
                        -- idle
412
                        when idle =>
413
                                case cmd is
414
                                        when CMD_START =>
415
                                                nxt_state := start_a;
416
                                                icmd_ack := '1'; -- command completed
417
 
418
                                        when CMD_STOP =>
419
                                                nxt_state := stop_a;
420
                                                icmd_ack := '1'; -- command completed
421
 
422
                                        when CMD_WRITE =>
423
                                                nxt_state := wr_a;
424
                                                icmd_ack := '1'; -- command completed
425
                                                itxd := Din;
426
 
427
                                        when CMD_READ =>
428
                                                nxt_state := rd_a;
429
                                                icmd_ack := '1'; -- command completed
430
 
431
                                        when others =>
432
                                                nxt_state := idle;
433
-- don't acknowledge NOP command                                                icmd_ack := '1'; -- command completed
434
                                                ibusy := '0';
435
                                end case;
436
 
437
                        -- start
438
                        when start_a =>
439
                                nxt_state := start_b;
440
 
441
                        when start_b =>
442
                                nxt_state := start_c;
443
 
444
                        when start_c =>
445
                                nxt_state := start_d;
446
 
447
                        when start_d =>
448
                                nxt_state := idle;
449
                                ibusy := '0'; -- not busy when idle
450
 
451
 
452
                        -- stop
453
                        when stop_a =>
454
                                nxt_state := stop_b;
455
 
456
                        when stop_b =>
457
                                nxt_state := stop_c;
458
 
459
                        when stop_c =>
460
--                              nxt_state := stop_d;
461
 
462
--                      when stop_d =>
463
                                nxt_state := idle;
464
                                ibusy := '0'; -- not busy when idle
465
 
466
                        -- read
467
                        when rd_a =>
468
                                nxt_state := rd_b;
469
 
470
                        when rd_b =>
471
                                nxt_state := rd_c;
472
 
473
                        when rd_c =>
474
                                nxt_state := rd_d;
475
                                store_sda := '1';
476
 
477
                        when rd_d =>
478
                                nxt_state := idle;
479
                                ibusy := '0'; -- not busy when idle
480
 
481
                        -- write
482
                        when wr_a =>
483
                                nxt_state := wr_b;
484
 
485
                        when wr_b =>
486
                                nxt_state := wr_c;
487
 
488
                        when wr_c =>
489
                                nxt_state := wr_d;
490
 
491
                        when wr_d =>
492
                                nxt_state := idle;
493
                                ibusy := '0'; -- not busy when idle
494
 
495
                end case;
496
 
497
                -- generate regs
498
                if (nReset = '0') then
499
                        state <= idle;
500
                        cmd_ack <= '0';
501
                        busy <= '0';
502
                        txd <= '0';
503
                        Dout <= '0';
504
                elsif (clk'event and clk = '1') then
505
                        if (clk_en = '1') then
506
                                state <= nxt_state;
507
                                busy <= ibusy;
508
 
509
                                txd <= itxd;
510
                                if (store_sda = '1') then
511
                                        Dout <= SDA;
512
                                end if;
513
                        end if;
514
 
515
                        cmd_ack <= icmd_ack and clk_en;
516
                end if;
517
        end process nxt_state_decoder;
518
 
519
        --
520
        -- convert states to SCL and SDA signals
521
        --
522
        output_decoder: process (clk, nReset, state)
523
                variable iscl, isda : std_logic;
524
        begin
525
                case (state) is
526
                        when idle =>
527
                                iscl := SCLo; -- keep SCL in same state
528
                                isda := SDA; -- keep SDA in same state
529
 
530
                        -- start
531
                        when start_a =>
532
                                iscl := SCLo; -- keep SCL in same state (for repeated start)
533
                                isda := '1'; -- set SDA high
534
 
535
                        when start_b =>
536
                                iscl := '1';    -- set SCL high
537
                                isda := '1'; -- keep SDA high
538
 
539
                        when start_c =>
540
                                iscl := '1';    -- keep SCL high
541
                                isda := '0'; -- sel SDA low
542
 
543
                        when start_d =>
544
                                iscl := '0'; -- set SCL low
545
                                isda := '0'; -- keep SDA low
546
 
547
                        -- stop
548
                        when stop_a =>
549
                                iscl := '0'; -- keep SCL disabled
550
                                isda := '0'; -- set SDA low
551
 
552
                        when stop_b =>
553
                                iscl := '1'; -- set SCL high
554
                                isda := '0'; -- keep SDA low
555
 
556
                        when stop_c =>
557
                                iscl := '1'; -- keep SCL high
558
                                isda := '1'; -- set SDA high
559
 
560
                        -- write
561
                        when wr_a =>
562
                                iscl := '0';    -- keep SCL low
563
--                              isda := txd; -- set SDA
564
                                isda := Din;
565
 
566
                        when wr_b =>
567
                                iscl := '1';    -- set SCL high
568
--                              isda := txd; -- set SDA
569
                                isda := Din;
570
 
571
                        when wr_c =>
572
                                iscl := '1';    -- keep SCL high
573
--                              isda := txd; -- set SDA
574
                                isda := Din;
575
 
576
                        when wr_d =>
577
                                iscl := '0'; -- set SCL low
578
--                              isda := txd; -- set SDA
579
                                isda := Din;
580
 
581
                        -- read
582
                        when rd_a =>
583
                                iscl := '0'; -- keep SCL low
584
                                isda := '1'; -- tri-state SDA
585
 
586
                        when rd_b =>
587
                                iscl := '1'; -- set SCL high
588
                                isda := '1'; -- tri-state SDA
589
 
590
                        when rd_c =>
591
                                iscl := '1'; -- keep SCL high
592
                                isda := '1'; -- tri-state SDA
593
 
594
                        when rd_d =>
595
                                iscl := '0'; -- set SCL low
596
                                isda := '1'; -- tri-state SDA
597
                end case;
598
 
599
                -- generate registers
600
                if (nReset = '0') then
601
                        SCLo <= '1';
602
                        SDAo <= '1';
603
                elsif (clk'event and clk = '1') then
604
                        if (clk_en = '1') then
605
                                SCLo <= iscl;
606
                                SDAo <= isda;
607
                        end if;
608
                end if;
609
        end process output_decoder;
610
 
611
        SCL <= '0' when (SCLo = '0') else 'Z'; -- since SCL is externally pulled-up convert a '1' to a 'Z'(tri-state)
612
        SDA <= '0' when (SDAo = '0') else 'Z'; -- since SDA is externally pulled-up convert a '1' to a 'Z'(tri-state)
613
--      SCL <= SCLo;
614
--      SDA <= SDAo;
615
 
616
end architecture structural;
617
 
618
 
619
 
620
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.