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 75

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 47 rherveille
--  $Id: i2c_master_byte_ctrl.vhd,v 1.5 2004-02-18 11:41:48 rherveille Exp $
41 15 rherveille
--
42 47 rherveille
--  $Date: 2004-02-18 11:41:48 $
43
--  $Revision: 1.5 $
44 15 rherveille
--  $Author: rherveille $
45
--  $Locker:  $
46
--  $State: Exp $
47
--
48
-- Change History:
49
--               $Log: not supported by cvs2svn $
50 47 rherveille
--               Revision 1.4  2003/08/09 07:01:13  rherveille
51
--               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
52
--               Fixed a potential bug in the byte controller's host-acknowledge generation.
53
--
54 38 rherveille
--               Revision 1.3  2002/12/26 16:05:47  rherveille
55
--               Core is now a Multimaster I2C controller.
56
--
57 31 rherveille
--               Revision 1.2  2002/11/30 22:24:37  rherveille
58
--               Cleaned up code
59
--
60 27 rherveille
--               Revision 1.1  2001/11/05 12:02:33  rherveille
61
--               Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version.
62
--               Code updated, is now up-to-date to doc. rev.0.4.
63
--               Added headers.
64
--
65 15 rherveille
 
66
 
67
 
68
 
69
--
70
------------------------------------------
71
-- Byte controller section
72
------------------------------------------
73
--
74
library ieee;
75
use ieee.std_logic_1164.all;
76
use ieee.std_logic_arith.all;
77
 
78
entity i2c_master_byte_ctrl is
79
        port (
80
                clk    : in std_logic;
81
                rst    : in std_logic; -- synchronous active high reset (WISHBONE compatible)
82
                nReset : in std_logic;  -- asynchornous active low reset (FPGA compatible)
83
                ena    : in std_logic; -- core enable signal
84
 
85 27 rherveille
                clk_cnt : in unsigned(15 downto 0);      -- 4x SCL
86 15 rherveille
 
87
                -- input signals
88
                start,
89
                stop,
90
                read,
91
                write,
92
                ack_in : std_logic;
93
                din    : in std_logic_vector(7 downto 0);
94
 
95
                -- output signals
96 31 rherveille
                cmd_ack  : out std_logic; -- command done
97 15 rherveille
                ack_out  : out std_logic;
98 31 rherveille
                i2c_busy : out std_logic; -- arbitration lost
99
                i2c_al   : out std_logic; -- i2c bus busy
100 15 rherveille
                dout     : out std_logic_vector(7 downto 0);
101
 
102
                -- i2c lines
103
                scl_i   : in std_logic;  -- i2c clock line input
104
                scl_o   : out std_logic; -- i2c clock line output
105
                scl_oen : out std_logic; -- i2c clock line output enable, active low
106
                sda_i   : in std_logic;  -- i2c data line input
107
                sda_o   : out std_logic; -- i2c data line output
108
                sda_oen : out std_logic  -- i2c data line output enable, active low
109
        );
110
end entity i2c_master_byte_ctrl;
111
 
112
architecture structural of i2c_master_byte_ctrl is
113
        component i2c_master_bit_ctrl is
114 27 rherveille
        port (
115
                clk    : in std_logic;
116
                rst    : in std_logic;
117
                nReset : in std_logic;
118
                ena    : in std_logic;                          -- core enable signal
119 15 rherveille
 
120 27 rherveille
                clk_cnt : in unsigned(15 downto 0);              -- clock prescale value
121 15 rherveille
 
122 27 rherveille
                cmd     : in std_logic_vector(3 downto 0);
123 31 rherveille
                cmd_ack : out std_logic; -- command done
124
                busy    : out std_logic; -- i2c bus busy
125
                al      : out std_logic; -- arbitration lost
126 15 rherveille
 
127 27 rherveille
                din  : in std_logic;
128
                dout : out std_logic;
129 15 rherveille
 
130 27 rherveille
                -- i2c lines
131
                scl_i   : in std_logic;  -- i2c clock line input
132
                scl_o   : out std_logic; -- i2c clock line output
133
                scl_oen : out std_logic; -- i2c clock line output enable, active low
134
                sda_i   : in std_logic;  -- i2c data line input
135
                sda_o   : out std_logic; -- i2c data line output
136
                sda_oen : out std_logic  -- i2c data line output enable, active low
137
        );
138 15 rherveille
        end component i2c_master_bit_ctrl;
139
 
