source: PlatformSupport/CustomPeripherals/pcores/w3_iic_eeprom_v1_00_b/opencores_src/rtl/verilog/i2c_master_top.v

Last change on this file was 1766, checked in by murphpo, 9 years ago
File size: 9.8 KB
Line 
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
78module 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
300endmodule
Note: See TracBrowser for help on using the repository browser.