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

Subversion Repositories i2c

[/] [i2c/] [trunk/] [rtl/] [vhdl/] [i2c_master_top.vhd] - Blame information for rev 71

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 15 rherveille
---------------------------------------------------------------------
2
----                                                             ----
3
----  WISHBONE revB2 compl. I2C Master Core; top level           ----
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 65 rherveille
--  $Id: i2c_master_top.vhd,v 1.8 2009-01-20 10:38:45 rherveille Exp $
41 15 rherveille
--
42 65 rherveille
--  $Date: 2009-01-20 10:38:45 $
43
--  $Revision: 1.8 $
44 15 rherveille
--  $Author: rherveille $
45
--  $Locker:  $
46
--  $State: Exp $
47
--
48
-- Change History:
49 65 rherveille
--               Revision 1.7  2004/03/14 10:17:03  rherveille
50
--               Fixed simulation issue when writing to CR register
51
--
52 51 rherveille
--               Revision 1.6  2003/08/09 07:01:13  rherveille
53
--               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
54
--               Fixed a potential bug in the byte controller's host-acknowledge generation.
55
--
56 38 rherveille
--               Revision 1.5  2003/02/01 02:03:06  rherveille
57
--               Fixed a few 'arbitration lost' bugs. VHDL version only.
58
--
59 34 rherveille
--               Revision 1.4  2002/12/26 16:05:47  rherveille
60
--               Core is now a Multimaster I2C controller.
61
--
62 31 rherveille
--               Revision 1.3  2002/11/30 22:24:37  rherveille
63
--               Cleaned up code
64
--
65 27 rherveille
--               Revision 1.2  2001/11/10 10:52:44  rherveille
66
--               Changed PRER reset value from 0x0000 to 0xffff, conform specs.
67
--
68 15 rherveille
 
69
 
70
library ieee;
71
use ieee.std_logic_1164.all;
72
 
73
entity i2c_master_top is
74 71 rherveille
    generic(
75
            ARST_LVL : std_logic := '0'                   -- asynchronous reset level
76
    );
77
    port   (
78
            -- wishbone signals
79
            wb_clk_i      : in  std_logic;                    -- master clock input
80
            wb_rst_i      : in  std_logic := '0';             -- synchronous active high reset
81
            arst_i        : in  std_logic := not ARST_LVL;    -- asynchronous reset
82
            wb_adr_i      : in  std_logic_vector(2 downto 0); -- lower address bits
83
            wb_dat_i      : in  std_logic_vector(7 downto 0); -- Databus input
84
            wb_dat_o      : out std_logic_vector(7 downto 0); -- Databus output
85
            wb_we_i       : in  std_logic;                    -- Write enable input
86
            wb_stb_i      : in  std_logic;                    -- Strobe signals / core select signal
87
            wb_cyc_i      : in  std_logic;                    -- Valid bus cycle input
88
            wb_ack_o      : out std_logic;                    -- Bus cycle acknowledge output
89
            wb_inta_o     : out std_logic;                    -- interrupt request output signal
90 15 rherveille
 
91 71 rherveille
            -- i2c lines
92
            scl_pad_i     : in  std_logic;                    -- i2c clock line input
93
            scl_pad_o     : out std_logic;                    -- i2c clock line output
94
            scl_padoen_o  : out std_logic;                    -- i2c clock line output enable, active low
95
            sda_pad_i     : in  std_logic;                    -- i2c data line input
96
            sda_pad_o     : out std_logic;                    -- i2c data line output
97
            sda_padoen_o  : out std_logic                     -- i2c data line output enable, active low
98
    );
99 15 rherveille
end entity i2c_master_top;
100
 
101
architecture structural of i2c_master_top is
102 71 rherveille
    component i2c_master_byte_ctrl is
103
    port (
104
          clk    : in std_logic;
105
          rst    : in std_logic; -- synchronous active high reset (WISHBONE compatible)
106
          nReset : in std_logic; -- asynchornous active low reset (FPGA compatible)
107
          ena    : in std_logic; -- core enable signal
108 15 rherveille
 
109 71 rherveille
          clk_cnt : in unsigned(15 downto 0); -- 4x SCL
110 15 rherveille
 
111 71 rherveille
          -- input signals
112
          start,
113
          stop,
114
          read,
115
          write,
116
          ack_in : std_logic;
117
          din    : in std_logic_vector(7 downto 0);
118 15 rherveille
 
119 71 rherveille
          -- output signals
120
          cmd_ack  : out std_logic;
121
          ack_out  : out std_logic;
122
          i2c_busy : out std_logic;
123
          i2c_al   : out std_logic;
124
          dout     : out std_logic_vector(7 downto 0);
125 15 rherveille
 
126 71 rherveille
          -- i2c lines
127
          scl_i   : in std_logic;  -- i2c clock line input
128
          scl_o   : out std_logic; -- i2c clock line output
129
          scl_oen : out std_logic; -- i2c clock line output enable, active low
130
          sda_i   : in std_logic;  -- i2c data line input
131
          sda_o   : out std_logic; -- i2c data line output
132
          sda_oen : out std_logic  -- i2c data line output enable, active low
133
    );
