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

Subversion Repositories i2c

[/] [i2c/] [trunk/] [rtl/] [verilog/] [i2c_master_byte_ctrl.v] - Diff between revs 47 and 62

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 47 Rev 62
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
////                                                             ////
////                                                             ////
////  WISHBONE rev.B2 compliant I2C Master byte-controller       ////
////  WISHBONE rev.B2 compliant I2C Master byte-controller       ////
////                                                             ////
////                                                             ////
////                                                             ////
////                                                             ////
////  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_byte_ctrl.v,v 1.7 2004-02-18 11:40:46 rherveille Exp $
//  $Id: i2c_master_byte_ctrl.v,v 1.8 2009-01-19 20:29:26 rherveille Exp $
//
//
//  $Date: 2004-02-18 11:40:46 $
//  $Date: 2009-01-19 20:29:26 $
//  $Revision: 1.7 $
//  $Revision: 1.8 $
//  $Author: rherveille $
//  $Author: rherveille $
//  $Locker:  $
//  $Locker:  $
//  $State: Exp $
//  $State: Exp $
//
//
// Change History:
// Change History:
//               $Log: not supported by cvs2svn $
//               $Log: not supported by cvs2svn $
 
//               Revision 1.7  2004/02/18 11:40:46  rherveille
 
//               Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command.
 
