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

Subversion Repositories i2c

[/] [i2c/] [trunk/] [rtl/] [vhdl/] [i2c_master_byte_ctrl.vhd] - Blame information for rev 15

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

Line No. Rev Author Line
1 15 rherveille
---------------------------------------------------------------------
2
----                                                             ----
3
----  WISHBONE revB2 compl. I2C Master Core; byte-controller     ----
4
----                                                             ----
5
----                                                             ----
6
----  Author: Richard Herveille                                  ----
7
----          richard@asics.ws                                   ----
8
----          www.asics.ws                                       ----
9
----                                                             ----
10
----  Downloaded from: http://www.opencores.org/projects/i2c/    ----
11
----                                                             ----
12
---------------------------------------------------------------------
13
----                                                             ----
14
---- Copyright (C) 2000 Richard Herveille                        ----
15
----                    richard@asics.ws                         ----
16
----                                                             ----
17
---- This source file may be used and distributed without        ----
18
---- restriction provided that this copyright statement is not   ----
19
---- removed from the file and that any derivative work contains ----
20
---- the original copyright notice and the associated disclaimer.----
21
----                                                             ----
22
----     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ----
23
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ----
24
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ----
25
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ----
26
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ----
27
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ----
28
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ----
29
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ----
30
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ----
31
---- LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ----
32
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ----
33
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ----
34
---- POSSIBILITY OF SUCH DAMAGE.                                 ----
35
----                                                             ----
36
---------------------------------------------------------------------
37
 
38
--  CVS Log
39
--
40
--  $Id: i2c_master_byte_ctrl.vhd,v 1.1 2001-11-05 12:02:33 rherveille Exp $
41
--
42
--  $Date: 2001-11-05 12:02:33 $
43
--  $Revision: 1.1 $
44
--  $Author: rherveille $
45
--  $Locker:  $
46
--  $State: Exp $
47
--
48
-- Change History:
49
--               $Log: not supported by cvs2svn $
50
 
51
 
52
 
53
 
54
--
55
------------------------------------------
56
-- Byte controller section
57
------------------------------------------
58
--
59
library ieee;
60
use ieee.std_logic_1164.all;
61
use ieee.std_logic_arith.all;
62
 
63
entity i2c_master_byte_ctrl is
64
        generic(
65
                Tcq : time := 1 ns
66
        );
67
        port (
68
                clk    : in std_logic;
69
                rst    : in std_logic; -- synchronous active high reset (WISHBONE compatible)
70
                nReset : in std_logic;  -- asynchornous active low reset (FPGA compatible)
71
                ena    : in std_logic; -- core enable signal
72
 
73
                clk_cnt : in unsigned(15 downto 0);      -- 4x SCL 
74
 
75
                -- input signals
76
                start,
77
                stop,
78
                read,
79
                write,
80
                ack_in : std_logic;
81
                din    : in std_logic_vector(7 downto 0);
82
 
83
                -- output signals
84
                cmd_ack  : out std_logic;
85
                ack_out  : out std_logic;
86
                i2c_busy : out std_logic;
87
                dout     : out std_logic_vector(7 downto 0);
88
 
89
                -- i2c lines
90
                scl_i   : in std_logic;  -- i2c clock line input
91
                scl_o   : out std_logic; -- i2c clock line output
92
                scl_oen : out std_logic; -- i2c clock line output enable, active low
93
                sda_i   : in std_logic;  -- i2c data line input
94
                sda_o   : out std_logic; -- i2c data line output
95
                sda_oen : out std_logic  -- i2c data line output enable, active low
96
        );
97
end entity i2c_master_byte_ctrl;
98
 
99
architecture structural of i2c_master_byte_ctrl is
100
        component i2c_master_bit_ctrl is
101
                generic(
102
                        Tcq : time := Tcq
103
                );
104
                port (
105
                        clk    : in std_logic;
106
                        rst    : in std_logic;
107
                        nReset : in std_logic;
108
                        ena    : in std_logic;                          -- core enable signal
109
 
110
                        clk_cnt : in unsigned(15 downto 0);              -- clock prescale value
111
 
112
                        cmd     : in std_logic_vector(3 downto 0);
113
                        cmd_ack : out std_logic;
114
                        busy    : out std_logic;
115
 
116
                        din  : in std_logic;
117
                        dout : out std_logic;
118
 
119
                        -- i2c lines
120
                        scl_i   : in std_logic;  -- i2c clock line input
121
                        scl_o   : out std_logic; -- i2c clock line output
122
                        scl_oen : out std_logic; -- i2c clock line output enable, active low
123
                        sda_i   : in std_logic;  -- i2c data line input
124
                        sda_o   : out std_logic; -- i2c data line output
125
                        sda_oen : out std_logic  -- i2c data line output enable, active low
126
                );
