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

📄 i2c_slv_ctrl.v

📁 I2c总线 verilog实现
💻 V
字号:
module i2c_slv_ctrl(rst,
					clk,
					dev_addr,
					scl,
					sda,
					dat_in,
					dat_out,
					wr,
					rd,
					reg_addr,
					busy,
					i2c_s,
					i2c_p,
					pos);

input rst,clk;
input [6:0] dev_addr;
input scl;
inout sda;

input [7:0]dat_in;
input busy;

output wr,rd;
output [7:0]reg_addr;
output [7:0]dat_out;


output i2c_s,i2c_p;
output [7:0]pos;



parameter I2C_STA_P = 3'd0;
parameter I2C_STA_S = 3'd1;
parameter I2C_STA_AACK = 3'd2;
parameter I2C_STA_RACK = 3'd3;
parameter I2C_STA_WACK = 3'd4;
parameter I2C_STA_A =	3'd5;
parameter I2C_STA_WD =	3'd6;
parameter I2C_STA_RD =	3'd7;


reg scl_dir; //scl方向控制,1输入,0输出
reg sda_dir; //sda方向控制,1输入,0输出
reg scl_r;
reg	sda_r;
reg _scl,__scl,___scl,_sda,__sda,___sda;

assign sda = sda_dir ? 1'bz : sda_r; 

reg [2:0] i2c_sta;
reg [2:0] bit_pos;

reg	i2c_rw;	//1:r,0:w

reg	[6:0] addr;
reg [7:0] dat_out;
reg [7:0] reg_addr;
reg [7:0] pos;
reg rd,_wr,wr;

wire i2c_s = ___scl && __scl && _scl && ___sda && !__sda && !_sda ;
wire i2c_p = ___scl && __scl && _scl && !___sda &&__sda && _sda;

wire scl_up = !___scl && __scl && _scl;
wire scl_down = ___scl && !__scl && !_scl;

//reg i2c_s,i2c_p,scl_up,scl_down;
always@(posedge clk)
begin
	_scl <= scl;
	_sda <= sda;
	__scl <= _scl;
	__sda <= _sda;
	___scl <= __scl;
	___sda <= __sda;
end

always@(posedge clk)
begin
	if(rst)
		i2c_sta <= I2C_STA_P;
	else begin
		
		if(i2c_s && i2c_sta == I2C_STA_P)		//i2c开始
			i2c_sta <= I2C_STA_S;

		else if(i2c_p)	//i2c停止
			i2c_sta <= I2C_STA_P;
			
		else if(scl_down) begin			//scl下降延
			case(i2c_sta)
			I2C_STA_S:begin	 
				i2c_sta <= I2C_STA_A; 
				
			end
			I2C_STA_A:	begin 
				if(bit_pos == 0)
					if(addr[6:0] == dev_addr)
						i2c_sta <= I2C_STA_AACK;
					else
						i2c_sta <= I2C_STA_P;
				
			end
			I2C_STA_AACK: begin
				i2c_sta <= i2c_rw ? I2C_STA_RD : I2C_STA_WD;	
			end	
			I2C_STA_RD: begin
				if(bit_pos == 0)
					i2c_sta <= I2C_STA_RACK;
			end
					
			I2C_STA_RACK: begin
				if(i2c_rw)
					i2c_sta <= I2C_STA_RD;
				else
					i2c_sta <= I2C_STA_P;
			end
				
			I2C_STA_WD: begin
				if(bit_pos == 0)
					i2c_sta <= I2C_STA_WACK;
			end
					
						
			I2C_STA_WACK:begin
		
				i2c_sta <= I2C_STA_WD;
			end
			
			default:
				i2c_sta <= I2C_STA_P;
										
			endcase
		end
	end	
end

always@(posedge clk)
begin
/*
	if(i2c_sta == I2C_STA_S && scl_down)
		bit_pos <= 7;
	else if(scl_up && (i2c_sta == I2C_STA_A || i2c_sta == I2C_STA_WD))
		bit_pos <= bit_pos - 1;
	else if(scl_down && (i2c_sta == I2C_STA_RD))
		bit_pos <= bit_pos - 1;
*/
	if(scl_down)
		if(i2c_sta == I2C_STA_S)
			bit_pos <= 7;
		else if(i2c_sta == I2C_STA_A 
		|| i2c_sta == I2C_STA_WD
		|| i2c_sta == I2C_STA_RD)
			bit_pos <= bit_pos - 1;
end

always@(posedge clk)
begin
	rd <= 0;
	_wr <= 0;
	sda_r <= 1;
	sda_dir <= 1;
	case(i2c_sta)
	I2C_STA_S:
		if(scl_down)
			pos <= 0;

	I2C_STA_A: 
		if(scl_up)
			if(bit_pos == 0)				
				i2c_rw <= sda;
			else
				addr[bit_pos-1] <= sda;
				
	I2C_STA_WD:
		 if(scl_up) begin
			dat_out[bit_pos] <= sda;
			if(bit_pos == 0) begin
				_wr <= 1;
			end
		 end
	
	I2C_STA_RD: begin
		sda_r <= dat_in[bit_pos]; 
		sda_dir <= 0; 
	end
	
	I2C_STA_AACK: begin 
		sda_r <= busy;	
		sda_dir <= 0;
		if(i2c_rw && scl_up) 
			rd <= 1;
			 
	end
	
	I2C_STA_RACK: begin 
		if(scl_up) begin
			pos <= pos + 1; 
			rd <= ~_sda;
			i2c_rw <= ~_sda;
		end			
	end
	 
	I2C_STA_WACK: begin
		sda_r <= busy; 
		sda_dir <= 0;
		if(scl_up)
			pos <= pos + 1;
	end
	
	endcase
end

always@(posedge clk)
begin
	wr <= 0;
	if(_wr) 
		if(pos == 0)
			reg_addr <= dat_out;
		else
			wr <= 1;
	
end



endmodule

⌨️ 快捷键说明

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