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 31

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

powered by: WebSVN 2.1.0

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