⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c_slave.v

📁 可以支持连续读写的i2cslave源码
💻 V
字号:
//***********************************//i2c_slave.v     v1.0   2007-05-27//initial//***********************************//v1.1  2007-05-28// Add neg_counter[9:0],cycle,scl_mid_pulse. neg_counter counts numbers when SCL=0; the result stored to cycle register;// scl_mid_pulse is the pulse between one negedge SCL and one posedge SCL. that is the midddle time from last negedge SCL to//next   posedge SCL.//***********************************//v2.0  2007-05-30//Can be write or read in burst mode;//2.2 2007-06-01  15:00//Can read data from "input_data.dat" file and send to I2C master//Can receive data from I2C master ,then save them to the "receive_data.dat" file//Modify define to parameter mode//*************************************module i2c_slave(clk,SCL,reset,SDAI,SDAO);input clk,SCL,reset,SDAI;output SDAO;////`include "i2c_slave_userconf.v"parameter	input_data= "input_data.dat";parameter	receive_data= "receive_data.dat";parameter	IDLE= 	3'b000;		//state machine parameter	START=	3'b001;parameter	ADDRESS= 3'b010;parameter	ACK= 	3'b011;parameter	DATA=	3'b100;	parameter	DATA_ACK= 3'b101;parameter	CONT_END= 4'b1000;	parameter	SLAVE_ADDRESS= 7'b0000001;	//define this I2C_SLAVE ip own address	 parameter	MEMLEN= 10;    //memory array length, can modify if u need//wire scl;assign scl = SCL;//wire SDAI;reg  SDAO; //reg [2:0] state;//reg 	sda_reg;		reg 	sda_reg_delayed;reg	scl_reg=0;reg	scl_reg_delayed=0;//reg [7:0] out_reg=0;reg [7:0] in_reg;//reg 	r_w_bit;	//read or write bit//reg 	ack_flag=0;reg 	start_pulse;reg	start_detect;//reg	stop_pulse;reg 	stop_detect;//reg	scl_pulse;reg	scl_neg_pulse;//reg	out_en=0;	//output enablereg	sda_out;//reg	in_reg_enable;//reg	[3:0]	bit_counter;	//bit counterreg	[7:0]	word_w_address;	//the data input i2c_slave will be stored in word_w_address register//reg	[7:0]	WORD_R_ADDRESS;//reg	[9:0]	neg_counter;reg	[9:0]	cycle;reg	scl_mid_pulse;		//sign the middle time when SCL is low//reg 	[7:0] memory[0:MEMLEN - 1];	//stored reading data from files//integer		N=0;integer		M;			//if the number of reading data is above 16, //integer rev;////initialbegin	$readmemh (input_data, memory);		//read data into memory	rev=$fopen(receive_data);				$fdisplay(rev,"Data received from I2C master as following:\n");end//output to receive_data.dat filealways @(posedge clk)if (N<MEMLEN+2)begin	if (out_en & scl_pulse)	begin		if (N>0)			begin			$fdisplay(rev,"BYTE%h=%h",N,word_w_address);			N<=N+1;			end		else			N<=N+1;		endendelse	$fclose(rev);	//sda_samplealways @(posedge clk)	if(~reset)		begin		sda_reg <= 1;		sda_reg_delayed <= 1;		end	else		begin			sda_reg <= SDAI;		sda_reg_delayed <= sda_reg;		end//start_pulsealways @(posedge clk)	if (~reset)	   start_pulse <= 0;	else if (~sda_reg & sda_reg_delayed & SCL) start_pulse <= 1;	else start_pulse <= 0;//start_detectalways @(posedge clk)	if (~reset) 	   start_detect <= 0;	else if (start_pulse)    start_detect <= 1;	else if (~SCL)	start_detect <= 0;	else 	start_detect <= start_detect;//stop_pulsealways @(posedge clk)	if (~reset)	   stop_pulse <= 0;	else if (sda_reg & ~sda_reg_delayed & SCL) stop_pulse <= 1;	else stop_pulse <= 0;//stop_detectalways @(posedge clk)	if (~reset)	   stop_detect <= 0;	else if (stop_pulse) 	stop_detect<=1;	else if (~SCL) stop_detect<=0;	else stop_detect<=stop_detect;//scl_samplealways @(posedge clk)	if (~reset)		begin		scl_reg<=1;		scl_reg_delayed<=1;		end	else		begin		scl_reg<=scl;		scl_reg_delayed<=scl_reg;		end	//scl_posedgealways @(posedge clk)	if (~reset)	   scl_pulse<=0;	else if (scl_reg & ~scl_reg_delayed )		scl_pulse <=1;	else 		scl_pulse <=0;				//scl_neg_posedgealways @(posedge clk)	if (~reset)	   scl_neg_pulse<=0;	else if (~scl_reg & scl_reg_delayed ) 		scl_neg_pulse<=1;	else 		scl_neg_pulse<=0;//neg_counteralways @(posedge clk) 	if (~reset) 	neg_counter<=0;	else if (~scl)			neg_counter<=neg_counter+1;	else if (scl_pulse)		begin			neg_counter<=0;		cycle<=neg_counter;	   	end//scl_mid_pulsealways @(posedge clk)	if (~reset)	scl_mid_pulse <=0;	else if (~scl & (neg_counter==cycle/2) & (neg_counter>0))				scl_mid_pulse <=1;			else		scl_mid_pulse<=0;	//moorealways @(posedge clk )if (~reset)	state<=IDLE;elsebegin////statecase (state)//////IDLE		IDLE:	   	begin		if (start_detect & scl)			   state <= START;		else 		begin			state <=IDLE;			in_reg_enable <= 0;		end	end//////START	START:	begin		if (start_detect & scl )	state <= START;		else if (stop_detect & scl)	state <= IDLE;		else if (scl_mid_pulse) 				////scl		begin			bit_counter <=0;			in_reg_enable <=1;		end		else if (in_reg_enable)		begin			in_reg_enable <=0;			bit_counter =bit_counter+1;			ack_flag<=0;			state<=ADDRESS;		end	end//////ADDRESS	ADDRESS:	begin		if (start_detect & scl) state <=START;		else if (stop_detect & scl) state<=IDLE;		else if (scl_pulse & (bit_counter<=CONT_END)) in_reg_enable<=1;    		else if (in_reg_enable) 			begin			in_reg_enable<=0;			bit_counter<=bit_counter+1;			state <=ADDRESS;			end		else if (bit_counter==CONT_END) 			begin			if (in_reg[7:1]==SLAVE_ADDRESS )		//slave address				begin				r_w_bit<=in_reg[0];				M<=0;				ack_flag<=0;				state<=ACK;				end					else				begin				sda_out<=1;				state <=IDLE;				end			end	end//////ACK	ACK:	begin		if (start_detect & scl)    	state<=START;		else if (stop_detect & scl) 	state<=IDLE;		else if  (~ack_flag & scl_neg_pulse) 			////////////neg			begin			out_en <=1;						ack_flag <=1;			end		else if (ack_flag & scl_neg_pulse) 			////////////neg			begin				out_en <=0;			ack_flag<=0;			sda_out<=1;			bit_counter<=0;			state<=DATA;			end		    else			begin				sda_out<=0;				bit_counter<=0;				state<=ACK;			end	end//////DATA	DATA:	begin		if (start_detect & scl)    state <=START;		else if (stop_detect & scl) state<=IDLE;		else if (~r_w_bit & (bit_counter==4'b0000) & scl_mid_pulse ) ///////////pos			begin				in_reg_enable<=1;			//	bit_counter <=bit_counter+1;			end		else if (in_reg_enable & scl_pulse & (bit_counter<CONT_END))			begin			//	in_reg_enable <=0;		      		bit_counter <=bit_counter+1;				state <=DATA;				end		else if (~r_w_bit & (bit_counter==CONT_END))			begin				in_reg_enable <=0;		      		ack_flag <=0;		     	 	word_w_address <= in_reg;		//save data from I2C master				state <= DATA_ACK;			end		else if (r_w_bit & (bit_counter==4'b0000) )				begin				out_en<=1;				bit_counter <=bit_counter+1;				out_reg<=memory[M];			//send memory data to I2C master			end		else if (r_w_bit & (bit_counter<CONT_END) & scl_neg_pulse)	///////////neg 				bit_counter <=bit_counter+1;				else if (r_w_bit & (bit_counter ==CONT_END) & scl_neg_pulse)	//////////neg			begin						      						if (M<MEMLEN)					M<=M+1;				else					M<=0;				bit_counter<=0;		     		ack_flag <=0;				state <= DATA_ACK;			end							end			//////DATA_ACK	DATA_ACK:	begin		if (start_detect & scl)    state <=START;		else if (stop_detect & scl) state<=IDLE;		else if (~r_w_bit & scl_neg_pulse & ~ack_flag)			/////////neg			begin 				out_en <=1;		      		sda_out <=0;		      		ack_flag <=1;						end		else if (r_w_bit & scl_neg_pulse & ~ack_flag)         	////////////neg  			begin 				ack_flag<=0;		      		sda_out <=1;		     			///add 5-29							if (~SDAI & (M<MEMLEN))					begin					out_en<=1;			///0					bit_counter<=0;					ack_flag <=0;					state <= DATA;			///IDLE					end				else					begin					out_en <=0;										state <= IDLE;				///IDLE					M<=0;					end			end	////add 5-29		else if (~r_w_bit & scl_neg_pulse)			////////////neg						begin				if (~SDAI)  					begin					out_en<=0;			///0					bit_counter<=0;					ack_flag <=0;					state <= DATA;			///IDLE				end			end	enddefault: 	state <= state;			endcaseend//moore end//cou_oalways @(posedge clk)case(bit_counter)	4'b0001: sda_out<= out_reg[7];				4'b0010: sda_out<= out_reg[6];	4'b0011: sda_out<= out_reg[5];	4'b0100: sda_out<= out_reg[4];	4'b0101: sda_out<= out_reg[3];	4'b0110: sda_out<= out_reg[2];	4'b0111: sda_out<= out_reg[1];	4'b1000: sda_out<= out_reg[0];	default: sda_out<= sda_out;endcase//cou_ialways @(posedge clk)if (in_reg_enable)   begin	case(bit_counter)	4'b0000: in_reg[7] <= sda_reg;	4'b0001: in_reg[6] <= sda_reg;	4'b0010: in_reg[5] <= sda_reg;	4'b0011: in_reg[4] <= sda_reg;	4'b0100: in_reg[3] <= sda_reg;	4'b0101: in_reg[2] <= sda_reg;	4'b0110: in_reg[1] <= sda_reg;	4'b0111: in_reg[0] <= sda_reg;	default: in_reg <= in_reg;	endcase  end//Palways @(posedge clk)	if (ack_flag) SDAO<=0;	else if (out_en)    	SDAO <= sda_out;  	else SDAO <= 1;endmodule//END......

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -