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

Subversion Repositories i2c_master_slave_core

[/] [i2c_master_slave_core/] [trunk/] [i2c_master_slave_core/] [verilog/] [rtl/] [controller_interface.v] - Rev 6

Compare with Previous | Blame | View Log

////////////////////////////////////////////controller_interface.v////////////////////////////////////////
//													//
//Design Engineer:	Ravi Gupta 									//
//Company Name	 :	Toomuch Semiconductor
//Email		 :	ravi1.gupta@toomuchsemi.com							//
//													//	
//Purpose	 :	This core will be used as an interface between I2C core and Processor		//			
//Created	 :	6-12-2007									//
//													//	
//													//
//													//
//													//	
//													//			
//													//			
//													//
//													//
//Modification : Change the control register,added halt reset and inter_rst in control register
/////////////////////////////////////////////////////////////////////////////////////////////////////////
 
/*// synopsys translate_off
`include "oc8051_timescale.v"
// synopsys translate_on
 
`include "oc8051_defines.v"*/
 
 
module processor_interface (clk,rst,add_bus,data_in,data_out,as,ds,rw,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,inter,ack_rec,
		  core_en,inter_en,mode,master_rw,ack,rep_start,data,i2c_data,slave_add,time_out_reg,prescale,irq,time_out,inter_rst,halt,data_en,time_rst);
input clk;			//System clock
input rst;			//system reset
 
//signals connecting core to processor
/////////////////////////////////////
 
input [7:0]add_bus;		//contains address of internal register
input [7:0]data_in;		//trnasport the data for i2c core
input as;			//asserted high indicates vallid address has been placed on the address bus
input ds;			//asserted high indicates valid data on data bus
input rw;			//"1" indicates that processor has to write else read
output irq;			//interrupt to processor
output inter_rst;		//this bit will be written by processor when it will clear the interrupt.
output [7:0]data_out;
output halt;
output data_en;
input time_rst;
 
//signals from core to reflect te status of core and buses
///////////////////////////////////////////////////////////
 
input bus_busy;			//signal from core indicates bus is busy
input byte_trans;		//signal from core indicates byte transfer is in progress
input slave_addressed;		//signal from core indicares core has been identified as slave
input arb_lost;			//signal from core indicates bus error
input slave_rw;			//signal from core indicates operation of slave core
input inter;			//signal from core.this will interrupt the processor if this bit as well as interrupt enable is high
input ack_rec;			//signal from core to reflect the status of ack bit
input time_out;
 
//bits of control register
//////////////////////////
 
inout core_en;			//this bit must be cleared before any other bit of control register have any effect on core
inout inter_en;			//To intrrupt the core this bit must be set when interrupt is pending
inout mode;			//Transaction from "0" to "1" directes core to act as master else slave
inout master_rw;		//set directiion for master either to transmit or receive
inout ack;			//value of acknowledgment bit to be transmitted on SDA line during ack cycle
inout rep_start;		//set this bit if processor wants a repeated start
 
//data register
////////////////
 
inout [7:0]prescale;		//contains the value for generating SCL frequency
inout [7:0]time_out_reg;		//contains the value for maximum low period for scl
inout [7:0]slave_add;		//this is the programmble slave address
inout [7:0]data;		   //data for i2c core 
input [7:0]i2c_data;		//data from core for processor
 
//defining registers addresses
/////////////////////////////
 
