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