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

Subversion Repositories i2c_to_wb

[/] [i2c_to_wb/] [trunk/] [src/] [i2c_to_wb_fsm.v] - Rev 5

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// 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 source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
 
 
`include "timescale.v"
 
 
module
  i2c_to_wb_fsm
  (
    input         i2c_data,
    input         i2c_data_rise,
    input         i2c_data_fall,
 
    input         i2c_clk,
    input         i2c_clk_rise,
    input         i2c_clk_fall,
 
    input         i2c_r_w_bit,
    input         i2c_ack_out,
    output        i2c_ack_done,
 
    output        tip_addr_byte,
    output        tip_read_byte,
    output        tip_write_byte,
    output        tip_wr_ack,
    output        tip_rd_ack,
    output        tip_addr_ack,
 
    output  [7:0] state_out,
    output        i2c_error,
 
    input         wb_clk_i,
    input         wb_rst_i
  );
 
  // --------------------------------------------------------------------
  //  wires
  wire xmt_byte_done;
 
  wire tip_ack;
 
 
  // --------------------------------------------------------------------
  //  start & stop & ack
 
  wire start_detected = i2c_data_fall & i2c_clk;
  wire stop_detected  = i2c_data_rise & i2c_clk;
 
 
  // --------------------------------------------------------------------
  //  state machine
 
  localparam   STATE_IDLE       = 8'b00000001;
  localparam   STATE_ADDR_BYTE  = 8'b00000010;
  localparam   STATE_ADDR_ACK   = 8'b00000100;
  localparam   STATE_WRITE      = 8'b00001000;
  localparam   STATE_WR_ACK     = 8'b00010000;
  localparam   STATE_READ       = 8'b00100000;
  localparam   STATE_RD_ACK     = 8'b01000000;
  localparam   STATE_ERROR      = 8'b10000000;
 
  reg [7:0] state;
  reg [7:0] next_state;
 
  always @(posedge wb_clk_i or posedge wb_rst_i)
    if(wb_rst_i)
      state <= STATE_IDLE;
    else
      state <= next_state;
 
  always @(*)
    case( state )
      STATE_IDLE:       if( start_detected )
                          next_state = STATE_ADDR_BYTE;
                        else
                          next_state = STATE_IDLE;
 
      STATE_ADDR_BYTE:  if( xmt_byte_done )
                          next_state = STATE_ADDR_ACK;
                        else if( stop_detected )
                          next_state = STATE_ERROR;
                        else
                          next_state = STATE_ADDR_BYTE;
 
      STATE_ADDR_ACK:   if(i2c_ack_out)
                          next_state = STATE_IDLE;
                        else
                          if( i2c_ack_done )
                            if( i2c_r_w_bit )
                              next_state = STATE_READ;
                            else
                              next_state = STATE_WRITE;
                          else if( start_detected | stop_detected )
                            next_state = STATE_ERROR;
                          else
                            next_state = STATE_ADDR_ACK;
 
      STATE_WRITE:      if( xmt_byte_done )
                          next_state = STATE_WR_ACK;
                        else if( start_detected )
                          next_state = STATE_ADDR_BYTE;
                        else if( stop_detected )
                          next_state = STATE_IDLE;
                        else
                          next_state = STATE_WRITE;
 
      STATE_WR_ACK:     if( i2c_ack_done )
                          next_state = STATE_WRITE;
                        else if( start_detected | stop_detected )
                          next_state = STATE_ERROR;
                        else
                          next_state = STATE_WR_ACK;
 
      STATE_READ:       if( xmt_byte_done )
                          next_state = STATE_RD_ACK;
                        else if( start_detected )
                          next_state = STATE_ADDR_BYTE;
                        else if( stop_detected )
                          next_state = STATE_IDLE;
                        else
                          next_state = STATE_READ;
 
      STATE_RD_ACK:     if( i2c_ack_done )
                          if(i2c_data)
                            next_state = STATE_IDLE;
                          else
                            next_state = STATE_READ;
                        else if( start_detected | stop_detected )
                          next_state = STATE_ERROR;
                        else
                          next_state = STATE_RD_ACK;
 
      STATE_ERROR:      next_state = STATE_IDLE;
 
      default:          next_state = STATE_ERROR;
    endcase
 
 
  // --------------------------------------------------------------------
  //  bit counter
  reg [3:0] bit_count;
 
  assign  xmt_byte_done = (bit_count == 4'h7) & i2c_clk_rise;
  assign  tip_ack       = (bit_count == 4'h8);
  assign  i2c_ack_done  = tip_ack & i2c_clk_rise;
 
  always @(posedge wb_clk_i)
    if( wb_rst_i | i2c_ack_done | start_detected )
      bit_count <= 4'hf;
    else if( i2c_clk_fall )
      bit_count <= bit_count + 1;
 
 
  // --------------------------------------------------------------------
  //  debug
  wire i2c_start_error = (state == STATE_ADDR_BYTE) & start_detected;
 
 
  // --------------------------------------------------------------------
  //  outputs
 
  assign state_out = state;
 
  assign  tip_addr_byte   = (state == STATE_ADDR_BYTE);
  assign  tip_addr_ack    = (state == STATE_ADDR_ACK);
  assign  tip_read_byte   = (state == STATE_READ);
  assign  tip_write_byte  = tip_addr_byte               | (state == STATE_WRITE);
  assign  tip_wr_ack      = tip_addr_ack                | (state == STATE_WR_ACK);
  assign  tip_rd_ack      = (state == STATE_RD_ACK);
 
  assign i2c_error = (state == STATE_ERROR) | i2c_start_error;
 
endmodule
 
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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