`define		PRER 	8'b0000_0010
`define		CTR 	8'b0000_0100
`define		SR 		8'b0000_1000
`define		TO 		8'b0000_1010
`define		ADDR 	8'b0000_1100
`define		DR 		8'b0000_1110
`define		RR		8'b0000_0000
 
/*//defing the machine state
//////////////////////////
 
parameter	processor_idle=2'b00;
parameter	processor_address=2'b01;
parameter	processor_data=2'b10;
parameter	processor_ack=2'b11;*/
 
//Definig internal registers and wires
/////////////////////////////////////
 
wire core_en,inter_en,mode,master_rw,ack,rep_start,inter_rst,halt;
wire prescale_reg_en;
wire ctr_reg_en;
wire sr_reg_en;
wire to_reg_en;
wire addr_reg_en;
wire dr_reg_en;
reg [7:0]data_out,sr_reg,ctr_reg,dr_reg,rr_reg;
wire [7:0]data_in;								//if address on add_bus matches with register address then set this high.
wire data_ie;								//this is signal used for enaling the data line in read or write cycle.
wire as_d;								//delay version of address strobe signal for detection of rising and falling edge 
reg as_delay_sig;							//same signal.					
wire ds_d;								//delayed version of data strobe.
wire decode;
wire rr_reg_en;
 
reg ds_delay_sig;
 
reg prescale_reg_en_sig;
assign prescale_reg_en = prescale_reg_en_sig;
 
reg ctr_reg_en_sig;
assign ctr_reg_en = ctr_reg_en_sig;
 
reg sr_reg_en_sig;
assign sr_reg_en = sr_reg_en_sig;
 
reg to_reg_en_sig;
assign to_reg_en = to_reg_en_sig;
 
reg addr_reg_en_sig;
assign addr_reg_en = addr_reg_en_sig;
 
reg dr_reg_en_sig;
assign dr_reg_en = dr_reg_en_sig;
 
reg as_d_sig;
assign  as_d =  as_d_sig;
 
reg ds_d_sig;
assign ds_d = ds_d_sig;
 
reg data_ie_sig;
assign data_ie = data_ie_sig;
 
//reg core_en_sig;
//assign core_en = core_en_sig;
 
//reg inter_en_sig;
//assign inter_en = inter_en_sig;
 
//reg mode_sig;
//assign mode = mode_sig;
 
//reg master_rw_sig;
//assign master_rw = master_rw_sig;
 
//reg ack_sig;
//assign ack = ack_sig;
 
//reg rep_start_sig;
//assign rep_start = rep_start_sig;
 
reg [7:0]data_sig;
assign data = dr_reg;
 
reg [7:0]prescale_sig;
assign prescale = prescale_sig;
 
reg [7:0]time_out_sig;
assign time_out_reg = time_out_sig;
 
reg [7:0]slave_add_sig;
assign slave_add = slave_add_sig;
 
//reg [7:0]data_out_sig;
//assign data_out = data_out_sig;
 
reg decode_sig;
assign decode = decode_sig;
 
//reg inter_rst_sig;
//assign inter_rst = inter_rst_sig;
 
//reg halt_sig;
//assign halt = halt_sig;
assign data_en = dr_reg_en_sig;
 
reg rr_reg_en_sig;
assign rr_reg_en = rr_reg_en_sig;
 
 
 
assign			core_en	 	=	ctr_reg [7]; 
assign			inter_en	=	ctr_reg [6];
assign			mode 	 	=	ctr_reg [5];
assign			master_rw	=	ctr_reg [4];
assign			ack 	 	=	ctr_reg [3];
assign			rep_start	=	ctr_reg [2];
assign			inter_rst	=	ctr_reg [1];
assign			halt	 	=	ctr_reg [0];
 
 
 
 
 
 
//generating delayed version of inputs for detection of rising and falling edge.
//////////////////////////////////////////////////////////////////////////////
 
always@(posedge clk or posedge rst)
begin
 
if(rst)
begin
	as_delay_sig<=1'b0;
	as_d_sig<=1'b0;
	ds_delay_sig<=1'b0;
	ds_d_sig<=1'b0;
end
 
else
begin
	as_delay_sig<=as;
	as_d_sig<=as_delay_sig;
	ds_delay_sig<=ds;
	ds_d_sig<=ds_delay_sig;
end
end
 
always@(posedge clk or posedge rst)
begin
	if(rst)
		decode_sig<=1'b0;
	else if(!as_d && as)
		decode_sig<=1'b1;
	//else
		//decode_sig<=1'b0;
end
 
//address decoding logic
///////////////////////
 
//always@(posedge clk or posedge rst)
always@(rst or as or add_bus or posedge time_rst)
begin
 
if(rst || time_rst)
begin
prescale_reg_en_sig<=1'b0;
ctr_reg_en_sig<=1'b0;
sr_reg_en_sig<=1'b0;
to_reg_en_sig<=1'b0;
addr_reg_en_sig<=1'b0;
dr_reg_en_sig<=1'b0;
rr_reg_en_sig <= 1'b0;
 
//add_match_sig<=1'b0;
end
 
 
 
else if(as)
begin
		if(add_bus == `PRER)
		begin
			rr_reg_en_sig <= 1'b0;
			prescale_reg_en_sig<=1'b1;
			ctr_reg_en_sig<=1'b0;
			sr_reg_en_sig<=1'b0;
			to_reg_en_sig<=1'b0;
			addr_reg_en_sig<=1'b0;
			dr_reg_en_sig<=1'b0;
			//add_match_sig<=1'b1;
		end
 
		else if(add_bus == `CTR)
		begin
			rr_reg_en_sig <= 1'b0;
			prescale_reg_en_sig<=1'b0;
			ctr_reg_en_sig<=1'b1;
			sr_reg_en_sig<=1'b0;
			to_reg_en_sig<=1'b0;
			addr_reg_en_sig<=1'b0;
			dr_reg_en_sig<=1'b0;
			//add_match_sig<=1'b1;
		end
 
		else if(add_bus == `SR)
		begin
			rr_reg_en_sig <= 1'b0;
			prescale_reg_en_sig<=1'b0;
			ctr_reg_en_sig<=1'b0;
			sr_reg_en_sig<=1'b1;
			to_reg_en_sig<=1'b0;
			addr_reg_en_sig<=1'b0;
			dr_reg_en_sig<=1'b0;
			//add_match_sig<=1'b1;
		end
 
		else if(add_bus == `TO)
		begin
			rr_reg_en_sig <= 1'b0;
			prescale_reg_en_sig<=1'b0;
			ctr_reg_en_sig<=1'b0;
			sr_reg_en_sig<=1'b0;
			to_reg_en_sig<=1'b1;
			addr_reg_en_sig<=1'b0;
			dr_reg_en_sig<=1'b0;
			//add_match_sig<=1'b1;
		end
 
		else if(add_bus == `ADDR)
		begin
			rr_reg_en_sig <= 1'b0;
			prescale_reg_en_sig<=1'b0;
			ctr_reg_en_sig<=1'b0;
			sr_reg_en_sig<=1'b0;
			to_reg_en_sig<=1'b0;
			addr_reg_en_sig<=1'b1;
			dr_reg_en_sig<=1'b0;
			//add_match_sig<=1'b1;
		end
 
		else if(add_bus == `DR)
		begin
 
			prescale_reg_en_sig<=1'b0;
			ctr_reg_en_sig<=1'b0;
			sr_reg_en_sig<=1'b0;
			to_reg_en_sig<=1'b0;
			addr_reg_en_sig<=1'b0;
			dr_reg_en_sig<=1'b1;
			rr_reg_en_sig <= 1'b0;
			//add_match_sig<=1'b1;
		end
 
		else if(add_bus == `RR)
		begin
			rr_reg_en_sig <= 1'b1;
			prescale_reg_en_sig<=1'b0;
			ctr_reg_en_sig<=1'b0;
			sr_reg_en_sig<=1'b0;
			to_reg_en_sig<=1'b0;
			addr_reg_en_sig<=1'b0;
			dr_reg_en_sig<=1'b0;
			//add_match_sig<=1'b1;
		end
 
		else
		begin
			rr_reg_en_sig <= 1'b0;
			prescale_reg_en_sig<=1'b0;
			ctr_reg_en_sig<=1'b0;
			sr_reg_en_sig<=1'b0;
			to_reg_en_sig<=1'b0;
			addr_reg_en_sig<=1'b0;
			dr_reg_en_sig<=1'b0;
			//add_match_sig<=1'b0;
		end
 
 
