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

Subversion Repositories i2c

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

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

//
// WISHBONE revB2 compiant I2C master core
//
// author: Richard Herveille
// rev. 0.1 August  24th, 2001. Initial Verilog release.
// rev. 0.2 October 25th, 2001. Fixed some synthesis warnings.
//
 
`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  [3: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 4'h0;
		else if (rst)
			dcnt <= #1 4'h0;
		else if (ld)
			dcnt <= #1 4'h7;
		else if (shift)
			dcnt <= #1 dcnt - 4'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;
			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;
			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;
							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 = 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.