140
        -- commands for bit_controller block
141
        constant I2C_CMD_NOP    : std_logic_vector(3 downto 0) := "0000";
142
        constant I2C_CMD_START  : std_logic_vector(3 downto 0) := "0001";
143
        constant I2C_CMD_STOP    : std_logic_vector(3 downto 0) := "0010";
144
        constant I2C_CMD_READ    : std_logic_vector(3 downto 0) := "0100";
145
        constant I2C_CMD_WRITE  : std_logic_vector(3 downto 0) := "1000";
146
 
147
        -- signals for bit_controller
148
        signal core_cmd : std_logic_vector(3 downto 0);
149
        signal core_ack, core_txd, core_rxd : std_logic;
150 31 rherveille
        signal al : std_logic;
151 15 rherveille
 
152
        -- signals for shift register
153
        signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
154
        signal shift, ld : std_logic;
155
 
156
        -- signals for state machine
157
        signal go, host_ack : std_logic;
158
        signal dcnt : unsigned(2 downto 0); -- data counter
159
        signal cnt_done : std_logic;
160
 
161
begin
162
        -- hookup bit_controller
163 31 rherveille
        bit_ctrl: i2c_master_bit_ctrl port map(
164 15 rherveille
                clk     => clk,
165
                rst     => rst,
166
                nReset  => nReset,
167
                ena     => ena,
168
                clk_cnt => clk_cnt,
169
                cmd     => core_cmd,
170
                cmd_ack => core_ack,
171
                busy    => i2c_busy,
172 31 rherveille
                al      => al,
173 15 rherveille
                din     => core_txd,
174
                dout    => core_rxd,
175
                scl_i   => scl_i,
176
                scl_o   => scl_o,
177
                scl_oen => scl_oen,
178
                sda_i   => sda_i,
179
                sda_o   => sda_o,
180
                sda_oen => sda_oen
181
        );
182 31 rherveille
        i2c_al <= al;
183 15 rherveille
 
184
        -- generate host-command-acknowledge
185
        cmd_ack <= host_ack;
186 27 rherveille
 
187 15 rherveille
        -- generate go-signal
188
        go <= (read or write or stop) and not host_ack;
189
 
190
        -- assign Dout output to shift-register
191
        dout <= sr;
192
 
193
        -- generate shift register
194
        shift_register: process(clk, nReset)
195
        begin
196 27 rherveille
            if (nReset = '0') then
197
              sr <= (others => '0');