end
else
begin
			prescale_reg_en_sig<=1'b0;
			ctr_reg_en_sig<=1'b0;
			sr_reg_en_sig<=1'b0;
			to_reg_en_sig<=1'b0;
			addr_reg_en_sig<=1'b0;
			dr_reg_en_sig<=1'b0;
			rr_reg_en_sig <= 1'b0;
	end
 
end
 
//assigning value of data_ie line
//////////////////////////////////
always@(posedge clk or posedge rst)
begin
	if(rst)
		data_ie_sig<=1'b0;
	else if(!ds_d && ds)
		data_ie_sig<=1'b1;
 
end
 
 
//read data to/from the register specified by processor addrress.
 
 
//always@(rst or addr_reg_en or ctr_reg_en or dr_reg_en or sr_reg_en or prescale_reg_en or to_reg_en or data_ie or rw or data_in )
 
always@(posedge clk or posedge rst)
begin
if(rst)
begin
	sr_reg <= 8'b0;
	dr_reg <= 8'b0;
	rr_reg <= 8'b0;	
//ctr_reg <= 8'b0;
end
 
/*else if(ctr_reg_en) 
begin
	//sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec};
	ctr_reg <= data_in;
end*/
else
begin
		sr_reg <= {byte_trans,slave_addressed,bus_busy,arb_lost,time_out,slave_rw,inter,ack_rec};
		rr_reg <= i2c_data;
