基于FPGA的I2C实验Verilog源代码优选.docx

上传人:b****5 文档编号:14535488 上传时间:2023-06-24 格式:DOCX 页数:15 大小:17.97KB
下载 相关 举报
基于FPGA的I2C实验Verilog源代码优选.docx_第1页
第1页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第2页
第2页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第3页
第3页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第4页
第4页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第5页
第5页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第6页
第6页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第7页
第7页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第8页
第8页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第9页
第9页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第10页
第10页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第11页
第11页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第12页
第12页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第13页
第13页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第14页
第14页 / 共15页
基于FPGA的I2C实验Verilog源代码优选.docx_第15页
第15页 / 共15页
亲,该文档总共15页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

基于FPGA的I2C实验Verilog源代码优选.docx

《基于FPGA的I2C实验Verilog源代码优选.docx》由会员分享,可在线阅读,更多相关《基于FPGA的I2C实验Verilog源代码优选.docx(15页珍藏版)》请在冰点文库上搜索。

基于FPGA的I2C实验Verilog源代码优选.docx

基于FPGA的I2C实验Verilog源代码优选

`timescale1ns/1ps

modulei2c_drive(

clk,rst_n,

sw1,sw2,

scl,sda,

dis_data

);

inputclk;//50MHz

inputrst_n;//复位信号,低有效

inputsw1,sw2;//按键1、2,(1按下执行写入操作,2按下执行读操作)

outputscl;//24C02的时钟端口

inoutsda;//24C02的数据端口

output[7:

0]dis_data;//输出指定单元的数据

//--------------------------------------------

//按键检测

regsw1_r,sw2_r;//键值锁存寄存器,每20ms检测一次键值

reg[19:

0]cnt_20ms;//20ms计数寄存器

always@(posedgeclkornegedgerst_n)

if(!

rst_n)

cnt_20ms<=20'd0;

else

cnt_20ms<=cnt_20ms+1'b1;//不断计数

always@(posedgeclkornegedgerst_n)

if(!

rst_n)

begin

sw1_r<=1'b1;//键值寄存器复位,没有键盘按下时键值都为1

sw2_r<=1'b1;

end

elseif(cnt_20ms==20'hfffff)

begin

sw1_r<=sw1;//按键1值锁存

sw2_r<=sw2;//按键2值锁存

end

//---------------------------------------------

//分频部分

reg[2:

0]cnt;//cnt=0:

scl上升沿,cnt=1:

scl高电平中间,cnt=2:

scl下降沿,cnt=3:

scl低电平中间

reg[8:

0]cnt_delay;//500循环计数,产生iic所需要的时钟

regscl_r;//时钟脉冲寄存器

always@(posedgeclkornegedgerst_n)

if(!

rst_n)

cnt_delay<=9'd0;

elseif(cnt_delay==9'd499)

cnt_delay<=9'd0;//计数到10us为scl的周期,即100KHz

else

cnt_delay<=cnt_delay+1'b1;//时钟计数

always@(posedgeclkornegedgerst_n)begin

if(!

rst_n)

cnt<=3'd5;

else

begin

case(cnt_delay)

9'd124:

cnt<=3'd1;//cnt=1:

scl高电平中间,用于数据采样

9'd249:

cnt<=3'd2;//cnt=2:

scl下降沿

9'd374:

cnt<=3'd3;//cnt=3:

scl低电平中间,用于数据变化

9'd499:

cnt<=3'd0;//cnt=0:

scl上升沿

default:

cnt<=3'd5;

endcase

end

end

`defineSCL_POS(cnt==3'd0)//cnt=0:

scl上升沿

`defineSCL_HIG(cnt==3'd1)//cnt=1:

scl高电平中间,用于数据采样

`defineSCL_NEG(cnt==3'd2)//cnt=2:

scl下降沿

`defineSCL_LOW(cnt==3'd3)//cnt=3:

scl低电平中间,用于数据变化

always@(posedgeclkornegedgerst_n)

if(!

rst_n)

scl_r<=1'b0;

elseif(cnt==3'd0)

scl_r<=1'b1;//scl信号上升沿

elseif(cnt==3'd2)

scl_r<=1'b0;//scl信号下降沿

assignscl=scl_r;//产生iic所需要的时钟

//---------------------------------------------

//需要写入24C02的地址和数据

`defineDEVICE_READ8'b1010_0001//被寻址器件地址(读操作)

`defineDEVICE_WRITE8'b1010_0000//被寻址器件地址(写操作)

`defineWRITE_DATA8'b0000_0111//写入EEPROM的数据

`defineBYTE_ADDR8'b0000_0100//写入/读出EEPROM的地址寄存器

reg[7:

0]db_r;//在IIC上传送的数据寄存器

reg[7:

0]read_data;//读出EEPROM的数据寄存器

//---------------------------------------------

//读、写时序

parameterIDLE=4'd0;

parameterSTART1=4'd1;

parameterADD1=4'd2;

parameterACK1=4'd3;

parameterADD2=4'd4;

parameterACK2=4'd5;

parameterSTART2=4'd6;

parameterADD3=4'd7;

parameterACK3=4'd8;

parameterDATA=4'd9;

parameterACK4=4'd10;

parameterSTOP1=4'd11;

parameterSTOP2=4'd12;

reg[3:

0]cstate;//状态寄存器

regsda_r;//输出数据寄存器

regsda_link;//输出数据sda信号inout方向控制位

reg[3:

0]num;//

always@(posedgeclkornegedgerst_n)begin

if(!

rst_n)

begin

cstate<=IDLE;

sda_r<=1'b1;

sda_link<=1'b0;

num<=4'd0;

read_data<=8'b0000_0000;

end

else

case(cstate)

IDLE:

begin

sda_link<=1'b1;//数据线sda为input

sda_r<=1'b1;

if(!

sw1_r||!

sw2_r)

begin//SW1,SW2键有一个被按下

db_r<=`DEVICE_WRITE;//送器件地址(写操作)

cstate<=START1;

end

else

cstate<=IDLE;//没有任何键被按下

end

START1:

begin

if(`SCL_HIG)

begin//scl为高电平期间

sda_link<=1'b1;//数据线sda为output

sda_r<=1'b0;//拉低数据线sda,产生起始位信号

cstate<=ADD1;

num<=4'd0;//num计数清零

end

else

cstate<=START1;//等待scl高电平中间位置到来

end

ADD1:

begin

if(`SCL_LOW)

begin

if(num==4'd8)

begin

num<=4'd0;//num计数清零

sda_r<=1'b1;

sda_link<=1'b0;//sda置为高阻态(input)

cstate<=ACK1;

end

else

begin

cstate<=ADD1;

num<=num+1'b1;

case(num)

4'd0:

sda_r<=db_r[7];

4'd1:

sda_r<=db_r[6];

4'd2:

sda_r<=db_r[5];

4'd3:

sda_r<=db_r[4];

4'd4:

sda_r<=db_r[3];

4'd5:

sda_r<=db_r[2];

4'd6:

sda_r<=db_r[1];

4'd7:

sda_r<=db_r[0];

default:

;

endcase

//sda_r<=db_r[4'd7-num];//送器件地址,从高位开始

end

end

//elseif(`SCL_POS)db_r<={db_r[6:

0],1'b0};//器件地址左移1bit

else

cstate<=ADD1;

end

ACK1:

begin

if(/*!

sda*/`SCL_NEG)

begin//注:

24C01/02/04/08/16器件可以不考虑应答位

cstate<=ADD2;//从机响应信号

db_r<=`BYTE_ADDR;//1地址

end

else

cstate<=ACK1;//等待从机响应

end

ADD2:

begin

if(`SCL_LOW)

begin

if(num==4'd8)

begin

num<=4'd0;//num计数清零

sda_r<=1'b1;

sda_link<=1'b0;//sda置为高阻态(input)

cstate<=ACK2;

end

else

begin

sda_link<=1'b1;//sda作为output

num<=num+1'b1;

case(num)

4'd0:

sda_r<=db_r[7];

4'd1:

sda_r<=db_r[6];

4'd2:

sda_r<=db_r[5];

4'd3:

sda_r<=db_r[4];

4'd4:

sda_r<=db_r[3];

4'd5:

sda_r<=db_r[2];

4'd6:

sda_r<=db_r[1];

4'd7:

sda_r<=db_r[0];

default:

;

endcase

//sda_r<=db_r[4'd7-num];//送EEPROM地址(高bit开始)

cstate<=ADD2;

end

end

//elseif(`SCL_POS)db_r<={db_r[6:

0],1'b0};//器件地址左移1bit

else

cstate<=ADD2;

end

ACK2:

begin

if(/*!

sda*/`SCL_NEG)begin//从机响应信号

if(!

sw1_r)begin

cstate<=DATA;//写操作

db_r<=`WRITE_DATA;//写入的数据

end

elseif(!

sw2_r)begin

db_r<=`DEVICE_READ;//送器件地址(读操作),特定地址读需要执行该步骤以下操作

cstate<=START2;//读操作

end

end

elsecstate<=ACK2;//等待从机响应

end

START2:

begin//读操作起始位

if(`SCL_LOW)begin

sda_link<=1'b1;//sda作为output

sda_r<=1'b1;//拉高数据线sda

cstate<=START2;

end

elseif(`SCL_HIG)begin//scl为高电平中间

sda_r<=1'b0;//拉低数据线sda,产生起始位信号

cstate<=ADD3;

end

elsecstate<=START2;

end

ADD3:

begin//送读操作地址

if(`SCL_LOW)begin

if(num==4'd8)begin

num<=4'd0;//num计数清零

sda_r<=1'b1;

sda_link<=1'b0;//sda置为高阻态(input)

cstate<=ACK3;

end

elsebegin

num<=num+1'b1;

case(num)

4'd0:

sda_r<=db_r[7];

4'd1:

sda_r<=db_r[6];

4'd2:

sda_r<=db_r[5];

4'd3:

sda_r<=db_r[4];

4'd4:

sda_r<=db_r[3];

4'd5:

sda_r<=db_r[2];

4'd6:

sda_r<=db_r[1];

4'd7:

sda_r<=db_r[0];

default:

;

endcase

//sda_r<=db_r[4'd7-num];//送EEPROM地址(高bit开始)

cstate<=ADD3;

end

end

//elseif(`SCL_POS)db_r<={db_r[6:

0],1'b0};//器件地址左移1bit

elsecstate<=ADD3;

end

ACK3:

begin

if(/*!

sda*/`SCL_NEG)begin

cstate<=DATA;//从机响应信号

sda_link<=1'b0;

end

elsecstate<=ACK3;//等待从机响应

end

DATA:

begin

if(!

sw2_r)begin//读操作

if(num<=4'd7)begin

cstate<=DATA;

if(`SCL_HIG)begin

num<=num+1'b1;

case(num)

4'd0:

read_data[7]<=sda;

4'd1:

read_data[6]<=sda;

4'd2:

read_data[5]<=sda;

4'd3:

read_data[4]<=sda;

4'd4:

read_data[3]<=sda;

4'd5:

read_data[2]<=sda;

4'd6:

read_data[1]<=sda;

4'd7:

read_data[0]<=sda;

default:

;

endcase

//read_data[4'd7-num]<=sda;//读数据(高bit开始)

end

//elseif(`SCL_NEG)read_data<={read_data[6:

0],read_data[7]};//数据循环右移

end

elseif((`SCL_LOW)&&(num==4'd8))begin

num<=4'd0;//num计数清零

cstate<=ACK4;

end

elsecstate<=DATA;

end

elseif(!

sw1_r)begin//写操作

sda_link<=1'b1;

if(num<=4'd7)begin

cstate<=DATA;

if(`SCL_LOW)begin

sda_link<=1'b1;//数据线sda作为output

num<=num+1'b1;

case(num)

4'd0:

sda_r<=db_r[7];

4'd1:

sda_r<=db_r[6];

4'd2:

sda_r<=db_r[5];

4'd3:

sda_r<=db_r[4];

4'd4:

sda_r<=db_r[3];

4'd5:

sda_r<=db_r[2];

4'd6:

sda_r<=db_r[1];

4'd7:

sda_r<=db_r[0];

default:

;

endcase

//sda_r<=db_r[4'd7-num];//写入数据(高bit开始)

end

//elseif(`SCL_POS)db_r<={db_r[6:

0],1'b0};//写入数据左移1bit

end

elseif((`SCL_LOW)&&(num==4'd8))begin

num<=4'd0;

sda_r<=1'b1;

sda_link<=1'b0;//sda置为高阻态

cstate<=ACK4;

end

elsecstate<=DATA;

end

end

ACK4:

begin

if(/*!

sda*/`SCL_NEG)begin

//sda_r<=1'b1;

cstate<=STOP1;

end

elsecstate<=ACK4;

end

STOP1:

begin

if(`SCL_LOW)begin

sda_link<=1'b1;

sda_r<=1'b0;

cstate<=STOP1;

end

elseif(`SCL_HIG)begin

sda_r<=1'b1;//scl为高时,sda产生上升沿(结束信号)

cstate<=STOP2;

end

elsecstate<=STOP1;

end

STOP2:

begin

if(`SCL_LOW)sda_r<=1'b1;

elseif(cnt_20ms==20'hffff0)cstate<=IDLE;

elsecstate<=STOP2;

end

default:

cstate<=IDLE;

endcase

end

assignsda=sda_link?

sda_r:

1'bz;

assigndis_data=read_data;

//---------------------------------------------

endmodule

最新文件----------------仅供参考--------------------已改成word文本---------------------方便更改

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2