1/////////////////////////////////////////////////////////////////////
2////                                                             ////
3////  WISHBONE revB.2 compliant I2C Master controller 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) 2001 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.v,v 1.11 2005/02/27 09:26:24 rherveille Exp $
41//
42//  $Date: 2005/02/27 09:26:24 $
43//  $Revision: 1.11 $
44//  $Author: rherveille $
45//  $Locker:  $
46//  $State: Exp $
47//
48// Change History:
49//               $Log: i2c_master_top.v,v $
50//               Revision 1.11  2005/02/27 09:26:24  rherveille
51//               Fixed register overwrite issue.
52//               Removed full_case pragma, replaced it by a default statement.
53//
54//               Revision 1.10  2003/09/01 10:34:38  rherveille
55//               Fix a blocking vs. non-blocking error in the wb_dat output mux.
56//
57//               Revision 1.9  2003/01/09 16:44:45  rherveille
58//               Fixed a bug in the Command Register declaration.
59//
60//               Revision 1.8  2002/12/26 16:05:12  rherveille
61//               Small code simplifications
62//
63//               Revision 1.7  2002/12/26 15:02:32  rherveille
64//               Core is now a Multimaster I2C controller
65//
66//               Revision 1.6  2002/11/30 22:24:40  rherveille
67//               Cleaned up code
68//
69//               Revision 1.5  2001/11/10 10:52:55  rherveille
70//               Changed PRER reset value from 0x0000 to 0xffff, conform specs.
71//
72
73// synopsys translate_off
74`include "timescale.v"
75// synopsys translate_on
76
77`include "i2c_master_defines.v"
78
79module i2c_master_top(
80	wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o,
81	wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o,
82	scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o );
83
84	// parameters
85	parameter ARST_LVL = 1'b0; // asynchronous reset level
86
87	//
88	// inputs & outputs
89	//
90
91	// wishbone signals
92	input        wb_clk_i;     // master clock input
93	input        wb_rst_i;     // synchronous active high reset
94	input        arst_i;       // asynchronous reset
95	input  [2:0] wb_adr_i;     // lower address bits
96	input  [7:0] wb_dat_i;     // databus input
97	output [7:0] wb_dat_o;     // databus output
98	input        wb_we_i;      // write enable input
99	input        wb_stb_i;     // stobe/core select signal
100	input        wb_cyc_i;     // valid bus cycle input
101	output       wb_ack_o;     // bus cycle acknowledge output
102	output       wb_inta_o;    // interrupt request signal output
103
104	reg [7:0] wb_dat_o;
105	reg wb_ack_o;
106	reg wb_inta_o;
107
108	// I2C signals
109	// i2c clock line
110	input  scl_pad_i;       // SCL-line input
111	output scl_pad_o;       // SCL-line output (always 1'b0)
112	output scl_padoen_o;    // SCL-line output enable (active low)
113
114	// i2c data line
115	input  sda_pad_i;       // SDA-line input
116	output sda_pad_o;       // SDA-line output (always 1'b0)
117	output sda_padoen_o;    // SDA-line output enable (active low)
118
119
120	//
121	// variable declarations
122	//
123
124	// registers
125	reg  [15:0] prer; // clock prescale register
126	reg  [ 7:0] ctr;  // control register
127	reg  [ 7:0] txr;  // transmit register
128	wire [ 7:0] rxr;  // receive register
129	reg  [ 7:0] cr;   // command register
130	wire [ 7:0] sr;   // status register
131
132	// done signal: command completed, clear command register
133	wire done;
134
135	// core enable signal
136	wire core_en;
137	wire ien;
138
139	// status register signals
140	wire irxack;
141	reg  rxack;       // received aknowledge from slave
142	reg  tip;         // transfer in progress
143	reg  irq_flag;    // interrupt pending flag
144	wire i2c_busy;    // bus busy (start signal detected)
145	wire i2c_al;      // i2c bus arbitration lost
146	reg  al;          // status register arbitration lost bit
147
148	//
149	// module body
150	//
151
152	// generate internal reset
153	wire rst_i = arst_i ^ ARST_LVL;
154
155	// generate wishbone signals
156	wire wb_wacc = wb_cyc_i & wb_stb_i & wb_we_i;
157
158	// generate acknowledge output signal
159	always @(posedge wb_clk_i)
160	  wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored
161
162	// assign DAT_O
163	always @(posedge wb_clk_i)
164	begin
165	  case (wb_adr_i) // synopsis parallel_case
166	    3'b000: wb_dat_o <= #1 prer[ 7:0];
167	    3'b001: wb_dat_o <= #1 prer[15:8];
168	    3'b010: wb_dat_o <= #1 ctr;
169	    3'b011: wb_dat_o <= #1 rxr; // write is transmit register (txr)
170	    3'b100: wb_dat_o <= #1 sr;  // write is command register (cr)
171	    3'b101: wb_dat_o <= #1 txr;
172	    3'b110: wb_dat_o <= #1 cr;
173	    3'b111: wb_dat_o <= #1 0;   // reserved
174	  endcase
175	end
176
177	// generate registers
178	always @(posedge wb_clk_i or negedge rst_i)
179	  if (!rst_i)
180	    begin
181	        prer <= #1 16'hffff;
182	        ctr  <= #1  8'h0;
183	        txr  <= #1  8'h0;
184	    end
185	  else if (wb_rst_i)
186	    begin
187	        prer <= #1 16'hffff;
188	        ctr  <= #1  8'h0;
189	        txr  <= #1  8'h0;
190	    end
191	  else
192	    if (wb_wacc)
193	      case (wb_adr_i) // synopsis parallel_case
194	         3'b000 : prer [ 7:0] <= #1 wb_dat_i;
195	         3'b001 : prer [15:8] <= #1 wb_dat_i;
196	         3'b010 : ctr         <= #1 wb_dat_i;
197	         3'b011 : txr         <= #1 wb_dat_i;
198	         default: ;
199	      endcase
200
201	// generate command register (special case)
202	always @(posedge wb_clk_i or negedge rst_i)
203	  if (~rst_i)
204	    cr <= #1 8'h0;
205	  else if (wb_rst_i)
206	    cr <= #1 8'h0;
207	  else if (wb_wacc)
208	    begin
209	        if (core_en & (wb_adr_i == 3'b100) )
210	          cr <= #1 wb_dat_i;
211	    end
212	  else
213	    begin
214	        if (done | i2c_al)
215	          cr[7:4] <= #1 4'h0;           // clear command bits when done
216	                                        // or when aribitration lost
217	        cr[2:1] <= #1 2'b0;             // reserved bits
218	        cr[0]   <= #1 2'b0;             // clear IRQ_ACK bit
219	    end
220
221
222	// decode command register
223	wire sta  = cr[7];
224	wire sto  = cr[6];
225	wire rd   = cr[5];
226	wire wr   = cr[4];
227	wire ack  = cr[3];
228	wire iack = cr[0];
229
230	// decode control register
231	assign core_en = ctr[7];
232	assign ien = ctr[6];
233
234	// hookup byte controller block
235	i2c_master_byte_ctrl byte_controller (
236		.clk      ( wb_clk_i     ),
237		.rst      ( wb_rst_i     ),
238		.nReset   ( rst_i        ),
239		.ena      ( core_en      ),
240		.clk_cnt  ( prer         ),
241		.start    ( sta          ),
242		.stop     ( sto          ),
243		.read     ( rd           ),
244		.write    ( wr           ),
245		.ack_in   ( ack          ),
246		.din      ( txr          ),
247		.cmd_ack  ( done         ),
248		.ack_out  ( irxack       ),
249		.dout     ( rxr          ),
250		.i2c_busy ( i2c_busy     ),
251		.i2c_al   ( i2c_al       ),
252		.scl_i    ( scl_pad_i    ),
253		.scl_o    ( scl_pad_o    ),
254		.scl_oen  ( scl_padoen_o ),
255		.sda_i    ( sda_pad_i    ),
256		.sda_o    ( sda_pad_o    ),
257		.sda_oen  ( sda_padoen_o )
258	);
259
260	// status register block + interrupt request signal
261	always @(posedge wb_clk_i or negedge rst_i)
262	  if (!rst_i)
263	    begin
264	        al       <= #1 1'b0;
265	        rxack    <= #1 1'b0;
266	        tip      <= #1 1'b0;
267	        irq_flag <= #1 1'b0;
268	    end
269	  else if (wb_rst_i)
270	    begin
271	        al       <= #1 1'b0;
272	        rxack    <= #1 1'b0;
273	        tip      <= #1 1'b0;
274	        irq_flag <= #1 1'b0;
275	    end
276	  else
277	    begin
278	        al       <= #1 i2c_al | (al & ~sta);
279	        rxack    <= #1 irxack;
280	        tip      <= #1 (rd | wr);
281	        irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated
282	    end
283
284	// generate interrupt request signals
285	always @(posedge wb_clk_i or negedge rst_i)
286	  if (!rst_i)
287	    wb_inta_o <= #1 1'b0;
288	  else if (wb_rst_i)
289	    wb_inta_o <= #1 1'b0;
290	  else
291	    wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set)
292
293	// assign status register bits
294	assign sr[7]   = rxack;
295	assign sr[6]   = i2c_busy;
296	assign sr[5]   = al;
297	assign sr[4:2] = 3'h0; // reserved
298	assign sr[1]   = tip;
299	assign sr[0]   = irq_flag;
300
301endmodule
302