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

Subversion Repositories oms8051mini

[/] [oms8051mini/] [trunk/] [rtl/] [i2cm/] [i2cm_byte_ctrl.v] - Rev 37

Go to most recent revision | Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  OMS8051 I2C Master byte-controller Module                  ////
////  WISHBONE rev.B2 compliant I2C Master byte-controller       ////
////                                                              ////
////  This file is part of the OMS 8051 cores project             ////
////  http://www.opencores.org/cores/oms8051mini/                 ////
////                                                              ////
////  Description                                                 ////
////  OMS 8051 definitions.                                       ////
////                                                              ////
////  To Do:                                                      ////
////    nothing                                                   ////
////                                                              ////
////  Author(s):                                                  ////
////      -Richard Herveille ,  richard@asics.ws, www.asics.ws    ////
////      -Dinesh Annayya, dinesha@opencores.org                  ////
////                                                              ////
////  Revision : Jan 6, 2017                                      //// 
////                                                              ////
//////////////////////////////////////////////////////////////////////
////   v0.0 - Dinesh A, 6th Jan 2017
////        1. Initail version picked from
////            http://www.opencores.org/projects/i2c/
////        2. renaming of reset signal to aresetn and sresetn
////   v0.1 - Dinesh.A, 19th Jan 2017
////        1. Lint Error fixes
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2000 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 "i2cm_defines.v"
 