134
    end component i2c_master_byte_ctrl;
135 15 rherveille
 
136 71 rherveille
    -- registers
137
    signal prer : unsigned(15 downto 0);             -- clock prescale register
138
    signal ctr  : std_logic_vector(7 downto 0);      -- control register
139
    signal txr  : std_logic_vector(7 downto 0);      -- transmit register
140
    signal rxr  : std_logic_vector(7 downto 0);      -- receive register
141
    signal cr   : std_logic_vector(7 downto 0);      -- command register
142
    signal sr   : std_logic_vector(7 downto 0);      -- status register
143 15 rherveille
 
144 71 rherveille
    -- internal reset signal
145
    signal rst_i : std_logic;
146 15 rherveille
 
147 71 rherveille
    -- wishbone write access
148
    signal wb_wacc : std_logic;
149 31 rherveille
 
150 71 rherveille
    -- internal acknowledge signal
151
    signal iack_o : std_logic;
152 27 rherveille
 
153 71 rherveille
    -- done signal: command completed, clear command register
154
    signal done : std_logic;
155 15 rherveille
 
156 71 rherveille
    -- command register signals
157
    signal sta, sto, rd, wr, ack, iack : std_logic;
158 15 rherveille
 
159 71 rherveille
    signal core_en : std_logic;                      -- core enable signal
160
    signal ien     : std_logic;                      -- interrupt enable signal
161 15 rherveille
 
162 71 rherveille
    -- status register signals
163
    signal irxack, rxack : std_logic;                -- received aknowledge from slave
164
    signal tip           : std_logic;                -- transfer in progress
165
    signal irq_flag      : std_logic;                -- interrupt pending flag
166
    signal i2c_busy      : std_logic;                -- i2c bus busy (start signal detected)
167
    signal i2c_al, al    : std_logic;                -- arbitration lost
168 15 rherveille
 
169
begin
170 71 rherveille
    -- generate internal reset signal
171
    rst_i <= arst_i xor ARST_LVL;
172 15 rherveille
 
173 71 rherveille
    -- generate acknowledge output signal
174
    gen_ack_o : process(wb_clk_i)
175
    begin
