[FPGA][IIC]驱动程序

开发环境

  • [软件]Quartus 13.1
  • [语言]Verilog

源代码

/*Copyright belong to afterdm@qq.com
 *Create data 2020/11/24
 *Last modified data 2020/12/8
 *Version v1.1.0.0
 *Descriptions IIC drive
 *Please delete within 24 hours without special circumstances
*/
/*
*/
module IICdrive(
	input				clk,		//clk signal(50M)
	input				rst,		//reset signal
	input		[7:0]	wdata,		//IIC write data
	output	reg	[7:0]	rdata,		//IIC read data
	input				enaSignal,	//enable siginal
	input				overFlag,	//over state(High level effective)
	input				wrFlag,		//write(0) read(1) state
	output	reg			comSignal,	//complete signal
	output	reg			errorFlag,	//error signal(High level effective)
	output	reg			SCL,		//IIC clk
	inout   			SDA,		//IIC data
	output	reg			align_clk
);
//define parameter
/******define state machine*****/
parameter STsetout	= 6'b00_0001;
parameter STbaction	= 6'b00_0010;
parameter STwrite	= 6'b00_0100;
parameter STread	= 6'b00_1000;
parameter STawait	= 6'b01_0000;
parameter STeaction	= 6'b10_0000;
//define reg
/******define div signal******/
reg drive_clk;
reg [6:0] drive_counter;
/******define state machine***/
reg [5:0] STstate, STnstate;
/******define state signal****/
reg STdone;
/******define count***********/
reg [7:0] IICcount;
/******define templete data***/  
reg [7:0] tempdata;
/******define IIC SDA(inout)**/
reg SDAswitch, SDAout;
//define wire
wire SDAin;
//define assign
assign SDA = (SDAswitch == 1'b1) ? (SDAout) : (1'bz);
assign SDAin = SDA;
//div clk (the input clk is 50M, generate 0.02M = 2vs)
always @(posedge clk or negedge rst) begin
	if(rst == 1'b0) begin
		drive_clk <= 1'b0;
		align_clk <= 1'b0;
		drive_counter <= 7'b0;
	end
	else begin
		if(drive_counter == 7'd99) begin
			drive_counter <= 7'b0;
		end
		else begin
			drive_counter <= drive_counter + 1'b1;
		end
		if(drive_counter == 7'd49) begin
			drive_clk <= 1'b1;
		end
		else begin
			drive_clk <= 1'b0;
		end
		if(drive_counter == 7'd50) begin
			align_clk <= 1'b1;
		end
		else begin
			align_clk <= 1'b0;
		end
	end
end
//state machine
always @(posedge drive_clk or negedge rst) begin
	if(rst == 1'b0) begin
		STstate <= STsetout;
	end
	else begin
		STstate <= STnstate;
	end
end
//state function
always @(*) begin
	STnstate = STsetout;
	case(STstate)
		STsetout	: begin
			if(enaSignal == 1'b1) begin
				STnstate = STbaction;
			end
			else begin
				STnstate = STsetout;
			end
		end
        STbaction   : begin
            if(STdone == 1'b1) begin
                STnstate = STwrite;
            end
            else begin
                STnstate = STbaction;
            end
        end
		STwrite		: begin
			if(STdone == 1'b1) begin
				if(errorFlag == 1'b1) begin
					STnstate = STeaction;
				end
				else begin
					STnstate = STawait;
				end
			end
			else begin
				STnstate = STwrite;
			end
		end
		STread		: begin
			if(STdone == 1'b1) begin
				STnstate = STawait;
			end
			else begin
				STnstate = STread;
			end
		end
        STawait     : begin
			if(enaSignal == 1'b1) begin
				if(overFlag == 1'b1) begin
					STnstate = STeaction;
				end
				else begin
					if(wrFlag == 1'b0) begin
						STnstate = STwrite;
					end
					else begin
						STnstate = STread;
					end
				end
			end
			else begin
				STnstate = STawait;
			end
        end
		STeaction	: begin
			if(STdone == 1'b1) begin
				STnstate = STsetout;
			end
			else begin
				STnstate = STeaction;
			end
		end
        default : begin end
	endcase
end
//handle function
always @(posedge drive_clk or negedge rst) begin
	if(rst == 1'b0) begin
		comSignal <= 1'b0;
		errorFlag <= 1'b0;
        SCL <= 1'b1;
        SDAout <= 1'b1;
		SDAswitch <= 1'b1;
		rdata <= 8'b0;
        STdone <= 1'b0;
		IICcount <= 8'b0;
	end
	else begin
		comSignal <= 1'b0;
		errorFlag <= 1'b0;
        STdone <= 1'b0;
		IICcount <= IICcount + 1'b1;
        
		case(STnstate)
			STsetout	: begin
				SDAswitch <= 1'b1;
				SCL <= 1'b1;
				SDAout <= 1'b1;
                IICcount <= 8'b0;
				comSignal <= 1'b1;
			end
            STbaction   : begin
				case(IICcount)
					2'd0 : begin
						SDAout <= 1'b0;
					end
					2'd1 : begin
						SCL <= 1'b0;
						IICcount <= 8'b0;
						STdone <= 1'b1;
					end
					default : begin end
				endcase
            end
			//cycle : SCL_LO -> outdata -> SCL_HI
			STwrite		: begin
				case(IICcount % 2'd3)
					2'd0 : begin
						case(IICcount)
							8'd0	: begin
								tempdata <= wdata;
							end
							8'd27	: begin
								//get subordinate response
								errorFlag <= 1'b0;
								STdone <= 1'b1;
							end
							default : begin
								SCL <= 1'b0;
								tempdata <= {tempdata[6:0], tempdata[7]};
							end
						endcase
					end
					2'd1 : begin
						case(IICcount)
							8'd25 : begin
							//three-state gate Prepare to input state
								SDAswitch <= 1'b0;
							end
							default : begin
								SDAout <= tempdata[7];
							end
						endcase
					end
					2'd2 : begin
						SCL <= 1'b1;
					end
					default : begin end
				endcase
			end
			//cycle : getdata -> SCL_LO -> SCL_HI
			STread		: begin
				case(IICcount % 2'd3)
					2'd0 : begin
						tempdata <= {tempdata[6:0], SDAin};
						case(IICcount)
							8'd0	: begin
								//three-state gate Prepare to input state
								SDAswitch <= 1'b0;
							end
							8'd24	: begin
								SDAout <= 1'b0;
							end
							default : begin end
						endcase
					end
					2'd1 : begin
						SCL <= 1'b0;
						if(IICcount == 8'd25) begin
							rdata <= tempdata;
							//three-state gate Prepare to output state
							SDAswitch <= 1'b1;
						end
						else begin end
					end
					2'd2 : begin
						SCL <= 1'b1;
						if(IICcount == 8'd26) begin
							STdone <= 1'b1;
						end
						else begin end
					end
					default : begin end
				endcase
			end
            STawait     : begin
                SDAswitch <= 1'b1;
				SCL <= 1'b0;
				SDAout <= 1'b0;
				IICcount <= 8'b0;
                comSignal <= 1'b1;
            end
			STeaction	: begin
				case(IICcount)
					8'd0 : begin
						SCL <= 1'b1;
					end
					8'd1 : begin
						SDAout <= 1'b1;
						STdone <= 1'b1;
					end
					default : begin end
				endcase
			end
            default : begin end
		endcase
	end
end
endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永恒盛夏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值