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

Last change on this file was 1766, checked in by murphpo, 12 years ago
File size: 14.6 KB
Line 
1---------------------------------------------------------------------
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--  $Id: i2c_master_top.vhd,v 1.8 2009-01-20 10:38:45 rherveille Exp $
41--
42--  $Date: 2009-01-20 10:38:45 $
43--  $Revision: 1.8 $
44--  $Author: rherveille $
45--  $Locker:  $
46--  $State: Exp $
47--
48-- Change History:
49--               Revision 1.7  2004/03/14 10:17:03  rherveille
50--               Fixed simulation issue when writing to CR register
51--
52--               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--               Revision 1.5  2003/02/01 02:03:06  rherveille
57--               Fixed a few 'arbitration lost' bugs. VHDL version only.
58--
59--               Revision 1.4  2002/12/26 16:05:47  rherveille
60--               Core is now a Multimaster I2C controller.
61--
62--               Revision 1.3  2002/11/30 22:24:37  rherveille
63--               Cleaned up code
64--
65--               Revision 1.2  2001/11/10 10:52:44  rherveille
66--               Changed PRER reset value from 0x0000 to 0xffff, conform specs.
67--
68
69
70library ieee;
71use ieee.std_logic_1164.all;
72
73entity i2c_master_top is
74    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
91            -- 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    );
99end entity i2c_master_top;
100
101architecture structural of i2c_master_top is
102    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
109          clk_cnt : in unsigned(15 downto 0); -- 4x SCL
110
111          -- 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
119          -- 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
126          -- 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
136    -- 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
144    -- internal reset signal
145    signal rst_i : std_logic;
146
147    -- wishbone write access
148    signal wb_wacc : std_logic;
149
150    -- internal acknowledge signal
151    signal iack_o : std_logic;
152
153    -- done signal: command completed, clear command register
154    signal done : std_logic;
155
156    -- command register signals
157    signal sta, sto, rd, wr, ack, iack : std_logic;
158
159    signal core_en : std_logic;                      -- core enable signal
160    signal ien     : std_logic;                      -- interrupt enable signal
161
162    -- 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
169begin
170    -- generate internal reset signal
171    rst_i <= arst_i xor ARST_LVL;
172
173    -- 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
182    -- generate wishbone write access signal
183    wb_wacc <= wb_we_i and iack_o;
184
185    -- 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
196                -- 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
207
208    -- 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
228                      -- 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
239
240    -- 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
259                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
265    -- 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
273    -- decode control register
274    core_en <= ctr(7);
275    ien     <= ctr(6);
276
277    -- 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
304
305    -- 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
327                       -- 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
333        -- 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
348        -- 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
357end architecture structural;
Note: See TracBrowser for help on using the repository browser.