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

Subversion Repositories i2c

[/] [i2c/] [trunk/] [rtl/] [verilog/] [i2c_master_byte_ctrl.v] - Rev 14

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

/////////////////////////////////////////////////////////////////////
////                                                             ////
////  WISHBONE rev.B2 compliant I2C Master byte-controller       ////
////                                                             ////
////                                                             ////
////  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_byte_ctrl.v,v 1.3 2001-11-05 11:59:25 rherveille Exp $
//
//  $Date: 2001-11-05 11:59:25 $
//  $Revision: 1.3 $
//  $Author: rherveille $
//  $Locker:  $
//  $State: Exp $
//
// Change History:
//               $Log: not supported by cvs2svn $
 
`include "timescale.v"
`include "i2c_master_defines.v"
 
module i2c_master_byte_ctrl (
	clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, din,
	cmd_ack, ack_out, dout, i2c_busy, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen );
 
	//
	// inputs & outputs
	//
	input clk;     // master clock
	input rst;     // synchronous active high reset
	input nReset;  // 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       cmd_ack;
	reg cmd_ack;
	output       ack_out;
	reg ack_out;
	output       i2c_busy;
	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
	i2c_master_bit_ctrl bit_controller (
		.clk(clk),
		.rst(rst),
		.nReset(nReset),
		.ena(ena),
		.clk_cnt(clk_cnt),
		.cmd(core_cmd),
		.cmd_ack(core_ack),
		.busy(i2c_busy),
		.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 nReset)
		if (!nReset)
			sr <= #1 8'h0;
		else if (rst)
			sr <= #1 8'h0;
		else if (ld)
			sr <= #1 din;
		else if (shift)
			sr <= #1 {sr[6:0], core_rxd};
 
	// generate counter
	always@(posedge clk or negedge nReset)
		if (!nReset)
			dcnt <= #1 3'h0;
		else if (rst)
			dcnt <= #1 3'h0;
		else if (ld)
			dcnt <= #1 3'h7;
		else if (shift)
			dcnt <= #1 dcnt - 3'h1;
 
	assign cnt_done = !(|dcnt);
 
	//
	// state machine
	//
	reg [4:0] c_state; // synopsis enum_state
 
	always@(posedge clk or negedge nReset)
		if (!nReset)
			begin
				core_cmd <= #1 `I2C_CMD_NOP;
				core_txd <= #1 1'b0;
 
				shift    <= #1 1'b0;
				ld       <= #1 1'b0;
 
				cmd_ack  <= #1 1'b0;
				c_state  <= #1 ST_IDLE;
 
				ack_out  <= #1 1'b0;
			end
		else if (rst)
			begin
				core_cmd <= #1 `I2C_CMD_NOP;
				core_txd <= #1 1'b0;
 
				shift    <= #1 1'b0;
				ld       <= #1 1'b0;
 
				cmd_ack  <= #1 1'b0;
				c_state  <= #1 ST_IDLE;
 
				ack_out  <= #1 1'b0;
			end
	else
		begin
			// initially reset all signals
			core_txd <= #1 sr[7];
 
			shift    <= #1 1'b0;
			ld       <= #1 1'b0;
 
			cmd_ack  <= #1 1'b0;
 
			case (c_state) // synopsis full_case parallel_case
				ST_IDLE:
					if (go)
						begin
							if (start)
								begin
									c_state  <= #1 ST_START;
									core_cmd <= #1 `I2C_CMD_START;
								end
							else if (read)
								begin
									c_state  <= #1 ST_READ;
									core_cmd <= #1 `I2C_CMD_READ;
								end
							else if (write)
								begin
									c_state  <= #1 ST_WRITE;
									core_cmd <= #1 `I2C_CMD_WRITE;
								end
							else // stop
								begin
									c_state  <= #1 ST_STOP;
									core_cmd <= #1 `I2C_CMD_STOP;
 
									// generate command acknowledge signal
									cmd_ack  <= #1 1'b1;
								end
 
							ld       <= #1 1'b1;
						end
 
				ST_START:
					if (core_ack)
						begin
							if (read)
								begin
									c_state  <= #1 ST_READ;
									core_cmd <= #1 `I2C_CMD_READ;
								end
							else
								begin
									c_state  <= #1 ST_WRITE;
									core_cmd <= #1 `I2C_CMD_WRITE;
								end
 
							ld       <= #1 1'b1;
						end
 
				ST_WRITE:
					if (core_ack)
						if (cnt_done)
							begin
								c_state  <= #1 ST_ACK;
								core_cmd <= #1 `I2C_CMD_READ;
							end
						else
							begin
								c_state  <= #1 ST_WRITE;       // stay in same state
								core_cmd <= #1 `I2C_CMD_WRITE; // write next bit
 
								shift    <= #1 1'b1;
							end
 
				ST_READ:
						if (core_ack)
							begin
								if (cnt_done)
									begin
										c_state  <= #1 ST_ACK;
										core_cmd <= #1 `I2C_CMD_WRITE;
									end
								else
									begin
										c_state  <= #1 ST_READ;       // stay in same state
										core_cmd <= #1 `I2C_CMD_READ; // read next bit
									end
 
								shift    <= #1 1'b1;
								core_txd <= #1 ack_in;
							end
 
				ST_ACK:
					if (core_ack)
						begin
							if (stop)
								begin
									c_state  <= #1 ST_STOP;
									core_cmd <= #1 `I2C_CMD_STOP;
								end
							else
								begin
									c_state  <= #1 ST_IDLE;
									core_cmd <= #1 `I2C_CMD_NOP;
								end
 
							// assign ack_out output to bit_controller_rxd (contains last received bit)
							ack_out <= #1 core_rxd;
 
							// generate command acknowledge signal
							cmd_ack  <= #1 1'b1;
 
							core_txd <= #1 1'b1;
						end
					else
						core_txd <= #1 ack_in;
 
				ST_STOP:
					if (core_ack)
						begin
							c_state  <= #1 ST_IDLE;
							core_cmd <= #1 `I2C_CMD_NOP;
						end
 
			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.