198
            elsif (clk'event and clk = '1') then
199
              if (rst = '1') then
200
                sr <= (others => '0');
201
              elsif (ld = '1') then
202
                sr <= din;
203
              elsif (shift = '1') then
204
                sr <= (sr(6 downto 0) & core_rxd);
205
              end if;
206
            end if;
207 15 rherveille
        end process shift_register;
208
 
209
        -- generate data-counter
210
        data_cnt: process(clk, nReset)
211
        begin
212 27 rherveille
            if (nReset = '0') then
213
              dcnt <= (others => '0');
214
            elsif (clk'event and clk = '1') then
215
              if (rst = '1') then
216
                dcnt <= (others => '0');
217
              elsif (ld = '1') then
218
                dcnt <= (others => '1');  -- load counter with 7
219
              elsif (shift = '1') then
220
                dcnt <= dcnt -1;
221
              end if;
222
            end if;
223 15 rherveille
        end process data_cnt;
224
 
225
        cnt_done <= '1' when (dcnt = 0) else '0';
226
 
227
        --
228
        -- state machine
229
        --
230
        statemachine : block
231 27 rherveille
            type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
232
            signal c_state : states;
233 15 rherveille
        begin
234 27 rherveille
            --
235
            -- command interpreter, translate complex commands into simpler I2C commands
236
            --
237
            nxt_state_decoder: process(clk, nReset)
238
            begin
239
                if (nReset = '0') then
240
                  core_cmd <= I2C_CMD_NOP;
241
                  core_txd <= '0';
242
                  shift    <= '0';
243
                  ld       <= '0';
244
                  host_ack <= '0';
245
                  c_state  <= st_idle;
246
                  ack_out  <= '0';
247
                elsif (clk'event and clk = '1') then
248 31 rherveille
                  if (rst = '1' or al = '1') then
249 27 rherveille
                    core_cmd <= I2C_CMD_NOP;
250
                    core_txd <= '0';
251
                    shift    <= '0';
252
                    ld       <= '0';
253
                    host_ack <= '0';
254
                    c_state  <= st_idle;
255
                    ack_out  <= '0';
256
                  else
257
                    -- initialy reset all signal
258
                    core_txd <= sr(7);
259
                    shift    <= '0';
260
                    ld       <= '0';
261
                    host_ack <= '0';
262 15 rherveille
 
263 27 rherveille
                    case c_state is
264
                      when st_idle =>
265
                         if (go = '1') then
266
                           if (start = '1') then
267
                             c_state  <= st_start;
268
                             core_cmd <= I2C_CMD_START;
269
                           elsif (read = '1') then
270
                             c_state  <= st_read;
271
                             core_cmd <= I2C_CMD_READ;
272
                           elsif (write = '1') then
273
                             c_state  <= st_write;
274
                             core_cmd <= I2C_CMD_WRITE;
275
                           else -- stop
276
                             c_state  <= st_stop;
277
                             core_cmd <= I2C_CMD_STOP;
278
                           end if;
279 15 rherveille
 
280 27 rherveille
                           ld <= '1';
281
                         end if;
282 15 rherveille
 
283 27 rherveille
                      when st_start =>
284
                         if (core_ack = '1') then
285
                           if (read = '1') then
286
                             c_state  <= st_read;
287
                             core_cmd <= I2C_CMD_READ;
288
                           else
289
                             c_state  <= st_write;
290
                             core_cmd <= I2C_CMD_WRITE;
291
                           end if;
292 15 rherveille
 
293 27 rherveille
                           ld <= '1';
294
                         end if;
295 15 rherveille
 
296 27 rherveille
                      when st_write =>
297
                         if (core_ack = '1') then
298
                           if (cnt_done = '1') then
299
                             c_state  <= st_ack;
300
                             core_cmd <= I2C_CMD_READ;
301
                           else
302
                             c_state  <= st_write;       -- stay in same state
303
                             core_cmd <= I2C_CMD_WRITE;  -- write next bit
304
                             shift    <= '1';
305
                           end if;
306
                         end if;
307 15 rherveille
 
308 27 rherveille
                      when st_read =>
309
                         if (core_ack = '1') then
310
                           if (cnt_done = '1') then
311
                             c_state  <= st_ack;
312
                             core_cmd <= I2C_CMD_WRITE;
313
                           else
314
                             c_state  <= st_read;      -- stay in same state
315
                             core_cmd <= I2C_CMD_READ; -- read next bit
316
                           end if;
317 15 rherveille
 
318 27 rherveille
                           shift    <= '1';
319
                           core_txd <= ack_in;
320
                         end if;
321 15 rherveille
 
322 27 rherveille
                      when st_ack =>
323
                         if (core_ack = '1') then
324
                           -- check for stop; Should a STOP command be generated ?
325
                           if (stop = '1') then
326
                             c_state  <= st_stop;
327
                             core_cmd <= I2C_CMD_STOP;
328
                           else
329
                             c_state  <= st_idle;
330
                             core_cmd <= I2C_CMD_NOP;
331 38 rherveille
 
332
                             -- generate command acknowledge signal
333
                             host_ack <= '1';
334 27 rherveille
                           end if;
335 15 rherveille
 
336 27 rherveille
                           -- assign ack_out output to core_rxd (contains last received bit)
337
                           ack_out  <= core_rxd;
338 15 rherveille
 
339 27 rherveille
                           core_txd <= '1';
340
                         else
341
                           core_txd <= ack_in;
342
                         end if;
343 15 rherveille
 
344 27 rherveille
                      when st_stop =>
345
                         if (core_ack = '1') then
346
                           c_state  <= st_idle;
347
                           core_cmd <= I2C_CMD_NOP;
348 38 rherveille
 
349
                           -- generate command acknowledge signal
350
                           host_ack <= '1';
351 27 rherveille
                         end if;
352 15 rherveille
 
353 27 rherveille
                      when others => -- illegal states
354
                         c_state  <= st_idle;
355
                         core_cmd <= I2C_CMD_NOP;
356
                         report ("Byte controller entered illegal state.");
357 15 rherveille
 
358 27 rherveille
                    end case;
359 15 rherveille
 
360 27 rherveille
                  end if;
361
                end if;
362
            end process nxt_state_decoder;
363 15 rherveille
 
364
        end block statemachine;
365
 
366
end architecture structural;
367
 

powered by: WebSVN 2.1.0

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