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