eeprominterfaceVerilog实现的简单程序I2C总线接口.docx
《eeprominterfaceVerilog实现的简单程序I2C总线接口.docx》由会员分享,可在线阅读,更多相关《eeprominterfaceVerilog实现的简单程序I2C总线接口.docx(13页珍藏版)》请在冰豆网上搜索。
eeprominterfaceVerilog实现的简单程序I2C总线接口
eeprom_interfaceVerilog实现的简单程序(I2C总线接口)
Actel公司时间:
2008年08月13日
字体:
大中小
关键词:
<"cblue""target='_blank'>上电<"cblue""target='_blank'>串行闪存<"cblue""target='_blank'>第一个<"cblue""target='_blank'>加载<"cblue""target='_blank'>连续输出
//i2c.vhd
//
//这是是能从一个外部NUM(AT24C02A)读数据到一个256x8的外部SRAM块的I2C主接口程序,
//当用于写NUM的外部逻辑寄存器存取时,SRAM就从外部源读数据并且把数据写到特定的I2C地址。
//----------------------------------------------------------------------
//
//?
?
?
?
?
?
?
?
?
?
?
?
?
Copyright2004Actelcorporation
//
//----------------------------------------------------------------------
//
//Version1.2?
06/04/04J.Vorgert-workingfile
//
//----------------------------------------------------------------------
'timescale1ns/1ps
modulei2c(Reset_n,CLK,INIT,IENB,IADDR,IDATA,ICLK,UPDT,
?
?
?
?
?
?
?
?
?
?
?
UENB,UADDR,UDATA,SDI,SDO,SCK);
inputReset_n;?
/*activelowreset*/
inputCLK?
?
?
;?
/*processorclock?
*/
outputINIT?
?
;?
/*highduringinit*/
outputIENB?
?
;?
/*lowtoenablewrite*/
output[7:
0]IADDR?
;?
/*initaddress*/
output[7:
0]IDATA?
;?
/*initdata*/
outputICLK?
?
;?
/*initclock*/
inputUPDT?
?
;?
/*hightotriggermirrorimageupdate*/
outputUENB?
?
;?
/*lowtoenablefifo*/
input[7:
0]UADDR;/*writeaddress*/
input[7:
0]UDATA;?
/*writedata*/
inputSDI?
?
?
;?
/*serialinput*/
outputSDO?
?
?
;/*activelowopen-draindriveenable-data*/
outputSCK?
?
?
;/*activelowopen-draindriveenable-clock*/
regIENB;
regINIT;
regUENB;
regBTCK;
wireSTEN;?
?
?
?
reg?
[3:
0]CSTATE;?
?
reg?
[3:
0]BCNT?
;?
reg?
[7:
0]CCNT?
;?
regDLY?
?
?
?
;
regD2;
wireD2I;
wireNKI?
?
?
?
;
regNACK?
?
?
;
wireWRI?
?
?
?
;
wireRDI?
?
?
?
;
reg[8:
0]BYTE?
?
;
reg[8:
0]SDATA?
;
wireLD_BYTE?
;
regSTSP?
?
?
?
;
wireCTL_VAL?
;
always@(posedgeCLKornegedgeReset_n)
begin
?
if(Reset_n==1'b0)
?
?
?
?
BTCK<=1'b0;
?
else
?
?
?
?
BTCK<=#1!
BTCK;
end
//INITissetatpower-upandclearedwhenthestatemachine
//reachesstate0101.
always@(negedgeReset_norposedgeCLK)
begin
?
if(Reset_n==1'b0)
?
?
?
?
INIT<=1'b1;
?
elseif(CSTATE==4'b0101)
?
?
?
?
?
?
?
INIT<=#11'b0;
end
//Thisstatemachineisset-uptoread/writedatatoanAT24C02A
//serialFlashmemory
//这个状态机是建立AT24C02A<"cblue""title="串行闪存">串行闪存的数据读写
//Atpower-up,theINITbitisset,andthestatemachineexecutes
//a'sequencialread'operationstartingataddress0x000and
//proceddinguntilall256byteshavebeenreadandforwardedinto
//theinternalmemoryblock.Thestatemachinethensendsa
//stopbittotheFlashandclearstheINITcontrolbit.
//
//在<"cblue""title="上电">上电时,INIT被设置为高,状态机从地址0x000开始执行“连续读”操作,
//一直进行下去直到所有的256字节都被读,然后向前到内部存储区,
//状态机然后给FLASH发送一个停止位并且清除INIT控制位。
//Thestatemachinethenwaitsforupdttobeset.
//Whentheupdtbitisset,theinterfaceassertsu_enblowona
//falling-edgeofclkandaddr/dataislatched?
onthenextfallingedge
//(rd_clkshouldbeontherising-edge).?
Thestatemachinewrites
//datatotheexternalFLASHmemoryonebyteatatimewhenever
//updtisassertedhigh.?
IftheFIFOremains'notempty'thenthis
//blockwillpolltheNVMuntilitisready,andthenproceedwith
//awritecycleforthenextbyte.
//状态机一直等待UPDT被置为高。
当updt比特被置成高,当clk下降沿时,接口把u_enb设成低
//(rd_clk应该在上升沿)。
这个状态机每次updt为高时就写一个字节数据到外部闪存。
//如果FIFO保持“非空”,则这个块会一直等到它准备好,然后在接下来的比特进行一个写周期。
//StateMachine:
//
//0000-resetstate:
?
?
generateastartbitandload0xA0command
//0001-sendbyte:
?
?
?
?
thenload0x00address
//0010-sendbyte:
?
?
?
?
generateastartbitandload0xA1command
//0011-sendbyte:
?
?
?
?
clearbytecount
//0100-receivebyte:
?
ifcnt/=FF:
ack,cnt++,goto0004else:
nack
//0101-stop:
?
?
?
?
?
?
?
?
?
assertstopbitandloopuntilupdt=1-then
//?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
generateastartbitandloadA0
//0110-sendbyte:
?
?
?
?
sendbyte-ifnack-goto0101,elseloadAddress
//0111-sendbyte:
?
?
?
?
senddatabyte,loaddata
//1000-sendbyte:
?
?
?
?
goto0101
//
//Inpractice,thestatemachineisjustacounterthatstartsatzero
//andcountsup,thenjumpsbackto101andcountsupagain,
//returningtozeroonlywhenreset_nisassertedlow.
//在练习中,状态机只是一个从0开始计数的计数器,加起来,然后跳到101,再重新计数,
//只有到reset_n被置为低时才返回到0。
assignSTEN=(BCNT[3]==1'b1&&
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
(CSTATE[2]!
=1'b1||CSTATE[2:
1]==2'b11||
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
CSTATE[3]?
==1'b1||(CSTATE==4'b0100&&CCNT==8'b11111111)||
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
(CSTATE==4'b0101&&UPDT==1'b1)))?
1'b1:
1'b0;
always@(negedgeReset_nornegedgeCLK)
begin
?
if(Reset_n==1'b0)?
?
?
?
?
CSTATE<=4'b0000;
?
else
?
begin
?
if(STEN==1'b1&&BTCK==1'b0)
?
?
?
?
?
?
?
begin
?
?
?
?
?
?
?
?
if(CSTATE<4'b0101&&NACK==1'b1)
?
?
?
?
?
?
?
?
?
?
CSTATE<=#14'b0000;
?
?
?
?
?
?
?
end
?
?
else
?
?
?
?
?
?
?
begin
?
?
?
?
?
?
?
if(CSTATE[3]==1'b1||NACK==1'b1)
?
?
?
?
?
?
?
?
?
CSTATE<=#14'b0101;
?
?
?
?
?
?
?
else
?
?
?
?
?
?
?
?
?
CSTATE<=#1CSTATE+1'b1;
?
?
?
?
?
?
?
end
?
end
end
//Thebitcounter(BCNT)isclearedatthestatetransition
//andduringthefirstcycleofstate'0011'(forstartbit).
//incrementedonthefalling-edgeofclkwhenBTCKislow.
//比特计数器在过渡状态时和在状态“0011”(起始比特)<"cblue""title="第一个">第一个循环期间被清空。
//在clk下降沿并且BTCK为低电平时,比特计数器增加。
always@(negedgeReset_nornegedgeCLK)
begin
?
if(Reset_n==1'b0)
?
?
?
?
begin
?
?
?
?
BCNT<=4'b0000;
?
?
?
?
DLY?
<=1'b0;
?
?
?
?
end
?
else
?
?
?
begin
?
?
?
?
if(BTCK==1'b0)
?
?
?
?
?
?
begin
?
?
?
?
?
?
if(BCNT[3]==1'b1&&CSTATE==4'b0010)
?
?
?
?
?
?
?
?
?
DLY<=#11'b1;
?
?
?
?
?
?
else
?
?
?
?
?
?
?
?
?
DLY<=1'b0;
?
?
?
?
?
?
?
?
?
?
?
?
if(BCNT[3]==1'b1||(CSTATE==4'b0011&&DLY==1'b1))
?
?
?
?
?
?
?
?
?
BCNT<=#14'b0000;
?
?
?
?
?
?
else
?
?
?
?
?
?
?
?
?
BCNT<=#1BCNT+1'b1;
?
?
?
?
?
?
end
?
?
?
?
?
?
end
end
//Thebytecounter(CCNT)isclearedinstate0011.
//字节计数器在状态0011时被清零。
//ItisincrementedduringtheACKbitaftereach
//bytetransferinstate0100tocount0x00-0xFFbytes
//astheyarereadfromtheNVM.?
ccntisusedbothas
//acontrolsignalandastheiaddroutput.
assignD2I=(BTCK==1'b1&&BCNT[3]==1'b1&&CSTATE==4'b0100)?
1'b1:
1'b0;
?
?
?
?
?
?
?
?
?
?
always@(negedgeReset_nornegedgeCLK)
begin
?
if(Reset_n==1'b0)
?
?
begin
?
?
?
?
CCNT<=8'b0;
?
?
?
?
D2?
?
<=1'b0;
?
?
end
?
else
?
?
begin
?
?
?
?
D2<=#1D2I;
?
?
?
?
if(CSTATE==4'b0011)
?
?
?
?
?
?
?
CCNT<=#18'b0;
?
?
?
?
elseif(D2==1'b1)
?
?
?
?
?
?
?
CCNT<=#1CCNT+1'b1;
?
?
?
?
end
end
//thefollowinglogiccheckstheACKbitforallstatesexcept
//states'0100'and'0101'andassertsNACKifthedatapinis
//highduringthe9thbitofanytransfer.?
Thisisregistered
//sothatthevalueispresentduringstatechanges.
assignNKI=(BCNT[3]==1'b1&&CSTATE!
=4'b0100&&CSTATE!
=4'b0101&&SDI==1'b1)?
1'b1:
1'b0;
always@(negedgeReset_norposedgeCLK)
begin
?
if(Reset_n==1'b0)
?
?
?
?
NACK<=1'b0;
?
elseif(BTCK==1'b1)
?
?
?
?
NACK<=#1NKI;
end
//Writeenablesareclearedto1atpower-upandareassertedlowduring
//ACKinstate0100.
assignWRI=(CSTATE==4'b0100&&BCNT[3]==1'b1&&BTCK==1'b1)?
1'b0:
1'b1;
always@(negedgeReset_nornegedgeCLK)
begin
?
if(Reset_n==1'b0)
?
?
?
?
IENB<=1'b1;
?
else
?
?
?
?
IENB<=#1WRI;
end
assignIADDR=CCNT[7:
0];?
?
/*usebytecountasaddress*/
assignIDATA=SDATA[8:
1];?
/*accountforACKbit*/
assignICLK=!
BTCK;?
?
?
?
?
?
?
?
?
?
/*invertBTCKandusetherising-edgeofthissignalas*/
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
/*thewriteclockintointernalSRAM*/
//UENBisclearedto1atpower-upandisassertedlowinstate0111
//UEUB在上电时被清到1,在0111状态当BCNT=7和BTCK=1时被置为低.
//whileBCNT=7andBTCK=1.?
Itisclockedonthefalling-edge
//ofCLKsoRD_CLKshouldoccurontherising-edge.
assignRDI=(CSTATE==4'b0111&&BCNT==4'b0111?
&&BTCK==1'b1)?
0:
1;
always@(negedgeReset_nornegedgeCLK)
begin
?
if(Reset_n==1'b0)
?
?
?
?
UENB?
<=1'b1;
?
else
?
?
?
?
UENB<=#1RDI;
?
end
//Thevaluethatgetsloadedintosdataisdetermined
//bywhichstatewe'reexiting...
//这个装载到sdata里的值由从哪个状态退出来决定
always@(CSTATEorUDATAorUADDR)
begin
?
case(CSTATE)
?
?
?
4'b0000:
?
BYTE=9'b101000001;/*A0*/
?
?
?
4'b0010:
?
BYTE=9'b101000011;/*A1*/
?
?
?
4'b0101:
?
BYTE=9'b101000001;/*A0*/
?
?
?
4'b0110:
?
BYTE={UADDR,1'b1};
?
?
?
4'b0111:
?
BYTE={UDATA,1'b1};
?
?
?
default:
?
BYTE=9'b000000001;/*0001,0011*/
?
endcase
end
//Thedataregisteris9bitslong(BYTEandACKbit)
//ItisparallelloadedduringtheACKcycleinstates
//0000,0001,0010,0011,0101,0110,and0111;
//这个数据寄存器为9比特长(一个字节加一个ACK位)
//在状态0000,0001,0010,0101,0110和0111状态的ACK循环时,这些都是平行<"cblue""title="加载">加载的。
assignLD_BYTE=(BCNT[3]==1'b1&&BTCK==1'b0&&CSTATE!
=4'b0100&&CSTATE[3]==1'b0)?
1'b1:
1'b0;
always@(negedgeReset_nornegedgeCLK)
begin
?
if(Reset_n==1'b0)
?
?
?
?
SDATA<=9'b111111111;
?
else
?
?
?
?
begin
?
?
?
?
if(LD_BYTE==1'b1)
?
?
?
?
?
?
?
SDATA<=#1BYTE;
?
?
?
?
elseif((CSTATE!
=4'b0101&&CSTATE!
=4'b0100&&BTCK==1'b0&&DLY==1'b0)||
?
?
?
?
?
?
?
?
?
?
(CSTATE==4'b0100&&BTCK==1'b1))
?
?
?
?
?
?
?
?
?
?
?
SDATA<=#1{SDATA[7:
0],SDI};
?
?
?
?
end
end
//Startbits(datafallingwhileBTCKishigh)aregeneratedas
//weexitstates0000,0010,and0101;stopbits(datarising
//whileBTCKishigh)aregeneratedasweenterstate0101.
//ThisisdonewiththeSTSPsignal.
//起始位(数据下降当BTCK为高)产生于退出状态0000,0010和0101时;
//停止位(数据上升当BTCK为高)产生于进入状态0101时。
//这些由STSP信号完成
always@(negedgeReset_nornegedg