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

📄 ms_core.v

📁 I2C总线的verilog语言实现
💻 V
📖 第 1 页 / 共 2 页
字号:
///////////////////////////////////////ms_core.v//////////////////////////////////////////////////////////////////////////														      //			//Design engineer:	Ravi Gupta										      //		//Company Name	 :	Toomuch Semiconductor	//Email		 :	ravi1.gupta@toomuchsemi.com								      //	//														      //	//Purpose	 :	This is the core which will be used to interface I2C bus.				      //	//Created	 :	23-11-07										      //														      //		//Modification : Changes made in data_reg_ld									      //															      //	//Modification : Change byte_trans generation bit								      //															      //		//Modification : Implemented a halt bit that will be generated at the completion of 9th scl pulse in master_mode only //														      //					//Modification : After core reset(time out feature) core will go in idle escaping stop generation so need to clear    ////all 														      ////of status register.    											      //																      ////Modification : Remove the sm_state clause,so that even if there is no acknowledegement it will not stop the         ////generation of SCL and SDA 											      //				//untill it gets command to generate stop from processor.							      //															      //		//Modification : Now also checking for detect_start in acknowledgement state for repeted start condition. 	      //	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// module core(clk,rst,sda_oe,sda_in,sda_o,scl_oe,scl_in,scl_o,ack,mode,rep_start,master_rw,data_in,slave_add,bus_busy,byte_trans,slave_addressed,arb_lost,slave_rw,time_out,inter,ack_rec,i2c_up,time_out_reg,prescale_reg,inter_rst,inter_en,halt_rst,data_en,time_rst,h_rst);////////////////////////////////////////////////signal defination////////////////////////////////////////////////////////////////input	clk;			//System Clockinput	rst;			//Main Resetoutput	sda_oe;			//I2C serial data line output to be connected to control line of bidirectional buffer on physical SDA lineinput	sda_in;			//I2C serial data line inputoutput	sda_o;			//I2C sda line always asssign to zero this is to be connected to input of bidirectional buffer on physical SDA lineoutput	scl_oe;			//I2C serial clock line output to be connected to control line of bidirectiional buffer on physical scl lineinput	scl_in;			//I2C serial clock line inputoutput	scl_o;			//SCL output line to be connected to input of bidirectional lineinput	ack;			//Acknowledgement signal from control registerinput	mode;			//master/slave mode selectinput	rep_start;		//repeated startinput	master_rw;		//command to core in master modeinput	[7:0]data_in;		//data from processor to be outputed on I2Cinput	[7:0]slave_add;		//I2C slave addressinput data_en;output time_rst;input h_rst;//status signal:output	bus_busy;		//bus busyinout	byte_trans;		//transfer of byte is in progress_reg_eninout	slave_addressed;	//addressed as slaveinout	arb_lost;		//arbitration has lostinout	slave_rw;		//indicates the operation by slaveinout	time_out;		//indicates that SCL LOW time has been exceededoutput	inter;			//interrupt pending,will be used for interrupting processorinput	inter_rst;		//use to clear the interruptinput	inter_en;		//processor wants to take interrupt or not//signal for processorinput halt_rst;output	ack_rec;		//indicates that ack has been recieved,will be used to inform if master reciever wants to terminate the transferoutput	[7:0]i2c_up;		//I2C data for micro processor//timing control registersinput [7:0]time_out_reg;		//max SCL low period.input [7:0]prescale_reg;		//clock divider for generating SCL frequency./////////////////////////////////////////End of port defination//////////////////////////////////////////////////////////////////wire master_slave,arbitration_lost,bb,gen_start,rep_start,byte_trans_delay,byte_trans_fall;								 //wire scl_out,sda_out,clk_cnt_enable,clk_cnt_rst,bit_cnt_enable,bit_cnt_rst,timer_cnt_enable,timer_cnt_rst,scl_in,sda_in,sda_out_reg,stop_scl_reg,master_sda,	gen_stop;wire master_sda,scl_in,gen_stop,sm_stop,detect_stop,detect_start,addr_match,core_rst,stop_scl,scl_out,neg_scl_sig,sda_sig;//reg [7:0]clk1_cnt,bit1_cnt,timer1_cnt;reg posedge_mode,negedge_mode;reg [2:0]scl_state;reg [1:0]state;reg [2:0]scl_main_state; wire [7:0] add_reg,shift_reg;wire [7:0]clk_cnt,bit_cnt;reg  [7:0]time_cnt;reg  [7:0]i2c_up; wire bit_cnt_enable,bit_cnt_rst,clk_cnt_enable,clk_cnt_rst,data_reg_ld,data_reg_en,sda_in,serial_out,i2c_serial_out,add_reg_ld,add_reg_en,posedge_mode_sig,negedge_mode_sig,interrupt;wire [7:0]zero;wire [7:0]reg_clr;wire slave_sda,sda_out,halt,arb_rst,interrupt_rst,d_detect_stop;shift shift_data(neg_scl,rst,data_reg_ld,data_reg_en,sda_in,data_in,serial_out,shift_reg);	//shift register for transferring the datashift shift_add(neg_scl,rst,add_reg_ld,add_reg_en,sda_in,reg_clr,i2c_serial_out,add_reg);	//shift register for transferring addresscounter clock_counter(clk,rst,clk_cnt_enable,clk_cnt_rst,zero,clk_cnt);				//This will count number of clock pulses for prescalecounter bit_counter(neg_scl,rst,bit_cnt_enable,bit_cnt_rst,zero,bit_cnt);			//Implementation of bit counter	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////reg clk_cnt_enable_sig;assign clk_cnt_enable = clk_cnt_enable_sig;reg clk_cnt_rst_sig;assign clk_cnt_rst = clk_cnt_rst_sig;//reg sda_in_sig;//assign sda_in = sda_in_sig;reg sm_stop_sig;assign sm_stop = sm_stop_sig;//reg scl_in_sig;//assign scl_in = scl_in_sig;reg gen_start_sig;assign gen_start = gen_start_sig;reg gen_stop_sig;assign gen_stop = gen_stop_sig;reg master_slave_sig;assign master_slave = master_slave_sig;reg detect_start_sig;assign detect_start=detect_start_sig;reg detect_stop_sig;assign detect_stop=detect_stop_sig;reg byte_trans_sig;assign byte_trans= byte_trans_sig;reg bb_sig;assign bb=bb_sig;reg slave_addressed_sig;assign slave_addressed=slave_addressed_sig; reg slave_rw_sig;assign slave_rw=slave_rw_sig;reg inter_sig;assign inter=inter_sig;	assign interrupt=inter_sig;reg time_out_sig;assign time_out=time_out_sig;reg ack_rec_sig;assign ack_rec=ack_rec_sig;reg add_reg_enable_sig;assign add_reg_en=add_reg_enable_sig;reg data_reg_en_sig;assign data_reg_en=data_reg_en_sig;reg data_reg_ld_sig;assign data_reg_ld=data_reg_ld_sig;reg stop_scl_sig;assign stop_scl=stop_scl_sig;reg core_rst_sig;assign core_rst=core_rst_sig;reg sda_out_sig;assign sda_out=sda_out_sig;reg scl_out_sig;assign scl_out=scl_out_sig;reg master_sda_sig;assign master_sda=master_sda_sig;reg slave_sda_sig;assign slave_sda=slave_sda_sig;reg arbitration_lost_sig;assign arbitration_lost=arbitration_lost_sig;reg arb_lost_sig;assign arb_lost=arb_lost_sig;reg byte_trans_delay_sig;assign byte_trans_delay=byte_trans_delay_sig;reg byte_trans_fall_sig;assign byte_trans_fall=byte_trans_fall_sig;reg halt_sig;assign halt = halt_sig;reg arb_rst_sig;assign arb_rst=arb_rst_sig;reg interrupt_rst_sig;assign interrupt_rst=interrupt_rst_sig;reg rep_start_sig;assign time_rst = core_rst;reg d_detect_stop_sig;assign d_detect_stop = d_detect_stop_sig;reg d1_detect_stop_sig;assign bus_busy = bb;assign reg_clr=8'b00000000;assign neg_scl_sig=(~scl_in);assign neg_scl=neg_scl_sig;assign zero=8'b00000000;assign posedge_mode_sig=posedge_mode;assign negedge_mode_sig=negedge_mode;assign sda_o = 1'b0;	//assign this to 0 alwaysassign scl_o = 1'b0;parameter	scl_idle=3'b000,scl_start=3'b001,scl_low_edge=3'b010,scl_low=3'b011,scl_high_edge=3'b100,scl_high=3'b101;parameter	scl_address_shift=3'b001,scl_ack_address=3'b010,scl_rx_data=3'b011,scl_tx_data=3'b100,scl_send_ack=3'b101,scl_wait_ack=3'b110,scl_main_idle=			3'b000;parameter	a=2'b00,b=2'b01,c=2'b10;////////////////////SCL Generator/////////////////////////////////This machine will generate SCL and SDA when in master mode.It will//also generate START and STOP condition.//always@(scl_state or arbitration_lost or sm_stop or gen_stop or rep_start//		or bb or gen_start or master_slave or clk_cnt or bit_cnt or//		scl_in  or sda_out or master_sda or core_rst)always@(posedge clk or posedge rst or posedge core_rst or posedge h_rst)begin//State machine initial conditionsif(rst || h_rst)begin	scl_state<=scl_idle;	scl_out_sig<=1'b1;	sda_out_sig<=1'b1;	stop_scl_sig<=1'b0;	clk_cnt_enable_sig<=1'b0;	clk_cnt_rst_sig<=1'b1;	//bit_cnt_rst_sig<=1'b0;	//bit_cnt_enable_sig<=1'b0;endelse if(core_rst)begin	scl_state<=scl_idle;	scl_main_state <= scl_main_idle;	scl_out_sig<=1'b1;	sda_out_sig<=1'b1;	stop_scl_sig<=1'b0;	clk_cnt_enable_sig<=1'b0;	clk_cnt_rst_sig<=1'b1;	slave_addressed_sig<=1'b0;endelsebegin		case (scl_state)					scl_idle:			begin				arb_rst_sig <= 1'b1;				interrupt_rst_sig<=1'b1;				sda_out_sig<=1'b1;				stop_scl_sig<=1'b0;										if(master_slave && !bb && gen_start)					begin 						scl_state<=scl_start;											end			end				scl_start:			begin				arb_rst_sig <= 1'b0;				interrupt_rst_sig<=1'b0;				clk_cnt_enable_sig<=1'b1;				//enable the counter as soon as machine enters in this state.				clk_cnt_rst_sig<=1'b0;				//sda_out_sig<=1'b0;					//generating start condition				stop_scl_sig<=1'b0;			if(clk_cnt == prescale_reg / 3)				sda_out_sig<= 1'b0;									if(clk_cnt == prescale_reg)		//wait for prescale value to over						scl_state<=scl_low_edge;					else						scl_state<=scl_start;			end			scl_low_edge:			begin				clk_cnt_rst_sig<=1'b1;			//This state will generate only SCL negative edge,and reset all the counters				//timer_cnt_enable_sig<=1'b1;			//except timer counter which will be enabled at this state.				//timer_cnt_rst_sig<=1'b0;			//also reseting the timer counter in this state.				scl_out_sig<=1'b0;				scl_state<=scl_low;				stop_scl_sig<=1'b0;			end			scl_low:			begin				clk_cnt_enable_sig<=1'b1;			//enable the clock counter				clk_cnt_rst_sig<=1'b0;				scl_out_sig<=1'b0;												if(arbitration_lost)								stop_scl_sig<=1'b0;						else if(rep_start_sig)							begin									sda_out_sig<=1'b1;								stop_scl_sig<=1'b0;							end												 else if((gen_stop) && ((scl_main_state != scl_ack_address) && (scl_main_state != scl_send_ack)									&& (scl_main_state != scl_wait_ack)))		//Ravi remove sm_stop from oring with gen_stop							begin								sda_out_sig<=1'b0;								stop_scl_sig<=1'b1;																	end  													/*else if(rep_start)							begin									sda_out_sig<=1'b1;								stop_scl_sig<=1'b0;							end*/							else if(clk_cnt == prescale_reg / 3)							begin										sda_out_sig<=master_sda;										stop_scl_sig<=1'b0;																end														else								stop_scl_sig<=1'b0;																	//determine next state.									if(clk_cnt == prescale_reg)					begin						if(bit_cnt == 8'b0000_0111 && arbitration_lost )							scl_state<=scl_idle;						else if(interrupt && inter_en)									//uncomenting out for cheking the core in interrupt mode 							scl_state<=scl_low;						else if(halt)							scl_state<=scl_low;							else							scl_state<=scl_high_edge;					end					else						scl_state<=scl_low;			end																											scl_high_edge:			begin				clk_cnt_rst_sig<=1'b1;				scl_out_sig<=1'b1;				if(gen_stop)				//Ravi sm_stop from oring with gen_stop					stop_scl_sig<=1'b1;									else					stop_scl_sig<=1'b0;				if(!scl_in)					scl_state<=scl_high_edge;				else					scl_state<=scl_high;			end					scl_high:			begin				clk_cnt_enable_sig<=1'b1;				clk_cnt_rst_sig<=1'b0;				scl_out_sig<=1'b1;				if(clk_cnt == prescale_reg) 				begin					if(rep_start_sig)						scl_state<=scl_start;					else if(stop_scl)						scl_state<=scl_idle;																			else						scl_state<=scl_low_edge;				end				else					scl_state<=scl_high;			end								endcaseendend	//Sample the incoming SDA and SCL line with System clock/*always@(posedge clk or posedge rst)begin	if(rst)	begin		//sda_in_sig <= 1'b1;		scl_in_sig <=1'b1;	end	else	begin		if(!scl)			scl_in_sig <= 1'b0;		else			scl_in_sig <= 1'b1;		if(!sda)			sda_in_sig <= 1'b0;		else			sda_in_sig <= 1'b1;				//sda_out_sig <= sda;	endend*///Generartion of control signal from the command based on processor.//This will control generation of start and stop signal.//This will also set the master_slave bit based on MODE signal//if bus is not busy i.e bb = 0always@(posedge clk or posedge rst or posedge h_rst)begin	if(rst || h_rst)	begin		gen_start_sig <= 1'b0;		gen_stop_sig <= 1'b0;		master_slave_sig <= 1'b0;			end	else	begin		if(posedge_mode_sig)			gen_start_sig <= 1'b1;		else if(detect_start)			gen_start_sig <= 1'b0;		if(!arbitration_lost && negedge_mode_sig)			gen_stop_sig <= 1'b1;		else if(detect_stop)			gen_stop_sig <= 1'b0;		if(!bb)			master_slave_sig <= mode;		else			master_slave_sig <= master_slave;	endend//State machine for detection of rising and falling edge of input mode for the generation of START and STOP.always@(posedge clk or posedge rst or posedge h_rst)begin	if(rst || h_rst)	begin		posedge_mode<=1'b0;		negedge_mode<=1'b0;		state<=a;	end	else	begin		case(state)					a:				if(mode==1'b0)				begin					state<=b;					posedge_mode<=1'b0;					negedge_mode<=1'b0;				end								else				begin					state<=c;					posedge_mode<=1'b1;					negedge_mode<=1'b0;				end			b:				if(mode==1'b0)				begin					state<=b;					posedge_mode<=1'b0;					negedge_mode<=1'b0;				end								else				begin					state<=a;					posedge_mode<=1'b1;					negedge_mode<=1'b0;				end			c:				if(mode==1'b0)				begin					state<=a;					posedge_mode<=1'b0;					negedge_mode<=1'b1;				end								else				begin					state<=c;					posedge_mode<=1'b0;					negedge_mode<=1'b0;				end			endcaseendend//This is the main state machine which will be used as both master as well as slave.//This gets triggered at falling edge of SCL.//If stop codition gets detected then it should work as asyn reset.always@(posedge rst or negedge scl_in or posedge detect_stop or posedge core_rst or posedge h_rst)beginif(rst || core_rst || h_rst)begin	scl_main_state<=scl_main_idle;	sm_stop_sig<=1'b0;endelsebegin	case(scl_main_state)	scl_main_idle:				if(detect_start)			scl_main_state<=scl_address_shift;		else if(detect_stop)		begin			scl_main_state<=scl_main_idle;			sm_stop_sig<=1'b0;		end	scl_address_shift:					//machine will remain in this state,unless all the bits of address has been transferred. 				if(bit_cnt == 8'b0000_0111)			scl_main_state<=scl_ack_address;		else if(detect_stop)		begin			scl_main_state<=scl_main_idle;			sm_stop_sig<=1'b0;		end	scl_ack_address:		

⌨️ 快捷键说明

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