//
//               Revision 1.6  2003/08/09 07:01:33  rherveille
//               Revision 1.6  2003/08/09 07:01:33  rherveille
//               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
//               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
//               Fixed a potential bug in the byte controller's host-acknowledge generation.
//               Fixed a potential bug in the byte controller's host-acknowledge generation.
//
//
//               Revision 1.5  2002/12/26 15:02:32  rherveille
//               Revision 1.5  2002/12/26 15:02:32  rherveille
//               Core is now a Multimaster I2C controller
//               Core is now a Multimaster I2C controller
//
//
//               Revision 1.4  2002/11/30 22:24:40  rherveille
//               Revision 1.4  2002/11/30 22:24:40  rherveille
//               Cleaned up code
//               Cleaned up code
//
//
//               Revision 1.3  2001/11/05 11:59:25  rherveille
//               Revision 1.3  2001/11/05 11:59:25  rherveille
//               Fixed wb_ack_o generation bug.
//               Fixed wb_ack_o generation bug.
//               Fixed bug in the byte_controller statemachine.
//               Fixed bug in the byte_controller statemachine.
//               Added headers.
//               Added headers.
//
//
 
 
// 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_byte_ctrl (
module i2c_master_byte_ctrl (
        clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, din,
        clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, din,
        cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen );
        cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen );
 
 
        //
        //
        // inputs & outputs
        // inputs & outputs
        //
        //
        input clk;     // master clock
        input clk;     // master clock
        input rst;     // synchronous active high reset
        input rst;     // synchronous active high reset
        input nReset;  // asynchronous active low reset
        input nReset;  // asynchronous active low reset
        input ena;     // core enable signal
        input ena;     // core enable signal
 
 
        input [15:0] clk_cnt; // 4x SCL
        input [15:0] clk_cnt; // 4x SCL
 
 
        // control inputs
        // control inputs
        input       start;
        input       start;
        input       stop;
        input       stop;
        input       read;
        input       read;
        input       write;
        input       write;
        input       ack_in;
        input       ack_in;
        input [7:0] din;
        input [7:0] din;
 
 
        // status outputs
        // status outputs
        output       cmd_ack;
        output       cmd_ack;
        reg cmd_ack;
        reg cmd_ack;
        output       ack_out;
        output       ack_out;
        reg ack_out;
        reg ack_out;
        output       i2c_busy;
        output       i2c_busy;
        output       i2c_al;
        output       i2c_al;
        output [7:0] dout;
        output [7:0] dout;
 
 
        // I2C signals
        // I2C signals
        input  scl_i;
        input  scl_i;
        output scl_o;
        output scl_o;
        output scl_oen;
        output scl_oen;
        input  sda_i;
        input  sda_i;
        output sda_o;
        output sda_o;
        output sda_oen;
        output sda_oen;
 
 
 
 
        //
        //
        // Variable declarations
        // Variable declarations
        //
        //
 
 
        // statemachine
        // statemachine
        parameter [4:0] ST_IDLE  = 5'b0_0000;
        parameter [4:0] ST_IDLE  = 5'b0_0000;
        parameter [4:0] ST_START = 5'b0_0001;
        parameter [4:0] ST_START = 5'b0_0001;
        parameter [4:0] ST_READ  = 5'b0_0010;
        parameter [4:0] ST_READ  = 5'b0_0010;
        parameter [4:0] ST_WRITE = 5'b0_0100;
        parameter [4:0] ST_WRITE = 5'b0_0100;
        parameter [4:0] ST_ACK   = 5'b0_1000;
        parameter [4:0] ST_ACK   = 5'b0_1000;
        parameter [4:0] ST_STOP  = 5'b1_0000;
        parameter [4:0] ST_STOP  = 5'b1_0000;
 
 
        // signals for bit_controller
        // signals for bit_controller
        reg  [3:0] core_cmd;
        reg  [3:0] core_cmd;
        reg        core_txd;
        reg        core_txd;
        wire       core_ack, core_rxd;
        wire       core_ack, core_rxd;
 
 
        // signals for shift register
        // signals for shift register
        reg [7:0] sr; //8bit shift register
        reg [7:0] sr; //8bit shift register
        reg       shift, ld;
        reg       shift, ld;
 
 
        // signals for state machine
        // signals for state machine
        wire       go;
        wire       go;
        reg  [2:0] dcnt;
        reg  [2:0] dcnt;
        wire       cnt_done;
        wire       cnt_done;
 
 
        //
        //
        // Module body
        // Module body
        //
        //
 
 
        // hookup bit_controller
        // hookup bit_controller
        i2c_master_bit_ctrl bit_controller (
        i2c_master_bit_ctrl bit_controller (
                .clk     ( clk      ),
                .clk     ( clk      ),
                .rst     ( rst      ),
                .rst     ( rst      ),
                .nReset  ( nReset   ),
                .nReset  ( nReset   ),
                .ena     ( ena      ),
                .ena     ( ena      ),
                .clk_cnt ( clk_cnt  ),
                .clk_cnt ( clk_cnt  ),
                .cmd     ( core_cmd ),
                .cmd     ( core_cmd ),
                .cmd_ack ( core_ack ),
                .cmd_ack ( core_ack ),
                .busy    ( i2c_busy ),
                .busy    ( i2c_busy ),
                .al      ( i2c_al   ),
                .al      ( i2c_al   ),
                .din     ( core_txd ),
                .din     ( core_txd ),
                .dout    ( core_rxd ),
                .dout    ( core_rxd ),
                .scl_i   ( scl_i    ),
                .scl_i   ( scl_i    ),
                .scl_o   ( scl_o    ),
                .scl_o   ( scl_o    ),
                .scl_oen ( scl_oen  ),
                .scl_oen ( scl_oen  ),
                .sda_i   ( sda_i    ),
                .sda_i   ( sda_i    ),
                .sda_o   ( sda_o    ),
                .sda_o   ( sda_o    ),
                .sda_oen ( sda_oen  )
                .sda_oen ( sda_oen  )
        );
        );
 
 
        // generate go-signal
        // generate go-signal
        assign go = (read | write | stop) & ~cmd_ack;
        assign go = (read | write | stop) & ~cmd_ack;
 
 
        // assign dout output to shift-register
        // assign dout output to shift-register
        assign dout = sr;
        assign dout = sr;
 
 
        // generate shift register
        // generate shift register
        always @(posedge clk or negedge nReset)
        always @(posedge clk or negedge nReset)
          if (!nReset)
          if (!nReset)
            sr <= #1 8'h0;
            sr <= #1 8'h0;
          else if (rst)
          else if (rst)
            sr <= #1 8'h0;
            sr <= #1 8'h0;
          else if (ld)
          else if (ld)
            sr <= #1 din;
            sr <= #1 din;
          else if (shift)
          else if (shift)
            sr <= #1 {sr[6:0], core_rxd};
            sr <= #1 {sr[6:0], core_rxd};
 
 
        // generate counter
        // generate counter
        always @(posedge clk or negedge nReset)
        always @(posedge clk or negedge nReset)
          if (!nReset)
          if (!nReset)
            dcnt <= #1 3'h0;
            dcnt <= #1 3'h0;
          else if (rst)
          else if (rst)
            dcnt <= #1 3'h0;
            dcnt <= #1 3'h0;
          else if (ld)
          else if (ld)
            dcnt <= #1 3'h7;
            dcnt <= #1 3'h7;
          else if (shift)
          else if (shift)
            dcnt <= #1 dcnt - 3'h1;
            dcnt <= #1 dcnt - 3'h1;
 
 
        assign cnt_done = ~(|dcnt);
        assign cnt_done = ~(|dcnt);
 
 
        //
        //
        // state machine
        // state machine
        //
        //
        reg [4:0] c_state; // synopsis enum_state
        reg [4:0] c_state; // synopsys enum_state
 
 
        always @(posedge clk or negedge nReset)
        always @(posedge clk or negedge nReset)
          if (!nReset)
          if (!nReset)
            begin
            begin
                core_cmd <= #1 `I2C_CMD_NOP;
                core_cmd <= #1 `I2C_CMD_NOP;
                core_txd <= #1 1'b0;
                core_txd <= #1 1'b0;
                shift    <= #1 1'b0;
                shift    <= #1 1'b0;
                ld       <= #1 1'b0;
                ld       <= #1 1'b0;
                cmd_ack  <= #1 1'b0;
                cmd_ack  <= #1 1'b0;
                c_state  <= #1 ST_IDLE;
                c_state  <= #1 ST_IDLE;
                ack_out  <= #1 1'b0;
                ack_out  <= #1 1'b0;
            end
            end
          else if (rst | i2c_al)
          else if (rst | i2c_al)
           begin
           begin
               core_cmd <= #1 `I2C_CMD_NOP;
               core_cmd <= #1 `I2C_CMD_NOP;
               core_txd <= #1 1'b0;
               core_txd <= #1 1'b0;
               shift    <= #1 1'b0;
               shift    <= #1 1'b0;
               ld       <= #1 1'b0;
               ld       <= #1 1'b0;
               cmd_ack  <= #1 1'b0;
               cmd_ack  <= #1 1'b0;
               c_state  <= #1 ST_IDLE;
               c_state  <= #1 ST_IDLE;
               ack_out  <= #1 1'b0;
               ack_out  <= #1 1'b0;
           end
           end
        else
        else
          begin
          begin
              // initially reset all signals
              // initially reset all signals
              core_txd <= #1 sr[7];
              core_txd <= #1 sr[7];
              shift    <= #1 1'b0;
              shift    <= #1 1'b0;
              ld       <= #1 1'b0;
              ld       <= #1 1'b0;
              cmd_ack  <= #1 1'b0;
              cmd_ack  <= #1 1'b0;
 
 
              case (c_state) // synopsys full_case parallel_case
              case (c_state) // synopsys full_case parallel_case
                ST_IDLE:
                ST_IDLE:
                  if (go)
                  if (go)
                    begin
                    begin
                        if (start)
                        if (start)
                          begin
                          begin
                              c_state  <= #1 ST_START;
                              c_state  <= #1 ST_START;
                              core_cmd <= #1 `I2C_CMD_START;
                              core_cmd <= #1 `I2C_CMD_START;
                          end
                          end
                        else if (read)
                        else if (read)
                          begin
                          begin
                              c_state  <= #1 ST_READ;
                              c_state  <= #1 ST_READ;
                              core_cmd <= #1 `I2C_CMD_READ;
                              core_cmd <= #1 `I2C_CMD_READ;
                          end
                          end
                        else if (write)
                        else if (write)
                          begin
                          begin
                              c_state  <= #1 ST_WRITE;
                              c_state  <= #1 ST_WRITE;
                              core_cmd <= #1 `I2C_CMD_WRITE;
                              core_cmd <= #1 `I2C_CMD_WRITE;
                          end
                          end
                        else // stop
                        else // stop
                          begin
                          begin
                              c_state  <= #1 ST_STOP;
                              c_state  <= #1 ST_STOP;
                              core_cmd <= #1 `I2C_CMD_STOP;
                              core_cmd <= #1 `I2C_CMD_STOP;
                          end
                          end
 
 
                        ld <= #1 1'b1;
                        ld <= #1 1'b1;
                    end
                    end
 
 
                ST_START:
                ST_START:
                  if (core_ack)
                  if (core_ack)
                    begin
                    begin
                        if (read)
                        if (read)
                          begin
                          begin
                              c_state  <= #1 ST_READ;
                              c_state  <= #1 ST_READ;
                              core_cmd <= #1 `I2C_CMD_READ;
                              core_cmd <= #1 `I2C_CMD_READ;
                          end
                          end
                        else
                        else
                          begin
                          begin
                              c_state  <= #1 ST_WRITE;
                              c_state  <= #1 ST_WRITE;
                              core_cmd <= #1 `I2C_CMD_WRITE;
                              core_cmd <= #1 `I2C_CMD_WRITE;
                          end
                          end
 
 
                        ld <= #1 1'b1;
                        ld <= #1 1'b1;
                    end
                    end
 
 
                ST_WRITE:
                ST_WRITE:
                  if (core_ack)
                  if (core_ack)
                    if (cnt_done)
                    if (cnt_done)
                      begin
                      begin
                          c_state  <= #1 ST_ACK;
                          c_state  <= #1 ST_ACK;
                          core_cmd <= #1 `I2C_CMD_READ;
                          core_cmd <= #1 `I2C_CMD_READ;
                      end
                      end
                    else
                    else
                      begin
                      begin
                          c_state  <= #1 ST_WRITE;       // stay in same state
                          c_state  <= #1 ST_WRITE;       // stay in same state
                          core_cmd <= #1 `I2C_CMD_WRITE; // write next bit
                          core_cmd <= #1 `I2C_CMD_WRITE; // write next bit
                          shift    <= #1 1'b1;
                          shift    <= #1 1'b1;
                      end
                      end
 
 
                ST_READ:
                ST_READ:
                  if (core_ack)
                  if (core_ack)
                    begin
                    begin
                        if (cnt_done)
                        if (cnt_done)
                          begin
                          begin
                              c_state  <= #1 ST_ACK;
                              c_state  <= #1 ST_ACK;
                              core_cmd <= #1 `I2C_CMD_WRITE;
                              core_cmd <= #1 `I2C_CMD_WRITE;
                          end
                          end
                        else
                        else
                          begin
                          begin
                              c_state  <= #1 ST_READ;       // stay in same state
                              c_state  <= #1 ST_READ;       // stay in same state
                              core_cmd <= #1 `I2C_CMD_READ; // read next bit
                              core_cmd <= #1 `I2C_CMD_READ; // read next bit
                          end
                          end
 
 
                        shift    <= #1 1'b1;
                        shift    <= #1 1'b1;
                        core_txd <= #1 ack_in;
                        core_txd <= #1 ack_in;
                    end
                    end
 
 
                ST_ACK:
                ST_ACK:
                  if (core_ack)
                  if (core_ack)
                    begin
                    begin
                       if (stop)
                       if (stop)
                         begin
                         begin
                             c_state  <= #1 ST_STOP;
                             c_state  <= #1 ST_STOP;
                             core_cmd <= #1 `I2C_CMD_STOP;
                             core_cmd <= #1 `I2C_CMD_STOP;
                         end
                         end
                       else
                       else
                         begin
                         begin
                             c_state  <= #1 ST_IDLE;
                             c_state  <= #1 ST_IDLE;
                             core_cmd <= #1 `I2C_CMD_NOP;
                             core_cmd <= #1 `I2C_CMD_NOP;
 
 
                             // generate command acknowledge signal
                             // generate command acknowledge signal
                             cmd_ack  <= #1 1'b1;
                             cmd_ack  <= #1 1'b1;
                         end
                         end
 
 
                         // assign ack_out output to bit_controller_rxd (contains last received bit)
                         // assign ack_out output to bit_controller_rxd (contains last received bit)
                         ack_out <= #1 core_rxd;
                         ack_out <= #1 core_rxd;
 
 
                         core_txd <= #1 1'b1;
                         core_txd <= #1 1'b1;
                     end
                     end
                   else
                   else
                     core_txd <= #1 ack_in;
                     core_txd <= #1 ack_in;
 
 
                ST_STOP:
                ST_STOP:
                  if (core_ack)
                  if (core_ack)
                    begin
                    begin
                        c_state  <= #1 ST_IDLE;
                        c_state  <= #1 ST_IDLE;
                        core_cmd <= #1 `I2C_CMD_NOP;
                        core_cmd <= #1 `I2C_CMD_NOP;
 
 
                        // generate command acknowledge signal
                        // generate command acknowledge signal
                        cmd_ack  <= #1 1'b1;
                        cmd_ack  <= #1 1'b1;
                    end
                    end
 
 
              endcase
              endcase
          end
          end
endmodule
endmodule
 
 

powered by: WebSVN 2.1.0

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