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

📄 i2c_master.v

📁 FPGA设计的I2C总线控制器的MASTER端的程序
💻 V
字号:
// ********************************************************************* //
// Filename: i2c_master.v                                                //
// Projects: STiMi-Receiver                                              //
// Author  : XQ-Wang                                                     //
// Date    : 2007-06-25                                                  //
// Version : 1.0                                                         //
// ********************************************************************* //

`timescale	1ns/1ps

module i2c_master(SYS_CLK, RST, RD, WR, DATA, DTyp, DNum, SCL, SDA, ACK);

input           SYS_CLK  ;
wire            SYS_CLK  ;
input           RST  ;
wire            RST  ;
input           RD   ;
wire            RD   ;
input           WR   ;
wire            WR   ;
inout     [7:0] DATA ;
wire      [7:0] DATA ;
input     [2:0] DTyp ;
wire      [2:0] DTyp;
input     [7:0] DNum ;
wire      [7:0] DNum ;

output          SCL  ;
wire            SCL  ;
inout		SDA  ;
wire		SDA  ;
output		ACK  ;
wire		ACK  ;
//output		SDA_SEL  ;
wire		SDA_SEL  ;

//------------------------------------------------
reg	[7:0]	chip_id_slave;
reg	[7:0]	addr_slave;
reg	[7:0]	data_to_slave;

wire	[7:0]	data_from_slave;
wire		SDA_in;
wire		SDA_out;

reg	[7:0]	dnum_cnt;
reg     [2:0]   dtype;	
reg	[9:0]	data_cnt;

reg	[7:0]	clk_cnt;
//----------- Generate SCL ---------------------
parameter	CLK_PERIOD	=	8'b10010110; //60M/400K=150

always @(negedge SYS_CLK)
begin
	if(RST)
		clk_cnt <= 8'b0;
	else
	begin
		if(clk_cnt==CLK_PERIOD)
			clk_cnt <= 8'b00000001;
		else
			clk_cnt <= clk_cnt + 1;
	end
end

i2c_core	INST_I2C(
	.SYS_CLK(SYS_CLK) , 
	.RST(RST)         , 
	.RD(RD)           , 
	.WR(WR)           , 
	
	.Chip_id(chip_id_slave), 
	.Addr(addr_slave)      ,
	.DATA_in(data_to_slave),
	.DTyp(DTyp)            , 
	.DNum(DNum)            ,
	 
	.DATA_out(data_from_slave), 
	.SCL(SCL)                 , 
	.SDA_in(SDA_in)           , 
	.SDA_out(SDA_out)         ,
	.SDA_sel(SDA_SEL)           ,
	.ACK(ACK)
	);

//---------------- Data Output -----------------
assign		SDA    = SDA_SEL ?	1'bz : SDA_out;
assign		SDA_in = SDA_SEL ? SDA  : 1'b1   ;
//assign		DATA = (link_read)  ?	data_from_slave	: 8'hzz;


//----------- Data Buf --------------------------	
always @(posedge SYS_CLK, posedge RST)
begin
	if(RST)
	begin
		dtype    <= 3'b0;
		dnum_cnt <= 8'b0;
	end
	else if(WR || RD)
	begin
		dtype    <= DTyp;
		dnum_cnt <= DNum;
	end
	else if(!WR && !RD)
	begin
		chip_id_slave <= 8'b0;
		addr_slave    <= 8'b0;
		data_to_slave <= 8'b0;
		data_cnt      <= 10'b0;
		dtype         <= 3'b0;
		dnum_cnt      <= 8'b0;
	end
end

always @(posedge SYS_CLK, posedge RST)
begin
	if(RST)
	begin
		chip_id_slave <= 8'b0;
		addr_slave    <= 8'b0;
		data_to_slave <= 8'b0;
		data_cnt      <= 10'b0;
	end
	else if(clk_cnt==(CLK_PERIOD>>1))
	begin
		if(WR)
		begin 
			
			
			case(dtype)
			4'b001:	begin
				if(data_cnt==0)
				begin
					chip_id_slave <= DATA;
					data_cnt <= data_cnt + 1;
				end
				else if(!ACK)
				begin
					if(data_cnt[0] && data_cnt<(dnum_cnt<<1+1))
					begin
						addr_slave <= DATA;
						data_cnt <= data_cnt +1;
					end
					else if(!data_cnt[0] && data_cnt<(dnum_cnt<<1+1))
					begin
						data_to_slave <= DATA;	
						data_cnt <= data_cnt +1;
					end
					else if(data_cnt==(dnum_cnt<<1+1))
						data_cnt      <= 10'b0;
				end
			end
			4'b010:	begin
				if(data_cnt==0)
				begin
					addr_slave <= DATA;
					data_cnt   <= data_cnt + 1;
				end
				if(!ACK)
				begin
					if(!data_cnt[0] && data_cnt<(dnum_cnt<<1))
					begin
						addr_slave <= DATA;
						data_cnt <= data_cnt +1;
					end
					else if(data_cnt[0] && data_cnt<(dnum_cnt<<1))
					begin
						data_to_slave <= DATA;	
						data_cnt <= data_cnt +1;
					end
					else if(data_cnt==(dnum_cnt<<1))
						data_cnt      <= 10'b0;
				end
			end
			4'b101:	begin
				if(data_cnt==0)
				begin
					chip_id_slave <= DATA;
					data_cnt <= data_cnt + 1;
				end
				else if(!ACK)
				begin
					if(data_cnt==1)
					begin
						addr_slave <= DATA;
						data_cnt <= data_cnt +1;
					end
					else if(data_cnt<(dnum_cnt+2))
					begin
						data_to_slave <= DATA;	
						data_cnt <= data_cnt +1;
					end
					else if(data_cnt==(dnum_cnt+2))
						data_cnt      <= 10'b0;
				end
			end
			4'b110:	begin
				if(data_cnt==0)
				begin
					addr_slave <= DATA;
					data_cnt   <= data_cnt + 1;
				end
				else if(!ACK)
				begin
					if(data_cnt<(dnum_cnt+2))
					begin
						data_to_slave <= DATA;	
						data_cnt <= data_cnt +1;
					end
					else if(data_cnt==(dnum_cnt+2))
						data_cnt      <= 10'b0;
				end
			end
			endcase
		end
	end
end

endmodule

⌨️ 快捷键说明

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