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

📄 i2cslave.tdf

📁 基于fpga的屏幕测试程序
💻 TDF
字号:
%    module I2CSLAVE   ---------------     version :  3.1     date    :  Nov 2, 2004     author  :  Frank Budzelaar    Summary   -------   This module implements an i2c slave with the following features:   - 7-bit address support only   - programmable I2C slave address   - subaddressing support:        - 1 to 16 bit subaddresses        - autoincrement of the subaddress   - no general call handling   - clock stretching support   By using this module together with the other i2c components in this   package, i2c controlled systems can be implemented very rapidly,   and with a minimum of hassle.   Parameters   ----------         SLAVEADDRESS      NOSUBADRESS : 1 / 0 	   	     If set to 1, no subaddressing is done. As the original slave core	     makes heavy use of subaddressing, this is a bit of a cludge:		 SUBADDRESSBITS must be set to 1 (or higher), so there is still a 		 subaddress bus, but the address on it will always be 0.		 the slave core will now pass all databytes directly to address 0.      SUBADDRESSBITS : 1..16         The number of subaddress bits to use. If the number of subaddressbits         is 8 or lower, one subaddress byte is expected as first data byte          during a write operation. If the number is higher, two subaddress bytes         are expected. The first byte holds the MSBs.      DEBUGMODE         As a bidirectional bus with pull-ups is very difficult to          simulate, a debug mode helps in debugging an application.         This debug mode is enabled by parameter DEBUGMODE=1.         Non debug mode:            scl, sda: bidirectional I2C pins            sclout, sdaout: not used         Debug mode:            scl, sda: input            sclOut, sdaOut: outputs, driven with the active bits                            generated by the slave itself.   Interface   ---------   General interface   -----------------       clk: INPUT          A clock which is at least 5 times the i2c speed      i2c interface   -------------          sda: BIDIR         standard bidirectional i2c SDA line      scl: BIDIR         standard bidirectional i2c SCL line   internal i2c interface   ----------------------      All signals are bundled into one bus for easy of use:      this starts at the i2c slave, flows through each i2c       subdevice, and returns to the i2cslave. The internal      structure of this bus is of no concern to the user.         [0] clk         [1] wr         [2] rd         [3] wait          [11..4] data in         [19..12] data out         [I2CBUSWIDTH-1..20] address      i2cBusOut[I2CBUSWIDTH-1..0]:  OUTPUT;         The output bus      i2cBusIn[I2CBUSWIDTH-1..0]:  INPUT;         The input bus%INCLUDE "medianFilter";PARAMETERS   (   SUBADDRESSBITS=1,   NOSUBADDRESS=1,   WAITSTATES=4,   DEBUGMODE=0   );CONSTANT SUBADDRESSBYTES = SUBADDRESSBITS > 8 ? 2 : 1;CONSTANT I2CBUSWIDTH = SUBADDRESSBITS+20; -- address, data in, data out, wait, read, write, clk   -- order:   -- [0] clk   -- [1] wr   -- [2] rd   -- [3] wait    -- [11..4] data in   -- [19..12] data out   -- [I2CBUSWIDTH-1..20] addressSUBDESIGN i2cSlave   (   -- system   clk:                            INPUT;   -- i2c side   sda:                            BIDIR;   scl:                            BIDIR;   slaveAddress[7..1]:			   INPUT;   -- internal side   i2cBusOut[I2CBUSWIDTH-1..0]:    OUTPUT;   i2cBusIn[I2CBUSWIDTH-1..0]:     INPUT;   -- debug   sdaOut:                         OUTPUT;   -- debugging only: ignore   sclOut:                         OUTPUT;   -- debugging only: ignore   dummyOut:                       OUTPUT;   -- just used to get rid of warnings: ignore   )VARIABLE   sdan,sdap,scln,sclp: DFF;   start,stop,bitStart,bitStop: NODE;   bitCounter[3..0]: DFF;   byteCounter[1..0]: DFFE;   shiftInReg[7..0]: DFFE;   shiftOutReg: DFFE;   addressed: DFF;   address[SUBADDRESSBITS-1..0]: DFFE;   wait: NODE;   waitff: DFF;   read: DFFE;   wr: DFF;   rd: DFF;   prevAct: DFF;   sdaMedian,sclMedian: medianFilter WITH (length=6);   forceSclLow: NODE;   forceSdaLow: NODE;   IF (WAITSTATES!=0) GENERATE      waitCounter[CEIL(LOG2(WAITSTATES+1))-1..0]: DFF;   END GENERATE;BEGIN-- scl and sda clocking, edge detectionsdaMedian.clk=clk;sdaMedian.in=sda;sdan.clk=clk;sdan=sdaMedian.out;sdap.clk=clk;sdap=sdan;sclMedian.clk=clk;sclMedian.in=scl;scln.clk=clk;scln=sclMedian.out;sclp.clk=clk;sclp=scln;start=!sdan & sdap & scln;stop=sdan & !sdap & scln;bitstart=scln & !sclp;bitstop=!scln & sclp;-- data bit counter: 0..8-- the bit counter is set to 15 on a start condition-- and incremented on negative edge of scl-- this means that the bit counter indicates the bit nr during-- the preceding low and subsequent high scl period of the bit-- code 0 means data bit 7-- code 7 means data bit 0-- code 8 means ack bitbitCounter[].clk=clk;IF (start) THEN   bitCounter[]=15;ELSIF (bitStop) THEN   IF (bitCounter[]==8) THEN      bitCounter[]=0;   ELSE      bitCounter[]=bitCounter[]+1;   END IF;ELSE   bitCounter[]=bitCounter[];END IF;-- data byte counter: 0..3 (3 means 3 or more)-- the byte counter is cleared on a start condition-- and incremented on negative edge of ackbyteCounter[].clk=clk;IF (start) THEN   byteCounter[]=0;ELSE   IF ((bitCounter[]==8) & bitStop & byteCounter[]!=3) THEN      byteCounter[]=byteCounter[]+1;   ELSE      byteCounter[]=byteCounter[];   END IF;END IF;-- data input shift register-- data is shifted in on every bit start-- During a read, the shiftInReg is misused to-- shift out the data to the processor.shiftInReg[].clk=clk;shiftInReg[].ena=bitStart # rd;IF (rd) THEN   shiftInReg[]=i2cBusIn[19..12];ELSE   shiftInReg[]=(shiftInReg[6..0],sdan);END IF;   shiftOutReg.clk=clk;shiftOutReg.ena=bitStop;shiftOutReg=shiftInReg[7];-- address recognition-- the addressed bit is cleared on every start and stop condition,-- and will be updated on reception of the last bit of the first byte-- of a transferaddressed.clk=clk;addressed=((addressed & !start & !stop) &           -- not a read with no ack           !(read & bitCounter[]==8 & bitStart & sdan))          #           -- Address matches in first byte          (bitStart & bitCounter[]==6 & byteCounter[]==0 & (shiftInReg[5..0],sdan)==slaveAddress[]);-- read/write mode logic-- the addressed bit will be updated on reception of the read bit -- in the first byte of the transferread.clk=clk;read.ena=bitStart & bitCounter[]==7 & byteCounter[]==0;read=sdan;-- subaddress logic-- the sub address will be loaded at the second and third byte of the write-- and it is incremented:-- during a write: -- during a read:address[].clk=clk;IF (addressed) THEN   IF (NOSUBADDRESS==1) GENERATE      address[]=0; -- address is always 0   ELSE GENERATE      IF (SUBADDRESSBYTES==2) GENERATE         IF (!read & byteCounter[]==1 & bitCounter[]==7 & bitStop) THEN            address[SUBADDRESSBITS-1..8]=shiftInReg[SUBADDRESSBITS-1-8..0];            address[7..0]=address[7..0];         ELSIF (!read & byteCounter[]==2 & bitCounter[]==7 & bitStop) THEN            address[7..0]=shiftInReg[];            address[SUBADDRESSBITS-1..8]=address[SUBADDRESSBITS-1..8];         ELSE            -- increment on negative egdes of rd and write            IF (prevAct & !(rd # wr)) THEN               address[]=address[]+1;            ELSE               address[]=address[];            END IF;        END IF;      END GENERATE;      IF (SUBADDRESSBYTES==1) GENERATE         IF (!read & byteCounter[]==1 & bitCounter[]==7 & bitStop) THEN            address[SUBADDRESSBITS-1..0]=shiftInReg[SUBADDRESSBITS-1..0];         ELSE             -- increment on negative egdes of rd and write            IF (prevAct & !(rd # wr)) THEN               address[]=address[]+1;            ELSE               address[]=address[];            END IF;         END IF;      END GENERATE;   END GENERATE;ELSE   address[]=address[];END IF;-- write logic-- a write to the internal registers occurs at the negative edge of -- scl of the last data bit.-- as a wait will keep scl low, no new data can shift into the -- shift registerwr.clk=clk;IF (NOSUBADDRESS==1) GENERATE   wr=addressed & ((!read & byteCounter[]>=1 & bitCounter[]==7 & bitStart) # (wr & wait));ELSE GENERATE   IF (SUBADDRESSBYTES==1) GENERATE      wr=addressed & ((!read & byteCounter[]>=2 & bitCounter[]==7 & bitStart) # (wr & wait));   END GENERATE;   IF (SUBADDRESSBYTES==2) GENERATE      wr=addressed & ((!read & byteCounter[]>=3 & bitCounter[]==7 & bitStart) # (wr & wait));   END GENERATE;END GENERATE;-- read logic-- a read occurs at each negative edge of a positive ack.-- this includes the positive ack on the first byte (!)rd.clk=clk;rd=addressed & ((read & bitCounter[]==8 & bitStart & !sdan) # (rd & wait));-- used to detect negative of wr or rd: will increment address counterprevAct.clk=Clk;prevAct=wr # rd;-- wait logicwaitff.clk=clk;waitff=(waitff # bitStop) & (addressed & (rd # wr));-- scl and sda out logicforceSclLow=waitff;forceSdaLow=addressed &                     -- ack bits                     ( (bitCounter[]==8 & (byteCounter[]==0 # !read)) #                     -- data bits during read                       (read & byteCounter[]!=0 & bitCounter[]!=8 & !shiftOutReg));IF (debugmode==0) GENERATEscl=tri(.in=gnd, .oe=forceSclLow);sda=tri(.in=gnd, .oe=forceSdaLow);sclOut=Gnd;sdaOut=Gnd;END GENERATE;IF (debugmode==1) GENERATEscl=tri(.in=gnd, .oe=gnd);sda=tri(.in=gnd, .oe=gnd);sclOut=!forceSclLow;sdaOut=!forceSdaLow;END GENERATE;-- wait state generatorIF (WAITSTATES!=0) GENERATE   waitCounter[].clk=clk;   IF (rd # wr) THEN      IF (waitCounter[]>0) THEN         waitCounter[]=waitCounter[]-1;      ELSE         waitCounter[]=waitCounter[];      END IF;   ELSE      waitCounter[]=WAITSTATES;   END IF;   wait=i2cBusIn[3] # waitCounter[]!=0;END GENERATE;IF (WAITSTATES==0) GENERATE   wait=i2cBusIn[3];END GENERATE;-- interfacei2cBusOut[0]=clk;i2cBusOut[1]=wr;i2cBusOut[2]=rd;i2cBusOut[3]=Gnd; -- wait: ignore;i2cBusOut[11..4]=shiftInReg[7..0]; -- data outi2cBusOut[19..12]=h"FF"; -- data In: ignore;i2cBusOut[I2CBUSWIDTH-1..20]=address[];dummyOut=i2cBusIn[I2CBUSWIDTH-1..0]==0;END;

⌨️ 快捷键说明

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