OpenCores
URL https://opencores.org/ocsvn/i2c/i2c/trunk

Subversion Repositories i2c

[/] [i2c/] [trunk/] [rtl/] [verilog/] [i2c_master_top.v] - Diff between revs 68 and 73

Only display areas with differences | Details | Blame | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.