www.pudn.com > i2cjiekouchengxu.rar > i2c_master_top.v


///////////////////////////////////////////////////////////////////// 
////                                                             //// 
////  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.11 2005/02/27 09:26:24 rherveille Exp $ 
// 
//  $Date: 2005/02/27 09:26:24 $ 
//  $Revision: 1.11 $ 
//  $Author: rherveille $ 
//  $Locker:  $ 
//  $State: Exp $ 
// 
// Change History: 
//               $Log: i2c_master_top.v,v $ 
//               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 "../rtl/verilog/timescale.v" 
// synopsys translate_on 
 
`include "../rtl/verilog/i2c_master_defines.v" 
 
module i2c_master_top( 
	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,test_o, 
	scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o ); 
 
	// parameters 
	parameter ARST_LVL = 1'b0; // asynchronous reset level 
 
	// 
	// 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 
	 
    output       test_o; 
    assign       test_o=1'bz; 
 
	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 
 
	// done signal: command completed, clear command register 
	wire done; 
 
	// core enable signal 
	wire core_en; 
	wire ien; 
 
	// 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 
 
	// 
	// module body 
	// 
 
	// generate internal reset 
	wire rst_i = arst_i ^ ARST_LVL; 
 
	// generate wishbone signals 
	wire wb_wacc = wb_cyc_i & wb_stb_i & wb_we_i; 
 
	// generate acknowledge output signal 
	always @(posedge wb_clk_i) 
	  wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored 
 
	// assign DAT_O 
	always @(posedge wb_clk_i) 
	begin 
	  case (wb_adr_i) // synopsis parallel_case 
	    3'b000: wb_dat_o <= #1 prer[ 7:0]; 
	    3'b001: wb_dat_o <= #1 prer[15:8]; 
	    3'b010: wb_dat_o <= #1 ctr; 
	    3'b011: wb_dat_o <= #1 rxr; // write is transmit register (txr) 
	    3'b100: wb_dat_o <= #1 sr;  // write is command register (cr) 
	    3'b101: wb_dat_o <= #1 txr; 
	    3'b110: wb_dat_o <= #1 cr; 
	    3'b111: wb_dat_o <= #1 0;   // reserved 
	  endcase 
	end 
 
	// generate registers 
	always @(posedge wb_clk_i or negedge rst_i) 
	  if (!rst_i) 
	    begin 
	        prer <= #1 16'hffff; 
	        ctr  <= #1  8'h0; 
	        txr  <= #1  8'h0; 
	    end 
	  else if (wb_rst_i) 
	    begin 
	        prer <= #1 16'hffff; 
	        ctr  <= #1  8'h0; 
	        txr  <= #1  8'h0; 
	    end 
	  else 
	    if (wb_wacc) 
	      case (wb_adr_i) // synopsis parallel_case 
	         3'b000 : prer [ 7:0] <= #1 wb_dat_i; 
	         3'b001 : prer [15:8] <= #1 wb_dat_i; 
	         3'b010 : ctr         <= #1 wb_dat_i; 
	         3'b011 : txr         <= #1 wb_dat_i; 
	         default: ; 
	      endcase 
 
	// generate command register (special case) 
	always @(posedge wb_clk_i or negedge rst_i) 
	  if (~rst_i) 
	    cr <= #1 8'h0; 
	  else if (wb_rst_i) 
	    cr <= #1 8'h0; 
	  else if (wb_wacc) 
	    begin 
	        if (core_en & (wb_adr_i == 3'b100) ) 
	          cr <= #1 wb_dat_i; 
	    end 
	  else 
	    begin 
	        if (done | i2c_al) 
	          cr[7:4] <= #1 4'h0;           // clear command bits when done 
	                                        // or when aribitration lost 
	        cr[2:1] <= #1 2'b0;             // reserved bits 
	        cr[0]   <= #1 2'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 iack = cr[0]; 
 
	// decode control register 
	assign core_en = ctr[7]; 
	assign ien = ctr[6]; 
 
	// hookup byte controller block 
	i2c_master_byte_ctrl byte_controller ( 
		.clk      ( wb_clk_i     ), 
		.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 ) 
	); 
 
	// status register block + interrupt request signal 
	always @(posedge wb_clk_i or negedge rst_i) 
	  if (!rst_i) 
	    begin 
	        al       <= #1 1'b0; 
	        rxack    <= #1 1'b0; 
	        tip      <= #1 1'b0; 
	        irq_flag <= #1 1'b0; 
	    end 
	  else if (wb_rst_i) 
	    begin 
	        al       <= #1 1'b0; 
	        rxack    <= #1 1'b0; 
	        tip      <= #1 1'b0; 
	        irq_flag <= #1 1'b0; 
	    end 
	  else 
	    begin 
	        al       <= #1 i2c_al | (al & ~sta); 
	        rxack    <= #1 irxack; 
	        tip      <= #1 (rd | wr); 
	        irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated 
	    end 
 
	// generate interrupt request signals 
	always @(posedge wb_clk_i or negedge rst_i) 
	  if (!rst_i) 
	    wb_inta_o <= #1 1'b0; 
	  else if (wb_rst_i) 
	    wb_inta_o <= #1 1'b0; 
	  else 
	    wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set) 
 
	// assign status register bits 
	assign sr[7]   = rxack; 
	assign sr[6]   = i2c_busy; 
	assign sr[5]   = al; 
	assign sr[4:2] = 3'h0; // reserved 
	assign sr[1]   = tip; 
	assign sr[0]   = irq_flag; 
 
endmodule