[1766] | 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 |
---|