127
        end component i2c_master_bit_ctrl;
128
 
129
        -- commands for bit_controller block
130
        constant I2C_CMD_NOP    : std_logic_vector(3 downto 0) := "0000";
131
        constant I2C_CMD_START  : std_logic_vector(3 downto 0) := "0001";
132
        constant I2C_CMD_STOP    : std_logic_vector(3 downto 0) := "0010";
133
        constant I2C_CMD_READ    : std_logic_vector(3 downto 0) := "0100";
134
        constant I2C_CMD_WRITE  : std_logic_vector(3 downto 0) := "1000";
135
 
136
        -- signals for bit_controller
137
        signal core_cmd : std_logic_vector(3 downto 0);
138
        signal core_ack, core_txd, core_rxd : std_logic;
139
 
140
        -- signals for shift register
141
        signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
142
        signal shift, ld : std_logic;
143
 
144
        -- signals for state machine
145
        signal go, host_ack : std_logic;
146
        signal dcnt : unsigned(2 downto 0); -- data counter
147
        signal cnt_done : std_logic;
148
 
149
begin
150
        -- hookup bit_controller
151
        u1: i2c_master_bit_ctrl port map(
152
                clk     => clk,
153
                rst     => rst,
154
                nReset  => nReset,
155
                ena     => ena,
156
                clk_cnt => clk_cnt,
157
                cmd     => core_cmd,
158
                cmd_ack => core_ack,
159
                busy    => i2c_busy,
160
                din     => core_txd,
161
                dout    => core_rxd,
162
                scl_i   => scl_i,
163
                scl_o   => scl_o,
164
                scl_oen => scl_oen,
165
                sda_i   => sda_i,
166
                sda_o   => sda_o,
167
                sda_oen => sda_oen
168
        );
169
 
170
        -- generate host-command-acknowledge
171
        cmd_ack <= host_ack;
172
 
173
        -- generate go-signal
174
        go <= (read or write or stop) and not host_ack;
175
 
176
        -- assign Dout output to shift-register
177
        dout <= sr;
178
 
179
        -- generate shift register
180
        shift_register: process(clk, nReset)
181
        begin
182
                if (nReset = '0') then
183
                        sr <= (others => '0') after Tcq;
