URL
https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk
Subversion Repositories openrisc_me
[/] [openrisc/] [trunk/] [orpsocv2/] [rtl/] [verilog/] [i2c_master_slave/] [i2c_master_slave.v] - Rev 472
Go to most recent revision | Compare with Previous | Blame | View Log
///////////////////////////////////////////////////////////////////// //// //// //// WISHBONE revB.2 compliant I2C Master controller Top-level //// //// //// //// //// //// Author: Richard Herveille //// //// richard@asics.ws //// //// www.asics.ws //// //// //// //// Downloaded from: http://www.opencores.org/projects/i2c/ //// //// //// ///////////////////////////////////////////////////////////////////// //// //// //// Copyright (C) 2001 Richard Herveille //// //// richard@asics.ws //// //// //// //// This source file may be used and distributed without //// //// restriction provided that this copyright statement is not //// //// removed from the file and that any derivative work contains //// //// the original copyright notice and the associated disclaimer.//// //// //// //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// //// POSSIBILITY OF SUCH DAMAGE. //// //// //// ///////////////////////////////////////////////////////////////////// // CVS Log // // $Id: i2c_master_top.v,v 1.12 2009-01-19 20:29:26 rherveille Exp $ // // $Date: 2009-01-19 20:29:26 $ // $Revision: 1.12 $ // $Author: rherveille $ // $Locker: $ // $State: Exp $ // // Change History: // Revision 1.11 2005/02/27 09:26:24 rherveille // Fixed register overwrite issue. // Removed full_case pragma, replaced it by a default statement. // // Revision 1.10 2003/09/01 10:34:38 rherveille // Fix a blocking vs. non-blocking error in the wb_dat output mux. // // Revision 1.9 2003/01/09 16:44:45 rherveille // Fixed a bug in the Command Register declaration. // // Revision 1.8 2002/12/26 16:05:12 rherveille // Small code simplifications // // Revision 1.7 2002/12/26 15:02:32 rherveille // Core is now a Multimaster I2C controller // // Revision 1.6 2002/11/30 22:24:40 rherveille // Cleaned up code // // Revision 1.5 2001/11/10 10:52:55 rherveille // Changed PRER reset value from 0x0000 to 0xffff, conform specs. // // synopsys translate_off `include "timescale.v" // synopsys translate_on `include "i2c_master_slave_defines.v" //module i2c_master_top( module i2c_master_slave ( wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o, scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o ); // parameters parameter ARST_LVL = 1'b1; // asynchronous reset level parameter [6:0] DEFAULT_SLAVE_ADDR = 7'b111_1110; // // inputs & outputs // // wishbone signals input wb_clk_i; // master clock input input wb_rst_i; // synchronous active high reset input arst_i; // asynchronous reset input [2:0] wb_adr_i; // lower address bits input [7:0] wb_dat_i; // databus input output [7:0] wb_dat_o; // databus output input wb_we_i; // write enable input input wb_stb_i; // stobe/core select signal input wb_cyc_i; // valid bus cycle input output wb_ack_o; // bus cycle acknowledge output output wb_inta_o; // interrupt request signal output reg [7:0] wb_dat_o; reg wb_ack_o; reg wb_inta_o; // I2C signals // i2c clock line input scl_pad_i; // SCL-line input output scl_pad_o; // SCL-line output (always 1'b0) output scl_padoen_o; // SCL-line output enable (active low) // i2c data line input sda_pad_i; // SDA-line input output sda_pad_o; // SDA-line output (always 1'b0) output sda_padoen_o; // SDA-line output enable (active low) // // variable declarations // // registers reg [15:0] prer; // clock prescale register reg [ 7:0] ctr; // control register reg [ 7:0] txr; // transmit register wire [ 7:0] rxr; // receive register reg [ 7:0] cr; // command register wire [ 7:0] sr; // status register reg [ 6:0] sladr; // slave address register // done signal: command completed, clear command register wire done; wire slave_done; // core enable signal wire core_en; wire ien; wire slave_en; // status register signals wire irxack; reg rxack; // received aknowledge from slave reg tip; // transfer in progress reg irq_flag; // interrupt pending flag wire i2c_busy; // bus busy (start signal detected) wire i2c_al; // i2c bus arbitration lost reg al; // status register arbitration lost bit reg slave_mode; // // module body // wire slave_act; // generate internal reset wire rst_i = arst_i ^ ARST_LVL; // generate wishbone signals wire wb_wacc = wb_we_i & wb_ack_o; // generate acknowledge output signal ... always @(posedge wb_clk_i) // ... because timing is always honored. wb_ack_o <= wb_cyc_i & wb_stb_i & ~wb_ack_o; // assign DAT_O always @(posedge wb_clk_i) begin case (wb_adr_i) // synopsys parallel_case 3'b000: wb_dat_o <= prer[ 7:0]; 3'b001: wb_dat_o <= prer[15:8]; 3'b010: wb_dat_o <= ctr; 3'b011: wb_dat_o <= rxr; // write is transmit register (txr) 3'b100: wb_dat_o <= sr; // write is command register (cr) 3'b101: wb_dat_o <= txr; // Debug out of TXR 3'b110: wb_dat_o <= cr; // Debug out control reg 3'b111: wb_dat_o <= {1'b0,sladr}; // slave address register endcase end // generate registers always @(posedge wb_clk_i or negedge rst_i) if (!rst_i) begin prer <= 16'hffff; ctr <= 8'h0; txr <= 8'h0; sladr <= DEFAULT_SLAVE_ADDR; end else if (wb_rst_i) begin prer <= 16'hffff; ctr <= 8'h0; txr <= 8'h0; sladr <= DEFAULT_SLAVE_ADDR; end else if (wb_wacc) case (wb_adr_i) // synopsys parallel_case 3'b000 : prer [ 7:0] <= wb_dat_i; 3'b001 : prer [15:8] <= wb_dat_i; 3'b010 : ctr <= wb_dat_i; 3'b011 : txr <= wb_dat_i; 3'b111 : sladr <= wb_dat_i[6:0]; default: ; endcase // generate command register (special case) always @(posedge wb_clk_i or negedge rst_i) if (!rst_i) cr <= 8'h0; else if (wb_rst_i) cr <= 8'h0; else if (wb_wacc) begin if (core_en & (wb_adr_i == 3'b100) ) cr <= wb_dat_i; end else begin cr[1] <= 1'b0; if (done | i2c_al) cr[7:4] <= 4'h0; // clear command bits when done // or when aribitration lost cr[2] <= 1'b0; // reserved bits cr[0] <= 1'b0; // clear IRQ_ACK bit end // decode command register wire sta = cr[7]; wire sto = cr[6]; wire rd = cr[5]; wire wr = cr[4]; wire ack = cr[3]; wire sl_cont = cr[1]; wire iack = cr[0]; // decode control register assign core_en = ctr[7]; assign ien = ctr[6]; assign slave_en = ctr[5]; // hookup byte controller block i2c_master_byte_ctrl byte_controller ( .clk ( wb_clk_i ), .my_addr ( sladr ), .rst ( wb_rst_i ), .nReset ( rst_i ), .ena ( core_en ), .clk_cnt ( prer ), .start ( sta ), .stop ( sto ), .read ( rd ), .write ( wr ), .ack_in ( ack ), .din ( txr ), .cmd_ack ( done ), .ack_out ( irxack ), .dout ( rxr ), .i2c_busy ( i2c_busy ), .i2c_al ( i2c_al ), .scl_i ( scl_pad_i ), .scl_o ( scl_pad_o ), .scl_oen ( scl_padoen_o ), .sda_i ( sda_pad_i ), .sda_o ( sda_pad_o ), .sda_oen ( sda_padoen_o ), .sl_cont ( sl_cont ), .slave_en ( slave_en ), .slave_dat_req (slave_dat_req), .slave_dat_avail (slave_dat_avail), .slave_act (slave_act), .slave_cmd_ack (slave_done) ); // status register block + interrupt request signal always @(posedge wb_clk_i or negedge rst_i) if (!rst_i) begin al <= 1'b0; rxack <= 1'b0; tip <= 1'b0; irq_flag <= 1'b0; slave_mode <= 1'b0; end else if (wb_rst_i) begin al <= 1'b0; rxack <= 1'b0; tip <= 1'b0; irq_flag <= 1'b0; slave_mode <= 1'b0; end else begin al <= i2c_al | (al & ~sta); rxack <= irxack; tip <= (rd | wr); // interrupt request flag is always generated irq_flag <= (done | slave_done| i2c_al | slave_dat_req | slave_dat_avail | irq_flag) & ~iack; if (done) slave_mode <= slave_act; end // generate interrupt request signals always @(posedge wb_clk_i or negedge rst_i) if (!rst_i) wb_inta_o <= 1'b0; else if (wb_rst_i) wb_inta_o <= 1'b0; else // interrupt signal is only generated when IEN (interrupt enable bit // is set) wb_inta_o <= irq_flag && ien; // assign status register bits assign sr[7] = rxack; assign sr[6] = i2c_busy; assign sr[5] = al; assign sr[4] = slave_mode; // reserved assign sr[3] = slave_dat_avail; assign sr[2] = slave_dat_req; assign sr[1] = tip; assign sr[0] = irq_flag; endmodule
Go to most recent revision | Compare with Previous | Blame | View Log