source: PlatformSupport/CustomPeripherals/pcores/w3_iic_eeprom_v1_00_b/opencores_src/rtl/vhdl/i2c_master_byte_ctrl.vhd

Last change on this file was 1766, checked in by murphpo, 12 years ago
File size: 12.3 KB
Line 
1---------------------------------------------------------------------
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.5 2004-02-18 11:41:48 rherveille Exp $
41--
42--  $Date: 2004-02-18 11:41:48 $
43--  $Revision: 1.5 $
44--  $Author: rherveille $
45--  $Locker:  $
46--  $State: Exp $
47--
48-- Change History:
49--               $Log: not supported by cvs2svn $
50--               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--               Revision 1.3  2002/12/26 16:05:47  rherveille
55--               Core is now a Multimaster I2C controller.
56--
57--               Revision 1.2  2002/11/30 22:24:37  rherveille
58--               Cleaned up code
59--
60--               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
66
67
68
69--
70------------------------------------------
71-- Byte controller section
72------------------------------------------
73--
74library ieee;
75use ieee.std_logic_1164.all;
76use ieee.std_logic_arith.all;
77
78entity 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        clk_cnt : in unsigned(15 downto 0); -- 4x SCL
86
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        cmd_ack  : out std_logic; -- command done
97        ack_out  : out std_logic;
98        i2c_busy : out std_logic; -- arbitration lost
99        i2c_al   : out std_logic; -- i2c bus busy
100        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    );
110end entity i2c_master_byte_ctrl;
111
112architecture structural of i2c_master_byte_ctrl is
113    component i2c_master_bit_ctrl is
114    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
120        clk_cnt : in unsigned(15 downto 0);     -- clock prescale value
121
122        cmd     : in std_logic_vector(3 downto 0);
123        cmd_ack : out std_logic; -- command done
124        busy    : out std_logic; -- i2c bus busy
125        al      : out std_logic; -- arbitration lost
126
127        din  : in std_logic;
128        dout : out std_logic;
129
130        -- 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    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    signal al : std_logic;
151
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
161begin
162    -- hookup bit_controller
163    bit_ctrl: i2c_master_bit_ctrl port map(
164        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        al      => al,
173        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    i2c_al <= al;
183
184    -- generate host-command-acknowledge
185    cmd_ack <= host_ack;
186
187    -- 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        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    end process shift_register;
208
209    -- generate data-counter
210    data_cnt: process(clk, nReset)
211    begin
212        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    end process data_cnt;
224
225    cnt_done <= '1' when (dcnt = 0) else '0';
226
227    --
228    -- state machine
229    --
230    statemachine : block
231        type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
232        signal c_state : states;
233    begin
234        --
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              if (rst = '1' or al = '1') then
249                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
263                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
280                       ld <= '1';
281                     end if;
282
283                  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
293                       ld <= '1';
294                     end if;
295
296                  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
308                  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
318                       shift    <= '1';
319                       core_txd <= ack_in;
320                     end if;
321
322                  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
332                         -- generate command acknowledge signal
333                         host_ack <= '1';
334                       end if;
335
336                       -- assign ack_out output to core_rxd (contains last received bit)
337                       ack_out  <= core_rxd;
338
339                       core_txd <= '1';
340                     else
341                       core_txd <= ack_in;
342                     end if;
343
344                  when st_stop =>
345                     if (core_ack = '1') then
346                       c_state  <= st_idle;
347                       core_cmd <= I2C_CMD_NOP;
348
349                       -- generate command acknowledge signal
350                       host_ack <= '1';
351                     end if;
352
353                  when others => -- illegal states
354                     c_state  <= st_idle;
355                     core_cmd <= I2C_CMD_NOP;
356                     report ("Byte controller entered illegal state.");
357
358                end case;
359
360              end if;
361            end if;
362        end process nxt_state_decoder;
363
364    end block statemachine;
365
366end architecture structural;
367
Note: See TracBrowser for help on using the repository browser.