module i2cm_byte_ctrl (
	//
	// inputs & outputs
	//
	input        clk,     // master clock
	input        sresetn, // synchronous active high reset
	input        aresetn, // asynchronous active low reset
	input        ena,     // core enable signal
 
	input [15:0] clk_cnt, // 4x SCL
 
	// control inputs
	input        start,
	input        stop,
	input        read,
	input        write,
	input        ack_in,
	input [7:0]  din,
 
	// status outputs
	output reg   cmd_ack,
	output reg   ack_out,
	output       i2c_busy,
	output       i2c_al,
	output [7:0] dout,
 
	// I2C signals
	input        scl_i,
	output       scl_o,
	output       scl_oen,
	input        sda_i,
	output       sda_o,
	output       sda_oen
 
       );
 
 
 
	//
	// Variable declarations
	//
 
	// statemachine
	parameter [4:0] ST_IDLE  = 5'b0_0000;
	parameter [4:0] ST_START = 5'b0_0001;
	parameter [4:0] ST_READ  = 5'b0_0010;
	parameter [4:0] ST_WRITE = 5'b0_0100;
	parameter [4:0] ST_ACK   = 5'b0_1000;
	parameter [4:0] ST_STOP  = 5'b1_0000;
 
	// signals for bit_controller
	reg  [3:0] core_cmd;
	reg        core_txd;
	wire       core_ack, core_rxd;
 
	// signals for shift register
	reg [7:0] sr; //8bit shift register
	reg       shift, ld;
 
	// signals for state machine
	wire       go;
	reg  [2:0] dcnt;
	wire       cnt_done;
 
	//
	// Module body
	//
 
	// hookup bit_controller
	i2cm_bit_ctrl u_bit_ctrl (
		.clk     ( clk      ),
		.sresetn ( sresetn  ),
		.aresetn ( aresetn ),
		.ena     ( ena      ),
		.clk_cnt ( clk_cnt  ),
		.cmd     ( core_cmd ),
		.cmd_ack ( core_ack ),
		.busy    ( i2c_busy ),
		.al      ( i2c_al   ),
		.din     ( core_txd ),
		.dout    ( core_rxd ),
		.scl_i   ( scl_i    ),
		.scl_o   ( scl_o    ),
		.scl_oen ( scl_oen  ),
		.sda_i   ( sda_i    ),
		.sda_o   ( sda_o    ),
		.sda_oen ( sda_oen  )
	);
 
	// generate go-signal
	assign go = (read | write | stop) & ~cmd_ack;
 
	// assign dout output to shift-register
	assign dout = sr;
 
	// generate shift register
	always @(posedge clk or negedge aresetn)
	  if (!aresetn)
	    sr <= 8'h0;
	  else if (!sresetn)
	    sr <= 8'h0;
	  else if (ld)
	    sr <= din;
	  else if (shift)
	    sr <= {sr[6:0], core_rxd};
 
	// generate counter
	always @(posedge clk or negedge aresetn)
	  if (!aresetn)
	    dcnt <= 3'h0;
	  else if (!sresetn)
	    dcnt <= 3'h0;
	  else if (ld)
	    dcnt <= 3'h7;
	  else if (shift)
	    dcnt <= dcnt - 3'h1;
 
	assign cnt_done = ~(|dcnt);
 
	//
	// state machine
	//
	reg [4:0] c_state; // synopsys enum_state
 
	always @(posedge clk or negedge aresetn)
	  if (!aresetn)
	    begin
	        core_cmd <= `I2C_CMD_NOP;
	        core_txd <= 1'b0;
	        shift    <= 1'b0;
	        ld       <= 1'b0;
	        cmd_ack  <= 1'b0;
	        c_state  <= ST_IDLE;
	        ack_out  <= 1'b0;
	    end
	  else if (!sresetn | i2c_al)
	   begin
	       core_cmd <= `I2C_CMD_NOP;
	       core_txd <= 1'b0;
	       shift    <= 1'b0;
	       ld       <= 1'b0;
	       cmd_ack  <= 1'b0;
	       c_state  <= ST_IDLE;
	       ack_out  <= 1'b0;
	   end
	else
	  begin
	      // initially reset all signals
	      core_txd <= sr[7];
	      shift    <= 1'b0;
	      ld       <= 1'b0;
	      cmd_ack  <= 1'b0;
 
	      case (c_state) // synopsys full_case parallel_case
	        ST_IDLE:
	          if (go)
	            begin
	                if (start)
	                  begin
	                      c_state  <= ST_START;
	                      core_cmd <= `I2C_CMD_START;
	                  end
	                else if (read)
	                  begin
	                      c_state  <= ST_READ;
	                      core_cmd <= `I2C_CMD_READ;
	                  end
	                else if (write)
	                  begin
	                      c_state  <= ST_WRITE;
	                      core_cmd <= `I2C_CMD_WRITE;
	                  end
	                else // stop
	                  begin
	                      c_state  <= ST_STOP;
	                      core_cmd <= `I2C_CMD_STOP;
	                  end
 
	                ld <= 1'b1;
	            end
 
	        ST_START:
	          if (core_ack)
	            begin
	                if (read)
	                  begin
	                      c_state  <= ST_READ;
	                      core_cmd <= `I2C_CMD_READ;
	                  end
	                else
	                  begin
	                      c_state  <= ST_WRITE;
	                      core_cmd <= `I2C_CMD_WRITE;
	                  end
 
	                ld <= 1'b1;
	            end
 
	        ST_WRITE:
	          if (core_ack)
	            if (cnt_done)
	              begin
	                  c_state  <= ST_ACK;
	                  core_cmd <= `I2C_CMD_READ;
	              end
	            else
	              begin
	                  c_state  <= ST_WRITE;       // stay in same state
	                  core_cmd <= `I2C_CMD_WRITE; // write next bit
	                  shift    <= 1'b1;
	              end
 
	        ST_READ:
	          if (core_ack)
	            begin
	                if (cnt_done)
	                  begin
	                      c_state  <= ST_ACK;
	                      core_cmd <= `I2C_CMD_WRITE;
	                  end
	                else
	                  begin
	                      c_state  <= ST_READ;       // stay in same state
	                      core_cmd <= `I2C_CMD_READ; // read next bit
	                  end
 
	                shift    <= 1'b1;
	                core_txd <= ack_in;
	            end
 
	        ST_ACK:
	          if (core_ack)
	            begin
	               if (stop)
	                 begin
	                     c_state  <= ST_STOP;
	                     core_cmd <= `I2C_CMD_STOP;
	                 end
	               else
	                 begin
	                     c_state  <= ST_IDLE;
	                     core_cmd <= `I2C_CMD_NOP;
 
	                     // generate command acknowledge signal
	                     cmd_ack  <= 1'b1;
	                 end
 
	                 // assign ack_out output to bit_controller_rxd (contains last received bit)
	                 ack_out <=  core_rxd;
 
	                 core_txd <=  1'b1;
	             end
	           else
	             core_txd <= ack_in;
 
	        ST_STOP:
	          if (core_ack)
	            begin
	                c_state  <= ST_IDLE;
	                core_cmd <= `I2C_CMD_NOP;
 
	                // generate command acknowledge signal
	                cmd_ack  <= 1'b1;
	            end
               default: c_state  <= ST_IDLE;
 
	      endcase
	  end
endmodule
 

Go to most recent revision | 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.