end
end
 
always@(posedge clk or posedge rst or posedge time_rst)
begin
	if(rst || time_rst)
	begin
		//initializing control register
		ctr_reg <= 8'b0;
		/*core_en_sig <= 1'b0;
		inter_en_sig <= 1'b0;
		mode_sig <= 1'b0;
		master_rw_sig <= 1'b0;
		ack_sig <= 1'b0;
		rep_start_sig <= 1'b0;
		inter_rst_sig<=1'b0;*/
		//initializing data and timer register
		data_sig <= 8'b00000000;
		prescale_sig <= 8'b00000000;
		time_out_sig <= 8'b00000000;
		data_out     <= 8'b00000000;
	end
 
	else if (data_ie)
	begin
		//address register
		if(addr_reg_en)						//if address matches with slave address register
		begin
		  if(rw)						//processor write cycle
			slave_add_sig <= {data_in[7:1] , 1'b0};
		  else							//processor read cycle
			data_out <= slave_add;
		end
 
		//control register
		if(ctr_reg_en)						//if address matches with cntrol register
		begin
		  if(rw)						//processor write cycle
		  //begin
			/*core_en_sig	 	<=	#2	ctr_reg [7];
			inter_en_sig 	<=	#2	ctr_reg [6];
			mode_sig 		<=	#2	ctr_reg [5];
			master_rw_sig	<= 	#2	ctr_reg [4];
			ack_sig 	 	<=	#2	ctr_reg [3];
			rep_start_sig	<=	#2	ctr_reg [2];
			inter_rst_sig	<=	#2	ctr_reg [1];
			halt_sig		<=	#2	ctr_reg [0];*/
		  //end
 
		  //else
			ctr_reg <= data_in;							//processor read cycle
			else
	  		data_out <= ctr_reg;
		end  	
 
		else if(!byte_trans && bus_busy)
			ctr_reg[1:0] <= 2'b0;
		//data register
 
		if(dr_reg_en)
		begin
		  if(rw)
			dr_reg <= data_in;
		  else
			data_out <= dr_reg;
		end
 
		if(rr_reg_en)
		begin
			data_out <= rr_reg;
		end
 
		//staus register
 
		if(sr_reg_en)
		begin
		  	if(!rw)
		  	//begin
				//if(data_in[0]==1'b0)	
				//inter_rst_sig <= 1'b0;
				//else
				//inter_rst_sig <= 1'b1;
		  	//end	
			//else
			//begin
				data_out <= sr_reg;
				//inter_rst_sig<=1'b0;
			//end
			//else
				//inter_rst_sig<=1'b0;
 
		end
 
 
		//prescale register
 
		if(prescale_reg_en)
		begin
		  if(rw)
			prescale_sig <= data_in;
		  else
			data_out <= prescale;
		end	
 
		//time_out register
 
		if(to_reg_en)
		begin
		  if(rw)
			time_out_sig <= data_in;
		  else
			data_out <= time_out_reg;
		end
	end
end
 
//assigning values to bidirectional bus
//////////////////////////////////////
 
//assign data_bus = (!rw && data_ie) ? data_out : 8'bzzzzzzzz;
//assign data_in  = (rw)  ? data_bus : 8'bzzzzzzzz;
 
//interuupt pin to processor
assign irq = (inter && inter_en) ? 1'b1 : 1'b0;
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.