176
        if (wb_clk_i'event and wb_clk_i = '1') then
177
            iack_o <= wb_cyc_i and wb_stb_i and not iack_o;         -- because timing is always honored
178
        end if;
179
    end process gen_ack_o;
180
    wb_ack_o <= iack_o;
181 15 rherveille
 
182 71 rherveille
    -- generate wishbone write access signal
183
    wb_wacc <= wb_we_i and iack_o;
184 15 rherveille
 
185 71 rherveille
    -- assign wb_dat_o
186
    assign_dato : process(wb_clk_i)
187
    begin
188
        if (wb_clk_i'event and wb_clk_i = '1') then
189
            case wb_adr_i is
190
                when "000"  => wb_dat_o <= std_logic_vector(prer( 7 downto 0));
191
                when "001"  => wb_dat_o <= std_logic_vector(prer(15 downto 8));
192
                when "010"  => wb_dat_o <= ctr;
193
                when "011"  => wb_dat_o <= rxr; -- write is transmit register TxR
194
                when "100"  => wb_dat_o <= sr;  -- write is command register CR
195 15 rherveille
 
196 71 rherveille
                -- Debugging registers:
197
                -- These registers are not documented.
198
                -- Functionality could change in future releases
199
                when "101"  => wb_dat_o <= txr;
200
                when "110"  => wb_dat_o <= cr;
201
                when "111"  => wb_dat_o <= (others => '0');
202
                when others => wb_dat_o <= (others => 'X'); -- for simulation only
203
            end case;
204
        end if;
205
    end process assign_dato;
206 15 rherveille
 
207
 
208 71 rherveille
    -- generate registers (CR, SR see below)
209
    gen_regs: process(rst_i, wb_clk_i)
210
    begin
211
        if (rst_i = '0') then
212
            prer <= (others => '1');
213
            ctr  <= (others => '0');
214
            txr  <= (others => '0');
215
        elsif (wb_clk_i'event and wb_clk_i = '1') then
216
               if (wb_rst_i = '1') then
217
                   prer <= (others => '1');
218
                   ctr  <= (others => '0');
219
                   txr  <= (others => '0');
220
               elsif (wb_wacc = '1') then
221
                   case wb_adr_i is
222
                       when "000" => prer( 7 downto 0) <= unsigned(wb_dat_i);
223
                       when "001" => prer(15 downto 8) <= unsigned(wb_dat_i);
224
                       when "010" => ctr               <= wb_dat_i;
225
                       when "011" => txr               <= wb_dat_i;
226
                       when "100" => null; --write to CR, avoid executing the others clause
227 15 rherveille
 
228 71 rherveille
                      -- illegal cases, for simulation only
229
                      when others =>
230
                          report ("Illegal write address, setting all registers to unknown.");
231
                          prer <= (others => 'X');
232
                          ctr  <= (others => 'X');
233
                          txr  <= (others => 'X');
234
                   end case;
235
               end if;
236
        end if;
237
    end process gen_regs;
238 15 rherveille
 
239 31 rherveille
 
240 71 rherveille
    -- generate command register
241
    gen_cr: process(rst_i, wb_clk_i)
242
    begin
243
        if (rst_i = '0') then
244
            cr <= (others => '0');
245
        elsif (wb_clk_i'event and wb_clk_i = '1') then
246
            if (wb_rst_i = '1') then
247
                cr <= (others => '0');
248
            elsif (wb_wacc = '1') then
249
                if ( (core_en = '1') and (wb_adr_i = "100") ) then
250
                    -- only take new commands when i2c core enabled
251
                    -- pending commands are finished
252
                    cr <= wb_dat_i;
253
                end if;
254
            else
255
                if (done = '1' or i2c_al = '1') then
256
                    cr(7 downto 4) <= (others => '0'); -- clear command bits when command done or arbitration lost
257
                end if;
258 27 rherveille
 
259 71 rherveille
                cr(2 downto 1) <= (others => '0');   -- reserved bits, always '0'
260
                cr(0) <= '0';                        -- clear IRQ_ACK bit
261
            end if;
262
        end if;
263
    end process gen_cr;
264 15 rherveille
 
265 71 rherveille
    -- decode command register
266
    sta  <= cr(7);
267
    sto  <= cr(6);
268
    rd   <= cr(5);
269
    wr   <= cr(4);
270
    ack  <= cr(3);
271
    iack <= cr(0);
272 15 rherveille
 
273 71 rherveille
    -- decode control register
274
    core_en <= ctr(7);
275
    ien     <= ctr(6);
276 15 rherveille
 
277 71 rherveille
    -- hookup byte controller block
278
    byte_ctrl: i2c_master_byte_ctrl
279
    port map (
280
              clk      => wb_clk_i,
281
              rst      => wb_rst_i,
282
              nReset   => rst_i,
283
              ena      => core_en,
284
              clk_cnt  => prer,
285
              start    => sta,
286
              stop     => sto,
287
              read     => rd,
288
              write    => wr,
289
              ack_in   => ack,
290
              i2c_busy => i2c_busy,
291
              i2c_al   => i2c_al,
292
              din      => txr,
293
              cmd_ack  => done,
294
              ack_out  => irxack,
295
              dout     => rxr,
296
              scl_i    => scl_pad_i,
297
              scl_o    => scl_pad_o,
298
              scl_oen  => scl_padoen_o,
299
              sda_i    => sda_pad_i,
300
              sda_o    => sda_pad_o,
301
              sda_oen  => sda_padoen_o
302
    );
303 15 rherveille
 
304
 
305 71 rherveille
    -- status register block + interrupt request signal
306
    st_irq_block : block
307
    begin
308
        -- generate status register bits
309
        gen_sr_bits: process (wb_clk_i, rst_i)
310
        begin
311
            if (rst_i = '0') then
312
                al       <= '0';
313
                rxack    <= '0';
314
                tip      <= '0';
315
                irq_flag <= '0';
316
            elsif (wb_clk_i'event and wb_clk_i = '1') then
317
                   if (wb_rst_i = '1') then
318
                       al       <= '0';
319
                       rxack    <= '0';
320
                       tip      <= '0';
321
                       irq_flag <= '0';
322
                   else
323
                       al       <= i2c_al or (al and not sta);
324
                       rxack    <= irxack;
325
                       tip      <= (rd or wr);
326 15 rherveille
 
327 71 rherveille
                       -- interrupt request flag is always generated
328
                       irq_flag <= (done or i2c_al or irq_flag) and not iack;
329
                   end if;
330
            end if;
331
        end process gen_sr_bits;
332 15 rherveille
 
333 71 rherveille
        -- generate interrupt request signals
334
        gen_irq: process (wb_clk_i, rst_i)
335
        begin
336
            if (rst_i = '0') then
337
                wb_inta_o <= '0';
338
            elsif (wb_clk_i'event and wb_clk_i = '1') then
339
                   if (wb_rst_i = '1') then
340
                       wb_inta_o <= '0';
341
                   else
342
                       -- interrupt signal is only generated when IEN (interrupt enable bit) is set
343
                       wb_inta_o <= irq_flag and ien;
344
                   end if;
345
            end if;
346
        end process gen_irq;
347 15 rherveille
 
348 71 rherveille
        -- assign status register bits
349
        sr(7)          <= rxack;
350
        sr(6)          <= i2c_busy;
351
        sr(5)          <= al;
352
        sr(4 downto 2) <= (others => '0'); -- reserved
353
        sr(1)          <= tip;
354
        sr(0)          <= irq_flag;
355
    end block;
356
 
357 15 rherveille
end architecture structural;

powered by: WebSVN 2.1.0

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