184
                elsif (clk'event and clk = '1') then
185
                        if (rst = '1') then
186
                                sr <= (others => '0') after Tcq;
187
                        elsif (ld = '1') then
188
                                sr <= din after Tcq;
189
                        elsif (shift = '1') then
190
                                sr <= (sr(6 downto 0) & core_rxd) after Tcq;
191
                        end if;
192
                end if;
193
        end process shift_register;
194
 
195
        -- generate data-counter
196
        data_cnt: process(clk, nReset)
197
        begin
198
                if (nReset = '0') then
199
                        dcnt <= (others => '0') after Tcq;
200
                elsif (clk'event and clk = '1') then
201
                        if (rst = '1') then
202
                                dcnt <= (others => '0') after Tcq;
203
                        elsif (ld = '1') then
204
                                dcnt <= (others => '1') after Tcq; -- load counter with 7
205
                        elsif (shift = '1') then
206
                                dcnt <= dcnt -1 after Tcq;
207
                        end if;
208
                end if;
209
        end process data_cnt;
210
 
211
        cnt_done <= '1' when (dcnt = 0) else '0';
212
 
213
        --
214
        -- state machine
215
        --
216
        statemachine : block
217
                type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
218
                signal c_state : states;
219
        begin
220
                --
221
                -- command interpreter, translate complex commands into simpler I2C commands
222
                --
223
                nxt_state_decoder: process(clk, nReset)
224
                begin
225
                        if (nReset = '0') then
226
                                core_cmd <= I2C_CMD_NOP after Tcq;
227
                                core_txd <= '0' after Tcq;
228
 
229
                                shift    <= '0' after Tcq;
230
                                ld       <= '0' after Tcq;
231
 
232
                                host_ack <= '0' after Tcq;
233
                                c_state  <= st_idle after Tcq;
234
 
235
                                ack_out  <= '0' after Tcq;
236
                        elsif (clk'event and clk = '1') then
237
                                if (rst = '1') then
238
                                        core_cmd <= I2C_CMD_NOP after Tcq;
239
                                        core_txd <= '0' after Tcq;
240
 
241
                                        shift    <= '0' after Tcq;
242
                                        ld       <= '0' after Tcq;
243
 
244
                                        host_ack <= '0' after Tcq;
245
                                        c_state  <= st_idle after Tcq;
246
 
247
                                        ack_out  <= '0' after Tcq;
248
                                else
249
                                        -- initialy reset all signal
250
                                        core_txd <= sr(7) after Tcq;
251
 
252
                                        shift    <= '0' after Tcq;
253
                                        ld       <= '0' after Tcq;
254
 
255
                                        host_ack <= '0' after Tcq;
256
 
257
                                        case c_state is
258
                                                when st_idle =>
259
                                                        if (go = '1') then
260
                                                                if (start = '1') then
261
                                                                        c_state  <= st_start after Tcq;
262
                                                                        core_cmd <= I2C_CMD_START after Tcq;
263
                                                                elsif (read = '1') then
264
                                                                        c_state  <= st_read after Tcq;
265
                                                                        core_cmd <= I2C_CMD_READ after Tcq;
266
                                                                elsif (write = '1') then
267
                                                                        c_state  <= st_write after Tcq;
268
                                                                        core_cmd <= I2C_CMD_WRITE after Tcq;
269
                                                                else -- stop
270
                                                                        c_state  <= st_stop after Tcq;
271
                                                                        core_cmd <= I2C_CMD_STOP after Tcq;
272
 
273
                                                                        host_ack <= '1' after Tcq; -- generate acknowledge signal
274
                                                                end if;
275
 
276
                                                                ld <= '1' after Tcq;
277
                                                        end if;
278
 
279
                                                when st_start =>
280
                                                        if (core_ack = '1') then
281
                                                                if (read = '1') then
282
                                                                        c_state  <= st_read after Tcq;
283
                                                                        core_cmd <= I2C_CMD_READ after Tcq;
284
                                                                else
285
                                                                        c_state  <= st_write after Tcq;
286
                                                                        core_cmd <= I2C_CMD_WRITE after Tcq;
287
                                                                end if;
288
 
289
                                                                ld <= '1' after Tcq;
290
                                                        end if;
291
 
292
                                                when st_write =>
293
                                                        if (core_ack = '1') then
294
                                                                if (cnt_done = '1') then
295
                                                                        c_state  <= st_ack after Tcq;
296
                                                                        core_cmd <= I2C_CMD_READ after Tcq;
297
                                                                else
298
                                                                        c_state  <= st_write after Tcq;       -- stay in same state
299
                                                                        core_cmd <= I2C_CMD_WRITE after Tcq;  -- write next bit
300
 
301
                                                                        shift    <= '1' after Tcq;
302
                                                                end if;
303
                                                        end if;
304
 
305
                                                when st_read =>
306
                                                        if (core_ack = '1') then
307
                                                                if (cnt_done = '1') then
308
                                                                        c_state  <= st_ack after Tcq;
309
                                                                        core_cmd <= I2C_CMD_WRITE after Tcq;
310
                                                                else
311
                                                                        c_state  <= st_read after Tcq;      -- stay in same state
312
                                                                        core_cmd <= I2C_CMD_READ after Tcq; -- read next bit
313
                                                                end if;
314
 
315
                                                                shift    <= '1' after Tcq;
316
                                                                core_txd <= ack_in after Tcq;
317
                                                        end if;
318
 
319
                                                when st_ack =>
320
                                                        if (core_ack = '1') then
321
                                                                -- check for stop; Should a STOP command be generated ?
322
                                                                if (stop = '1') then
323
                                                                        c_state  <= st_stop after Tcq;
324
                                                                        core_cmd <= I2C_CMD_STOP after Tcq;
325
                                                                else
326
                                                                        c_state  <= st_idle after Tcq;
327
                                                                        core_cmd <= I2C_CMD_NOP after Tcq;
328
                                                                end if;
329
 
330
                                                                -- assign ack_out output to core_rxd (contains last received bit)
331
                                                                ack_out  <= core_rxd after Tcq;
332
 
333
                                                                -- generate command acknowledge signal
334
                                                                host_ack <= '1' after Tcq;
335
 
336
                                                                core_txd <= '1' after Tcq;
337
                                                        else
338
                                                                core_txd <= ack_in after Tcq;
339
                                                        end if;
340
 
341
                                                when st_stop =>
342
                                                        if (core_ack = '1') then
343
                                                                c_state  <= st_idle after Tcq;
344
                                                                core_cmd <= I2C_CMD_NOP after Tcq;
345
                                                        end if;
346
 
347
                                                when others => -- illegal states
348
                                                        c_state  <= st_idle after Tcq;
349
                                                        core_cmd <= I2C_CMD_NOP after Tcq;
350
                                                        report ("Byte controller entered illegal state.");
351
 
352
                                        end case;
353
 
354
                                end if;
355
                        end if;
356
                end process nxt_state_decoder;
357
 
358
        end block statemachine;
359
 
360
end architecture structural;
361
 

powered by: WebSVN 2.1.0

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