目录

  • 日常·唠嗑
  • 一、程序设计
  • 二、镁光模型仿真验证
  • 三、testbench文件
  • 四、完整工程下载

日常·唠嗑

IIC协议这里就不赘述了,网上很多,这里推荐两个,可以看看【接口时序】6、IIC总线的原理与Verilog实现 ,还有IIC协议原理以及主机、从机Verilog实现。
      前者是对IIC协议详细介绍、以及主机发送,主机接收两种方式。后者,是在前者基础上做设计,讲的是主机、从机两种设计实例。关于IIC从机,网上例程较少,可以参考这个博主的。不过,这个博主的状态机写的很乱,也没什么注释,看了两天才搞明白Verilog描述的什么,如果有FPGA爱好者需要用到,又看不懂的,可以私信我:bumianzhe@126.com.

一、程序设计

本程序参考芯路恒IIC设计,可以去他们官网下完整资料看看。
顶层模块:用来控制底层模块连续读写,包含了状态机

module i2c_control(Clk,Rst_n,wrreg_req,rdreg_req,addr,addr_mode,wrdata,rddata,device_id,RW_Done,ack,i2c_sclk,i2c_sdat
);input Clk;input Rst_n;input wrreg_req;input rdreg_req;input [15:0]addr;input addr_mode;input [7:0]wrdata;output reg[7:0]rddata;input [7:0]device_id;output reg RW_Done;output reg ack;output i2c_sclk;inout i2c_sdat;reg [5:0]Cmd;reg [7:0]Tx_DATA;wire Trans_Done;wire ack_o;reg Go;wire [15:0] reg_addr;assign reg_addr = addr_mode?addr:{addr[7:0],addr[15:8]};wire [7:0]Rx_DATA;localparam WR   = 6'b000001,   //写请求STA  = 6'b000010,   //起始位请求RD   = 6'b000100,   //读请求STO  = 6'b001000,   //停止位请求ACK  = 6'b010000,   //应答位请求NACK = 6'b100000;   //无应答请求i2c_bit_shift i2c_bit_shift(.Clk(Clk),.Rst_n(Rst_n),.Cmd(Cmd),.Go(Go),.Rx_DATA(Rx_DATA),.Tx_DATA(Tx_DATA),.Trans_Done(Trans_Done),.ack_o(ack_o),.i2c_sclk(i2c_sclk),.i2c_sdat(i2c_sdat));reg [6:0]state;reg [7:0]cnt;localparamIDLE         = 7'b0000001,   //空闲状态WR_REG       = 7'b0000010,   //写寄存器状态WAIT_WR_DONE = 7'b0000100,   //等待写寄存器完成状态WR_REG_DONE  = 7'b0001000,   //写寄存器完成状态RD_REG       = 7'b0010000,   //读寄存器状态WAIT_RD_DONE = 7'b0100000,   //等待读寄存器完成状态RD_REG_DONE  = 7'b1000000;   //读寄存器完成状态always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginCmd <= 6'd0;Tx_DATA <= 8'd0;Go <= 1'b0;rddata <= 0;state <= IDLE;ack <= 0;endelse begincase(state)IDLE:begincnt <= 0;ack <= 0;RW_Done <= 1'b0;                   if(wrreg_req)state <= WR_REG;else if(rdreg_req)state <= RD_REG;elsestate <= IDLE;endWR_REG:beginstate <= WAIT_WR_DONE;case(cnt)0:write_byte(WR | STA, device_id);1:write_byte(WR, reg_addr[15:8]);2:write_byte(WR, reg_addr[7:0]);3:write_byte(WR | STO, wrdata);default:;endcaseendWAIT_WR_DONE:beginGo <= 1'b0; if(Trans_Done)beginack <= ack | ack_o;case(cnt)0: begin cnt <= 1; state <= WR_REG;end1: begin state <= WR_REG;if(addr_mode)cnt <= 2; elsecnt <= 3;end2: begincnt <= 3;state <= WR_REG;end3:state <= WR_REG_DONE;default:state <= IDLE;endcaseendendWR_REG_DONE:beginRW_Done <= 1'b1;state <= IDLE;endRD_REG:beginstate <= WAIT_RD_DONE;case(cnt)0:write_byte(WR | STA, device_id);1:write_byte(WR, reg_addr[15:8]);2:write_byte(WR, reg_addr[7:0]);3:write_byte(WR | STA, device_id | 8'd1);4:read_byte(RD | NACK | STO);default:;endcaseendWAIT_RD_DONE:beginGo <= 1'b0; if(Trans_Done)beginif(cnt <= 3)ack <= ack | ack_o;case(cnt)0: begin cnt <= 1; state <= RD_REG;end1: begin state <= RD_REG;if(addr_mode)cnt <= 2; elsecnt <= 3;end2: begincnt <= 3;state <= RD_REG;end3:begincnt <= 4;state <= RD_REG;end4:state <= RD_REG_DONE;default:state <= IDLE;endcaseendendRD_REG_DONE:beginRW_Done <= 1'b1;rddata <= Rx_DATA;state <= IDLE;                enddefault:state <= IDLE;endcaseendtask read_byte;input [5:0]Ctrl_Cmd;beginCmd <= Ctrl_Cmd;Go <= 1'b1; endendtasktask write_byte;input [5:0]Ctrl_Cmd;input [7:0]Wr_Byte_Data;beginCmd <= Ctrl_Cmd;Tx_DATA <= Wr_Byte_Data;Go <= 1'b1; endendtaskendmodule

子模块:单字节读写操作

module i2c_bit_shift(Clk,Rst_n,Cmd,Go,Rx_DATA,Tx_DATA,Trans_Done,ack_o,i2c_sclk,i2c_sdat
);input Clk;input Rst_n;input [5:0]Cmd;input Go;output reg[7:0]Rx_DATA;input [7:0]Tx_DATA;output reg Trans_Done;output reg ack_o;output reg i2c_sclk;inout i2c_sdat;reg i2c_sdat_o;//系统时钟采用50MHzparameter SYS_CLOCK = 50_000_000;//SCL总线时钟采用400kHzparameter SCL_CLOCK = 400_000;//产生时钟SCL计数器最大值localparam SCL_CNT_M = SYS_CLOCK/SCL_CLOCK/4 - 1;reg i2c_sdat_oe;localparam WR   = 6'b000001,   //写请求STA  = 6'b000010,   //起始位请求RD   = 6'b000100,   //读请求STO  = 6'b001000,   //停止位请求ACK  = 6'b010000,   //应答位请求NACK = 6'b100000;   //无应答请求reg [19:0]div_cnt;reg en_div_cnt;always@(posedge Clk or negedge Rst_n)if(!Rst_n)div_cnt <= 20'd0;else if(en_div_cnt)beginif(div_cnt < SCL_CNT_M)div_cnt <= div_cnt + 1'b1;elsediv_cnt <= 0;endelsediv_cnt <= 0;wire sclk_plus = div_cnt == SCL_CNT_M;//assign i2c_sdat = i2c_sdat_oe?i2c_sdat_o:1'bz;assign i2c_sdat = !i2c_sdat_o && i2c_sdat_oe ? 1'b0:1'bz;reg [7:0]state;localparamIDLE      = 8'b00000001,   //空闲状态GEN_STA   = 8'b00000010,   //产生起始信号WR_DATA   = 8'b00000100,   //写数据状态RD_DATA   = 8'b00001000,   //读数据状态CHECK_ACK = 8'b00010000,   //检测应答状态GEN_ACK   = 8'b00100000,   //产生应答状态GEN_STO   = 8'b01000000;   //产生停止信号reg [4:0]cnt;always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginRx_DATA <= 0;i2c_sdat_oe <= 1'd0;en_div_cnt <= 1'b0;i2c_sdat_o <= 1'd1;Trans_Done <= 1'b0;ack_o <= 0;state <= IDLE;cnt <= 0;endelse begincase(state)IDLE:beginTrans_Done <= 1'b0;i2c_sdat_oe <= 1'd1;if(Go)beginen_div_cnt <= 1'b1;if(Cmd & STA)state <= GEN_STA;else if(Cmd & WR)state <= WR_DATA;else if(Cmd & RD)state <= RD_DATA;elsestate <= IDLE;endelse beginen_div_cnt <= 1'b0;state <= IDLE;endendGEN_STA:beginif(sclk_plus)beginif(cnt == 3)cnt <= 0;elsecnt <= cnt + 1'b1;case(cnt)0:begin i2c_sdat_o <= 1; i2c_sdat_oe <= 1'd1;end1:begin i2c_sclk <= 1;end2:begin i2c_sdat_o <= 0; i2c_sclk <= 1;end3:begin i2c_sclk <= 0;enddefault:begin i2c_sdat_o <= 1; i2c_sclk <= 1;endendcaseif(cnt == 3)beginif(Cmd & WR)state <= WR_DATA;else if(Cmd & RD)state <= RD_DATA;endendendWR_DATA:beginif(sclk_plus)beginif(cnt == 31)cnt <= 0;elsecnt <= cnt + 1'b1;case(cnt)0,4,8,12,16,20,24,28:begin i2c_sdat_o <= Tx_DATA[7-cnt[4:2]]; i2c_sdat_oe <= 1'd1;end  //set data;1,5,9,13,17,21,25,29:begin i2c_sclk <= 1;end //sclk posedge2,6,10,14,18,22,26,30:begin i2c_sclk <= 1;end //sclk keep high3,7,11,15,19,23,27,31:begin i2c_sclk <= 0;end   //sclk negedge
/*                          0 :begin i2c_sdat_o <= Tx_DATA[7];end1 :begin i2c_sclk <= 1;end //sclk posedge2 :begin i2c_sclk <= 1;end    //sclk keep high3 :begin i2c_sclk <= 0;end  //sclk negedge4 :begin i2c_sdat_o <= Tx_DATA[6];end5 :begin i2c_sclk <= 1;end   //sclk posedge6 :begin i2c_sclk <= 1;end    //sclk keep high7 :begin i2c_sclk <= 0;end  //sclk negedge8 :begin i2c_sdat_o <= Tx_DATA[5];end9 :begin i2c_sclk <= 1;end   //sclk posedge10:begin i2c_sclk <= 1;end    //sclk keep high11:begin i2c_sclk <= 0;end  //sclk negedge12:begin i2c_sdat_o <= Tx_DATA[4];end13:begin i2c_sclk <= 1;end   //sclk posedge14:begin i2c_sclk <= 1;end    //sclk keep high15:begin i2c_sclk <= 0;end  //sclk negedge16:begin i2c_sdat_o <= Tx_DATA[3];end17:begin i2c_sclk <= 1;end   //sclk posedge18:begin i2c_sclk <= 1;end    //sclk keep high19:begin i2c_sclk <= 0;end  //sclk negedge20:begin i2c_sdat_o <= Tx_DATA[2];end21:begin i2c_sclk <= 1;end   //sclk posedge22:begin i2c_sclk <= 1;end    //sclk keep high23:begin i2c_sclk <= 0;end  //sclk negedge  24:begin i2c_sdat_o <= Tx_DATA[1];end25:begin i2c_sclk <= 1;end //sclk posedge26:begin i2c_sclk <= 1;end    //sclk keep high27:begin i2c_sclk <= 0;end  //sclk negedge  28:begin i2c_sdat_o <= Tx_DATA[0];end29:begin i2c_sclk <= 1;end //sclk posedge30:begin i2c_sclk <= 1;end    //sclk keep high31:begin i2c_sclk <= 0;end  //sclk negedge
*/                          default:begin i2c_sdat_o <= 1; i2c_sclk <= 1;endendcaseif(cnt == 31)beginstate <= CHECK_ACK;endendendRD_DATA:beginif(sclk_plus)beginif(cnt == 31)cnt <= 0;elsecnt <= cnt + 1'b1;case(cnt)0,4,8,12,16,20,24,28:begin i2c_sdat_oe <= 1'd0; i2c_sclk <= 0;end   //set data;1,5,9,13,17,21,25,29:begin i2c_sclk <= 1;end //sclk posedge2,6,10,14,18,22,26,30:begin i2c_sclk <= 1; Rx_DATA <= {Rx_DATA[6:0],i2c_sdat};end //sclk keep high3,7,11,15,19,23,27,31:begin i2c_sclk <= 0;end   //sclk negedge                      default:begin i2c_sdat_o <= 1; i2c_sclk <= 1;endendcaseif(cnt == 31)beginstate <= GEN_ACK;endendendCHECK_ACK:beginif(sclk_plus)beginif(cnt == 3)cnt <= 0;elsecnt <= cnt + 1'b1;case(cnt)0:begin i2c_sdat_oe <= 1'd0; i2c_sclk <= 0;end1:begin i2c_sclk <= 1;end2:begin ack_o <= i2c_sdat; i2c_sclk <= 1;end3:begin i2c_sclk <= 0;enddefault:begin i2c_sdat_o <= 1; i2c_sclk <= 1;endendcaseif(cnt == 3)beginif(Cmd & STO)state <= GEN_STO;else beginstate <= IDLE;Trans_Done <= 1'b1;end                              endendendGEN_ACK:beginif(sclk_plus)beginif(cnt == 3)cnt <= 0;elsecnt <= cnt + 1'b1;case(cnt)0:begin i2c_sdat_oe <= 1'd1;i2c_sclk <= 0;if(Cmd & ACK)i2c_sdat_o <= 1'b0;else if(Cmd & NACK)i2c_sdat_o <= 1'b1;end1:begin i2c_sclk <= 1;end2:begin i2c_sclk <= 1;end3:begin i2c_sclk <= 0;enddefault:begin i2c_sdat_o <= 1; i2c_sclk <= 1;endendcaseif(cnt == 3)beginif(Cmd & STO)state <= GEN_STO;else beginstate <= IDLE;Trans_Done <= 1'b1;endendendendGEN_STO:beginif(sclk_plus)beginif(cnt == 3)cnt <= 0;elsecnt <= cnt + 1'b1;case(cnt)0:begin i2c_sdat_o <= 0; i2c_sdat_oe <= 1'd1;end1:begin i2c_sclk <= 1;end2:begin i2c_sdat_o <= 1; i2c_sclk <= 1;end3:begin i2c_sclk <= 1;enddefault:begin i2c_sdat_o <= 1; i2c_sclk <= 1;endendcaseif(cnt == 3)beginTrans_Done <= 1'b1;state <= IDLE;endendenddefault:state <= IDLE;endcaseendendmodule

二、镁光模型仿真验证

镁 光 官 网 提 供 的 EEPROM 仿 真 模 型 , 具 体 下 载 网 址 为 :
http://ww1.microchip.com/downloads/en/DeviceDoc/24xx04_Verilog_Model.zip

1、本次使用的是1 字节寄存器地址段的 24LC04B 仿真模型,进行验证

// *******************************************************************************************************
// **                                                                                       **
// **   24LC04B.v - Microchip 24LC04B 4K-BIT I2C SERIAL EEPROM (VCC = +2.5V TO +5.5V)            **
// **                                                                                       **
// *******************************************************************************************************
// **                                                                                       **
// **           This information is distributed under license from Young Engineering.       **
// **                              COPYRIGHT (c) 2003 YOUNG ENGINEERING                         **
// **                                      ALL RIGHTS RESERVED                                  **
// **                                                                                       **
// **                                                                                                   **
// **   Young Engineering provides design expertise for the digital world                               **
// **   Started in 1990, Young Engineering offers products and services for your electronic design      **
// **   project.  We have the expertise in PCB, FPGA, ASIC, firmware, and software design.              **
// **   From concept to prototype to production, we can help you.                                       **
// **                                                   **
// **   http://www.young-engineering.com/                               **
// **                                                   **
// *******************************************************************************************************
// **   This information is provided to you for your convenience and use with Microchip products only.  **
// **   Microchip disclaims all liability arising from this information and its use.            **
// **                                                   **
// **   THIS INFORMATION IS PROVIDED "AS IS." MICROCHIP MAKES NO REPRESENTATION OR WARRANTIES OF  **
// **   ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO    **
// **   THE INFORMATION PROVIDED TO YOU, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY,       **
// **   PERFORMANCE, MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR PURPOSE.             **
// **   MICROCHIP IS NOT LIABLE, UNDER ANY CIRCUMSTANCES, FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL  **
// **   DAMAGES, FOR ANY REASON WHATSOEVER.                             **
// **                                                   **
// **   It is your responsibility to ensure that your application meets with your specifications.   **
// **                                                   **
// *******************************************************************************************************
// **   Revision       : 1.3                                                                **
// **   Modified Date  : 12/04/2006                                                         **
// **   Revision History:                                                                   **
// **                                                                                       **
// **   02/01/2003:  Initial design                                                         **
// **   07/19/2004:  Fixed the timing checks and the open-drain modeling for SDA.           **
// **   01/06/2006:  Changed the legal information in the header                    **
// **   12/04/2006:  Corrected timing checks to reference proper clock edges                **
// **                Added timing check for Tbuf (bus free time)                    **
// **                                                                                       **
// *******************************************************************************************************
// **                                       TABLE OF CONTENTS                                   **
// *******************************************************************************************************
// **---------------------------------------------------------------------------------------------------**
// **   DECLARATIONS                                                                        **
// **---------------------------------------------------------------------------------------------------**
// **---------------------------------------------------------------------------------------------------**
// **   INITIALIZATION                                                                  **
// **---------------------------------------------------------------------------------------------------**
// **---------------------------------------------------------------------------------------------------**
// **   CORE LOGIC                                                                      **
// **---------------------------------------------------------------------------------------------------**
// **   1.01:  START Bit Detection                                  **
// **   1.02:  STOP Bit Detection                                   **
// **   1.03:  Input Shift Register                                 **
// **   1.04:  Input Bit Counter                                    **
// **   1.05:  Control Byte Register                                    **
// **   1.06:  Byte Address Register                                    **
// **   1.07:  Write Data Buffer                                    **
// **   1.08:  Acknowledge Generator                                    **
// **   1.09:  Acknowledge Detect                                   **
// **   1.10:  Write Cycle Timer                                    **
// **   1.11:  Write Cycle Processor                                    **
// **   1.12:  Read Data Multiplexor                                    **
// **   1.13:  Read Data Processor                                  **
// **   1.14:  SDA Data I/O Buffer                                  **
// **                                                                                       **
// **---------------------------------------------------------------------------------------------------**
// **   DEBUG LOGIC                                                                     **
// **---------------------------------------------------------------------------------------------------**
// **   2.01:  Memory Data Bytes                                    **
// **   2.02:  Write Data Buffer                                    **
// **                                                                                       **
// **---------------------------------------------------------------------------------------------------**
// **   TIMING CHECKS                                                                   **
// **---------------------------------------------------------------------------------------------------**
// **                                                                                       **
// *******************************************************************************************************`timescale 1ns/10psmodule M24LC04B (A0, A1, A2, WP, SDA, SCL, RESET);input       A0;             // unconnected pininput         A1;             // unconnected pininput         A2;             // unconnected pininput     WP;             // write protect pininout       SDA;          // serial data I/Oinput       SCL;          // serial data clockinput     RESET;    // system reset// *******************************************************************************************************
// **   DECLARATIONS                                                                        **
// *******************************************************************************************************reg                 SDA_DO;                         // serial data - outputreg            SDA_OE;                       // serial data - output enablewire                  SDA_DriveEnable;          // serial data output enablereg               SDA_DriveEnableDlyd;      // serial data output enable - delayedwire [02:00]   ChipAddress;            // hardwired chip addressreg   [03:00]     BitCounter;                 // serial bit counterreg                  START_Rcvd;                   // START bit received flagreg                 STOP_Rcvd;                    // STOP bit received flagreg                  CTRL_Rcvd;                    // control byte received flagreg                  ADDR_Rcvd;                    // byte address received flagreg                  MACK_Rcvd;                    // master acknowledge received flagreg                WrCycle;                    // memory write cyclereg                RdCycle;                    // memory read cyclereg   [07:00]     ShiftRegister;              // input data shift registerreg  [07:00]        ControlByte;                // control byte registerwire                  BlockSelect;              // memory block selectwire                RdWrBit;                    // read/write control bitreg  [08:00]     StartAddress;                 // memory access starting addressreg  [03:00]     PageAddress;                  // memory page addressreg [07:00]     WrDataByte [0:15];      // memory write data bufferwire [07:00]     RdDataByte;                 // memory read datareg  [15:00]     WrCounter;                  // write buffer counterreg  [03:00]     WrPointer;                  // write buffer pointerreg  [08:00]     RdPointer;                  // read address pointerreg                WriteActive;                // memory write cycle activereg   [07:00]     MemoryBlock0 [0:255];       // EEPROM data memory arrayreg  [07:00]     MemoryBlock1 [0:255];       // EEPROM data memory arrayinteger          LoopIndex;                  // iterative loop indexinteger          tAA;                            // timing parameterinteger          tWC;                            // timing parameter// *******************************************************************************************************
// **   INITIALIZATION                                                                      **
// *******************************************************************************************************initial tAA = 900;                                   // SCL to SDA output delayinitial tWC = 5000000;                               // memory write cycle timeinitial beginSDA_DO = 0;SDA_OE = 0;endinitial beginSTART_Rcvd = 0;STOP_Rcvd  = 0;CTRL_Rcvd  = 0;ADDR_Rcvd  = 0;MACK_Rcvd  = 0;endinitial beginBitCounter  = 0;ControlByte = 0;endinitial beginWrCycle = 0;RdCycle = 0;WriteActive = 0;endassign ChipAddress = {A2,A1,A0};// *******************************************************************************************************
// **   CORE LOGIC                                                                      **
// *******************************************************************************************************
// -------------------------------------------------------------------------------------------------------
//      1.01:  START Bit Detection
// -------------------------------------------------------------------------------------------------------always @(negedge SDA) beginif (SCL == 1) beginSTART_Rcvd <= 1;STOP_Rcvd  <= 0;CTRL_Rcvd  <= 0;ADDR_Rcvd  <= 0;MACK_Rcvd  <= 0;WrCycle <= #1 0;RdCycle <= #1 0;BitCounter <= 0;endend// -------------------------------------------------------------------------------------------------------
//      1.02:  STOP Bit Detection
// -------------------------------------------------------------------------------------------------------always @(posedge SDA) beginif (SCL == 1) beginSTART_Rcvd <= 0;STOP_Rcvd  <= 1;CTRL_Rcvd  <= 0;ADDR_Rcvd  <= 0;MACK_Rcvd  <= 0;WrCycle <= #1 0;RdCycle <= #1 0;BitCounter <= 10;endend// -------------------------------------------------------------------------------------------------------
//      1.03:  Input Shift Register
// -------------------------------------------------------------------------------------------------------always @(posedge SCL) beginShiftRegister[00] <= SDA;ShiftRegister[01] <= ShiftRegister[00];ShiftRegister[02] <= ShiftRegister[01];ShiftRegister[03] <= ShiftRegister[02];ShiftRegister[04] <= ShiftRegister[03];ShiftRegister[05] <= ShiftRegister[04];ShiftRegister[06] <= ShiftRegister[05];ShiftRegister[07] <= ShiftRegister[06];end// -------------------------------------------------------------------------------------------------------
//      1.04:  Input Bit Counter
// -------------------------------------------------------------------------------------------------------always @(posedge SCL) beginif (BitCounter < 10) BitCounter <= BitCounter + 1;end// -------------------------------------------------------------------------------------------------------
//      1.05:  Control Byte Register
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (START_Rcvd & (BitCounter == 8)) beginif (!WriteActive & (ShiftRegister[07:01] == {4'b1010,ChipAddress[02:00]})) beginif (ShiftRegister[00] == 0) WrCycle <= 1;if (ShiftRegister[00] == 1) RdCycle <= 1;ControlByte <= ShiftRegister[07:00];CTRL_Rcvd <= 1;endSTART_Rcvd <= 0;endendassign BlockSelect = ControlByte[01];assign RdWrBit     = ControlByte[00];// -------------------------------------------------------------------------------------------------------
//      1.06:  Byte Address Register
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (CTRL_Rcvd & (BitCounter == 8)) beginif (RdWrBit == 0) beginStartAddress <= {BlockSelect,ShiftRegister[07:00]};RdPointer    <= {BlockSelect,ShiftRegister[07:00]};ADDR_Rcvd <= 1;endWrCounter <= 0;WrPointer <= 0;CTRL_Rcvd <= 0;endend// -------------------------------------------------------------------------------------------------------
//      1.07:  Write Data Buffer
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (ADDR_Rcvd & (BitCounter == 8)) beginif ((WP == 0) & (RdWrBit == 0)) beginWrDataByte[WrPointer] <= ShiftRegister[07:00];WrCounter <= WrCounter + 1;WrPointer <= WrPointer + 1;endendend// -------------------------------------------------------------------------------------------------------
//      1.08:  Acknowledge Generator
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (!WriteActive) beginif (BitCounter == 8) beginif (WrCycle | (START_Rcvd & (ShiftRegister[07:01] == {4'b1010,ChipAddress[02:00]}))) beginSDA_DO <= 0;SDA_OE <= 1;end endif (BitCounter == 9) beginBitCounter <= 0;if (!RdCycle) beginSDA_DO <= 0;SDA_OE <= 0;endendendend // -------------------------------------------------------------------------------------------------------
//      1.09:  Acknowledge Detect
// -------------------------------------------------------------------------------------------------------always @(posedge SCL) beginif (RdCycle & (BitCounter == 8)) beginif ((SDA == 0) & (SDA_OE == 0)) MACK_Rcvd <= 1;endendalways @(negedge SCL) MACK_Rcvd <= 0;// -------------------------------------------------------------------------------------------------------
//      1.10:  Write Cycle Timer
// -------------------------------------------------------------------------------------------------------always @(posedge STOP_Rcvd) beginif (WrCycle & (WP == 0) & (WrCounter > 0)) beginWriteActive = 1;#(tWC);WriteActive = 0;endendalways @(posedge STOP_Rcvd) begin#(1.0);STOP_Rcvd = 0;end// -------------------------------------------------------------------------------------------------------
//      1.11:  Write Cycle Processor
// -------------------------------------------------------------------------------------------------------always @(negedge WriteActive) beginfor (LoopIndex = 0; LoopIndex < WrCounter; LoopIndex = LoopIndex + 1) beginif (StartAddress[08] == 0) beginPageAddress = StartAddress[03:00] + LoopIndex;MemoryBlock0[{StartAddress[07:04],PageAddress[03:00]}] = WrDataByte[LoopIndex[03:00]];endif (StartAddress[08] == 1) beginPageAddress = StartAddress[03:00] + LoopIndex;MemoryBlock1[{StartAddress[07:04],PageAddress[03:00]}] = WrDataByte[LoopIndex[03:00]];endendend// -------------------------------------------------------------------------------------------------------
//      1.12:  Read Data Multiplexor
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (BitCounter == 8) beginif (WrCycle & ADDR_Rcvd) beginRdPointer <= StartAddress + WrPointer + 1;endif (RdCycle) beginRdPointer <= RdPointer + 1;endendendassign RdDataByte = RdPointer[08] ? MemoryBlock1[RdPointer[07:00]] : MemoryBlock0[RdPointer[07:00]];// -------------------------------------------------------------------------------------------------------
//      1.13:  Read Data Processor
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (RdCycle) beginif (BitCounter == 8) beginSDA_DO <= 0;SDA_OE <= 0;endelse if (BitCounter == 9) beginSDA_DO <= RdDataByte[07];if (MACK_Rcvd) SDA_OE <= 1;endelse beginSDA_DO <= RdDataByte[7-BitCounter];endendend// -------------------------------------------------------------------------------------------------------
//      1.14:  SDA Data I/O Buffer
// -------------------------------------------------------------------------------------------------------bufif1 (SDA, 1'b0, SDA_DriveEnableDlyd);assign SDA_DriveEnable = !SDA_DO & SDA_OE;always @(SDA_DriveEnable) SDA_DriveEnableDlyd <= #(tAA) SDA_DriveEnable;// *******************************************************************************************************
// **   DEBUG LOGIC                                                                         **
// *******************************************************************************************************
// -------------------------------------------------------------------------------------------------------
//      2.01:  Memory Data Bytes
// -------------------------------------------------------------------------------------------------------wire [07:00]  MemoryByte0_00 = MemoryBlock0[00];wire [07:00] MemoryByte0_01 = MemoryBlock0[01];wire [07:00] MemoryByte0_02 = MemoryBlock0[02];wire [07:00] MemoryByte0_03 = MemoryBlock0[03];wire [07:00] MemoryByte0_04 = MemoryBlock0[04];wire [07:00] MemoryByte0_05 = MemoryBlock0[05];wire [07:00] MemoryByte0_06 = MemoryBlock0[06];wire [07:00] MemoryByte0_07 = MemoryBlock0[07];wire [07:00] MemoryByte0_08 = MemoryBlock0[08];wire [07:00] MemoryByte0_09 = MemoryBlock0[09];wire [07:00] MemoryByte0_0A = MemoryBlock0[10];wire [07:00] MemoryByte0_0B = MemoryBlock0[11];wire [07:00] MemoryByte0_0C = MemoryBlock0[12];wire [07:00] MemoryByte0_0D = MemoryBlock0[13];wire [07:00] MemoryByte0_0E = MemoryBlock0[14];wire [07:00] MemoryByte0_0F = MemoryBlock0[15];wire [07:00] MemoryByte1_00 = MemoryBlock1[00];wire [07:00] MemoryByte1_01 = MemoryBlock1[01];wire [07:00] MemoryByte1_02 = MemoryBlock1[02];wire [07:00] MemoryByte1_03 = MemoryBlock1[03];wire [07:00] MemoryByte1_04 = MemoryBlock1[04];wire [07:00] MemoryByte1_05 = MemoryBlock1[05];wire [07:00] MemoryByte1_06 = MemoryBlock1[06];wire [07:00] MemoryByte1_07 = MemoryBlock1[07];wire [07:00] MemoryByte1_08 = MemoryBlock1[08];wire [07:00] MemoryByte1_09 = MemoryBlock1[09];wire [07:00] MemoryByte1_0A = MemoryBlock1[10];wire [07:00] MemoryByte1_0B = MemoryBlock1[11];wire [07:00] MemoryByte1_0C = MemoryBlock1[12];wire [07:00] MemoryByte1_0D = MemoryBlock1[13];wire [07:00] MemoryByte1_0E = MemoryBlock1[14];wire [07:00] MemoryByte1_0F = MemoryBlock1[15];// -------------------------------------------------------------------------------------------------------
//      2.02:  Write Data Buffer
// -------------------------------------------------------------------------------------------------------wire [07:00]  WriteData_0 = WrDataByte[00];wire [07:00]  WriteData_1 = WrDataByte[01];wire [07:00]  WriteData_2 = WrDataByte[02];wire [07:00]  WriteData_3 = WrDataByte[03];wire [07:00]  WriteData_4 = WrDataByte[04];wire [07:00]  WriteData_5 = WrDataByte[05];wire [07:00]  WriteData_6 = WrDataByte[06];wire [07:00]  WriteData_7 = WrDataByte[07];wire [07:00]  WriteData_8 = WrDataByte[08];wire [07:00]  WriteData_9 = WrDataByte[09];wire [07:00]  WriteData_A = WrDataByte[10];wire [07:00]  WriteData_B = WrDataByte[11];wire [07:00]  WriteData_C = WrDataByte[12];wire [07:00]  WriteData_D = WrDataByte[13];wire [07:00]  WriteData_E = WrDataByte[14];wire [07:00]  WriteData_F = WrDataByte[15];// *******************************************************************************************************
// **   TIMING CHECKS                                                                       **
// *******************************************************************************************************wire TimingCheckEnable = (RESET == 0) & (SDA_OE == 0);specifyspecparamtHI = 600,                                     // SCL pulse width - hightLO = 1300,                                    // SCL pulse width - lowtSU_STA = 600,                                 // SCL to SDA setup timetHD_STA = 600,                                 // SCL to SDA hold timetSU_DAT = 100,                                 // SDA to SCL setup timetSU_STO = 600,                                 // SCL to SDA setup timetBUF = 1300;                                   // Bus free time$width (posedge SCL, tHI);$width (negedge SCL, tLO);$width (posedge SDA &&& SCL, tBUF);$setup (posedge SCL, negedge SDA &&& TimingCheckEnable, tSU_STA);$setup (SDA, posedge SCL &&& TimingCheckEnable, tSU_DAT);$setup (posedge SCL, posedge SDA &&& TimingCheckEnable, tSU_STO);$hold  (negedge SDA &&& TimingCheckEnable, negedge SCL, tHD_STA);endspecifyendmodule

2、M24LC64仿真模型供大家使用

// *******************************************************************************************************
// **                                                                                                   **
// **   24LC64.v - Microchip 24LC64 64K-BIT I2C SERIAL EEPROM (VCC = +2.5V TO +5.5V)                    **
// **                                                                                                   **
// *******************************************************************************************************
// **                                                                                                   **
// **                   This information is distributed under license from Young Engineering.           **
// **                              COPYRIGHT (c) 2009 YOUNG ENGINEERING                                 **
// **                                      ALL RIGHTS RESERVED                                          **
// **                                                                                                   **
// **                                                                                                   **
// **   Young Engineering provides design expertise for the digital world                               **
// **   Started in 1990, Young Engineering offers products and services for your electronic design      **
// **   project.  We have the expertise in PCB, FPGA, ASIC, firmware, and software design.              **
// **   From concept to prototype to production, we can help you.                                       **
// **                                                                                                   **
// **   http://www.young-engineering.com/                                                               **
// **                                                                                                   **
// *******************************************************************************************************
// **   This information is provided to you for your convenience and use with Microchip products only.  **
// **   Microchip disclaims all liability arising from this information and its use.                    **
// **                                                                                                   **
// **   THIS INFORMATION IS PROVIDED "AS IS." MICROCHIP MAKES NO REPRESENTATION OR WARRANTIES OF        **
// **   ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO        **
// **   THE INFORMATION PROVIDED TO YOU, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY,           **
// **   PERFORMANCE, MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR PURPOSE.                         **
// **   MICROCHIP IS NOT LIABLE, UNDER ANY CIRCUMSTANCES, FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL      **
// **   DAMAGES, FOR ANY REASON WHATSOEVER.                                                             **
// **                                                                                                   **
// **   It is your responsibility to ensure that your application meets with your specifications.       **
// **                                                                                                   **
// *******************************************************************************************************
// **   Revision       : 1.4                                                                            **
// **   Modified Date  : 02/04/2009                                                                     **
// **   Revision History:                                                                               **
// **                                                                                                   **
// **   10/01/2003:  Initial design                                                                     **
// **   07/19/2004:  Fixed the timing checks and the open-drain modeling for SDA.                       **
// **   01/06/2006:  Changed the legal information in the header                                        **
// **   12/04/2006:  Corrected timing checks to reference proper clock edges                            **
// **                Added timing check for Tbuf (bus free time)                                        **
// **                Reduced memory blocks to single, monolithic array                                  **
// **   02/04/2009:  Added timing checks for tSU_WP and tHD_WP                                          **
// **                                                                                                   **
// *******************************************************************************************************
// **                                       TABLE OF CONTENTS                                           **
// *******************************************************************************************************
// **---------------------------------------------------------------------------------------------------**
// **   DECLARATIONS                                                                                    **
// **---------------------------------------------------------------------------------------------------**
// **---------------------------------------------------------------------------------------------------**
// **   INITIALIZATION                                                                                  **
// **---------------------------------------------------------------------------------------------------**
// **---------------------------------------------------------------------------------------------------**
// **   CORE LOGIC                                                                                      **
// **---------------------------------------------------------------------------------------------------**
// **   1.01:  START Bit Detection                                                                      **
// **   1.02:  STOP Bit Detection                                                                       **
// **   1.03:  Input Shift Register                                                                     **
// **   1.04:  Input Bit Counter                                                                        **
// **   1.05:  Control Byte Register                                                                    **
// **   1.06:  Byte Address Register                                                                    **
// **   1.07:  Write Data Buffer                                                                        **
// **   1.08:  Acknowledge Generator                                                                    **
// **   1.09:  Acknowledge Detect                                                                       **
// **   1.10:  Write Cycle Timer                                                                        **
// **   1.11:  Write Cycle Processor                                                                    **
// **   1.12:  Read Data Multiplexor                                                                    **
// **   1.13:  Read Data Processor                                                                      **
// **   1.14:  SDA Data I/O Buffer                                                                      **
// **                                                                                                   **
// **---------------------------------------------------------------------------------------------------**
// **   DEBUG LOGIC                                                                                     **
// **---------------------------------------------------------------------------------------------------**
// **   2.01:  Memory Data Bytes                                                                        **
// **   2.02:  Write Data Buffer                                                                        **
// **                                                                                                   **
// **---------------------------------------------------------------------------------------------------**
// **   TIMING CHECKS                                                                                   **
// **---------------------------------------------------------------------------------------------------**
// **                                                                                                   **
// *******************************************************************************************************`timescale 1ns/10psmodule M24LC64 (A0, A1, A2, WP, SDA, SCL, RESET);input                A0;                             // chip select bitinput                A1;                             // chip select bitinput                A2;                             // chip select bitinput                WP;                             // write protect pininout                SDA;                            // serial data I/Oinput                SCL;                            // serial data clockinput                RESET;                          // system reset// *******************************************************************************************************
// **   DECLARATIONS                                                                                    **
// *******************************************************************************************************reg                  SDA_DO;                         // serial data - outputreg                  SDA_OE;                         // serial data - output enablewire                 SDA_DriveEnable;                // serial data output enablereg                  SDA_DriveEnableDlyd;            // serial data output enable - delayedwire [02:00]         ChipAddress;                    // hardwired chip addressreg  [03:00]         BitCounter;                     // serial bit counterreg                  START_Rcvd;                     // START bit received flagreg                  STOP_Rcvd;                      // STOP bit received flagreg                  CTRL_Rcvd;                      // control byte received flagreg                  ADHI_Rcvd;                      // byte address hi received flagreg                  ADLO_Rcvd;                      // byte address lo received flagreg                  MACK_Rcvd;                      // master acknowledge received flagreg                  WrCycle;                        // memory write cyclereg                  RdCycle;                        // memory read cyclereg  [07:00]         ShiftRegister;                  // input data shift registerreg  [07:00]         ControlByte;                    // control byte registerwire                 RdWrBit;                        // read/write control bitreg  [12:00]         StartAddress;                   // memory access starting addressreg  [04:00]         PageAddress;                    // memory page addressreg  [07:00]         WrDataByte [0:31];              // memory write data bufferwire [07:00]         RdDataByte;                     // memory read datareg  [15:00]         WrCounter;                      // write buffer counterreg  [04:00]         WrPointer;                      // write buffer pointerreg  [12:00]         RdPointer;                      // read address pointerreg                  WriteActive;                    // memory write cycle activereg  [07:00]         MemoryBlock [0:8191];           // EEPROM data memory arrayinteger              LoopIndex;                      // iterative loop indexinteger              tAA;                            // timing parameterinteger              tWC;                            // timing parameter// *******************************************************************************************************
// **   INITIALIZATION                                                                                  **
// *******************************************************************************************************//----------------------------
//------写数据间隔改动----------initial tAA = 900;                                   // SCL to SDA output delayinitial tWC = 500;                                   // memory write cycle time//   initial tAA = 900;                                   // SCL to SDA output delay
//   initial tWC = 5000000;                               // memory write cycle timeinitial beginSDA_DO = 0;SDA_OE = 0;endinitial beginSTART_Rcvd = 0;STOP_Rcvd  = 0;CTRL_Rcvd  = 0;ADHI_Rcvd  = 0;ADLO_Rcvd  = 0;MACK_Rcvd  = 0;endinitial beginBitCounter  = 0;ControlByte = 0;endinitial beginWrCycle = 0;RdCycle = 0;WriteActive = 0;endassign ChipAddress = {A2,A1,A0};// *******************************************************************************************************
// **   CORE LOGIC                                                                                      **
// *******************************************************************************************************
// -------------------------------------------------------------------------------------------------------
//      1.01:  START Bit Detection
// -------------------------------------------------------------------------------------------------------always @(negedge SDA) beginif (SCL == 1) beginSTART_Rcvd <= 1;STOP_Rcvd  <= 0;CTRL_Rcvd  <= 0;ADHI_Rcvd  <= 0;ADLO_Rcvd  <= 0;MACK_Rcvd  <= 0;WrCycle <= #1 0;RdCycle <= #1 0;BitCounter <= 0;endend// -------------------------------------------------------------------------------------------------------
//      1.02:  STOP Bit Detection
// -------------------------------------------------------------------------------------------------------always @(posedge SDA) beginif (SCL == 1) beginSTART_Rcvd <= 0;STOP_Rcvd  <= 1;CTRL_Rcvd  <= 0;ADHI_Rcvd  <= 0;ADLO_Rcvd  <= 0;MACK_Rcvd  <= 0;WrCycle <= #1 0;RdCycle <= #1 0;BitCounter <= 10;endend// -------------------------------------------------------------------------------------------------------
//      1.03:  Input Shift Register
// -------------------------------------------------------------------------------------------------------always @(posedge SCL) beginShiftRegister[00] <= SDA;ShiftRegister[01] <= ShiftRegister[00];ShiftRegister[02] <= ShiftRegister[01];ShiftRegister[03] <= ShiftRegister[02];ShiftRegister[04] <= ShiftRegister[03];ShiftRegister[05] <= ShiftRegister[04];ShiftRegister[06] <= ShiftRegister[05];ShiftRegister[07] <= ShiftRegister[06];end// -------------------------------------------------------------------------------------------------------
//      1.04:  Input Bit Counter
// -------------------------------------------------------------------------------------------------------always @(posedge SCL) beginif (BitCounter < 10) BitCounter <= BitCounter + 1;end// -------------------------------------------------------------------------------------------------------
//      1.05:  Control Byte Register
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (START_Rcvd & (BitCounter == 8)) beginif (!WriteActive & (ShiftRegister[07:01] == {4'b1010,ChipAddress[02:00]})) beginif (ShiftRegister[00] == 0) WrCycle <= 1;if (ShiftRegister[00] == 1) RdCycle <= 1;ControlByte <= ShiftRegister[07:00];CTRL_Rcvd <= 1;endSTART_Rcvd <= 0;endendassign RdWrBit = ControlByte[00];// -------------------------------------------------------------------------------------------------------
//      1.06:  Byte Address Register
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (CTRL_Rcvd & (BitCounter == 8)) beginif (RdWrBit == 0) beginStartAddress[12:08] <= ShiftRegister[04:00];RdPointer[12:08]    <= ShiftRegister[04:00];ADHI_Rcvd <= 1;endWrCounter <= 0;WrPointer <= 0;CTRL_Rcvd <= 0;endendalways @(negedge SCL) beginif (ADHI_Rcvd & (BitCounter == 8)) beginif (RdWrBit == 0) beginStartAddress[07:00] <= ShiftRegister[07:00];RdPointer[07:00]    <= ShiftRegister[07:00];ADLO_Rcvd <= 1;endWrCounter <= 0;WrPointer <= 0;ADHI_Rcvd <= 0;endend// -------------------------------------------------------------------------------------------------------
//      1.07:  Write Data Buffer
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (ADLO_Rcvd & (BitCounter == 8)) beginif (RdWrBit == 0) beginWrDataByte[WrPointer] <= ShiftRegister[07:00];WrCounter <= WrCounter + 1;WrPointer <= WrPointer + 1;endendend// -------------------------------------------------------------------------------------------------------
//      1.08:  Acknowledge Generator
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (!WriteActive) beginif (BitCounter == 8) beginif (WrCycle | (START_Rcvd & (ShiftRegister[07:01] == {4'b1010,ChipAddress[02:00]}))) beginSDA_DO <= 0;SDA_OE <= 1;end endif (BitCounter == 9) beginBitCounter <= 0;if (!RdCycle) beginSDA_DO <= 0;SDA_OE <= 0;endendendend // -------------------------------------------------------------------------------------------------------
//      1.09:  Acknowledge Detect
// -------------------------------------------------------------------------------------------------------always @(posedge SCL) beginif (RdCycle & (BitCounter == 8)) beginif ((SDA == 0) & (SDA_OE == 0)) MACK_Rcvd <= 1;endendalways @(negedge SCL) MACK_Rcvd <= 0;// -------------------------------------------------------------------------------------------------------
//      1.10:  Write Cycle Timer
// -------------------------------------------------------------------------------------------------------always @(posedge STOP_Rcvd) beginif (WrCycle & (WP == 0) & (WrCounter > 0)) beginWriteActive = 1;#(tWC);WriteActive = 0;endendalways @(posedge STOP_Rcvd) begin#(1.0);STOP_Rcvd = 0;end// -------------------------------------------------------------------------------------------------------
//      1.11:  Write Cycle Processor
// -------------------------------------------------------------------------------------------------------always @(negedge WriteActive) beginfor (LoopIndex = 0; LoopIndex < WrCounter; LoopIndex = LoopIndex + 1) beginPageAddress = StartAddress[04:00] + LoopIndex;MemoryBlock[{StartAddress[12:05],PageAddress[04:00]}] = WrDataByte[LoopIndex[04:00]];endend// -------------------------------------------------------------------------------------------------------
//      1.12:  Read Data Multiplexor
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (BitCounter == 8) beginif (WrCycle & ADLO_Rcvd) beginRdPointer <= StartAddress + WrPointer + 1;endif (RdCycle) beginRdPointer <= RdPointer + 1;endendendassign RdDataByte = MemoryBlock[RdPointer[12:00]];// -------------------------------------------------------------------------------------------------------
//      1.13:  Read Data Processor
// -------------------------------------------------------------------------------------------------------always @(negedge SCL) beginif (RdCycle) beginif (BitCounter == 8) beginSDA_DO <= 0;SDA_OE <= 0;endelse if (BitCounter == 9) beginSDA_DO <= RdDataByte[07];if (MACK_Rcvd) SDA_OE <= 1;endelse beginSDA_DO <= RdDataByte[7-BitCounter];endendend// -------------------------------------------------------------------------------------------------------
//      1.14:  SDA Data I/O Buffer
// -------------------------------------------------------------------------------------------------------bufif1 (SDA, 1'b0, SDA_DriveEnableDlyd);assign SDA_DriveEnable = !SDA_DO & SDA_OE;always @(SDA_DriveEnable) SDA_DriveEnableDlyd <= #(tAA) SDA_DriveEnable;// *******************************************************************************************************
// **   DEBUG LOGIC                                                                                     **
// *******************************************************************************************************
// -------------------------------------------------------------------------------------------------------
//      2.01:  Memory Data Bytes
// -------------------------------------------------------------------------------------------------------wire [07:00] MemoryByte_000 = MemoryBlock[00];wire [07:00] MemoryByte_001 = MemoryBlock[01];wire [07:00] MemoryByte_002 = MemoryBlock[02];wire [07:00] MemoryByte_003 = MemoryBlock[03];wire [07:00] MemoryByte_004 = MemoryBlock[04];wire [07:00] MemoryByte_005 = MemoryBlock[05];wire [07:00] MemoryByte_006 = MemoryBlock[06];wire [07:00] MemoryByte_007 = MemoryBlock[07];wire [07:00] MemoryByte_008 = MemoryBlock[08];wire [07:00] MemoryByte_009 = MemoryBlock[09];wire [07:00] MemoryByte_00A = MemoryBlock[10];wire [07:00] MemoryByte_00B = MemoryBlock[11];wire [07:00] MemoryByte_00C = MemoryBlock[12];wire [07:00] MemoryByte_00D = MemoryBlock[13];wire [07:00] MemoryByte_00E = MemoryBlock[14];wire [07:00] MemoryByte_00F = MemoryBlock[15];// -------------------------------------------------------------------------------------------------------
//      2.02:  Write Data Buffer
// -------------------------------------------------------------------------------------------------------wire [07:00] WriteData_00 = WrDataByte[00];wire [07:00] WriteData_01 = WrDataByte[01];wire [07:00] WriteData_02 = WrDataByte[02];wire [07:00] WriteData_03 = WrDataByte[03];wire [07:00] WriteData_04 = WrDataByte[04];wire [07:00] WriteData_05 = WrDataByte[05];wire [07:00] WriteData_06 = WrDataByte[06];wire [07:00] WriteData_07 = WrDataByte[07];wire [07:00] WriteData_08 = WrDataByte[08];wire [07:00] WriteData_09 = WrDataByte[09];wire [07:00] WriteData_0A = WrDataByte[10];wire [07:00] WriteData_0B = WrDataByte[11];wire [07:00] WriteData_0C = WrDataByte[12];wire [07:00] WriteData_0D = WrDataByte[13];wire [07:00] WriteData_0E = WrDataByte[14];wire [07:00] WriteData_0F = WrDataByte[15];wire [07:00] WriteData_10 = WrDataByte[16];wire [07:00] WriteData_11 = WrDataByte[17];wire [07:00] WriteData_12 = WrDataByte[18];wire [07:00] WriteData_13 = WrDataByte[19];wire [07:00] WriteData_14 = WrDataByte[20];wire [07:00] WriteData_15 = WrDataByte[21];wire [07:00] WriteData_16 = WrDataByte[22];wire [07:00] WriteData_17 = WrDataByte[23];wire [07:00] WriteData_18 = WrDataByte[24];wire [07:00] WriteData_19 = WrDataByte[25];wire [07:00] WriteData_1A = WrDataByte[26];wire [07:00] WriteData_1B = WrDataByte[27];wire [07:00] WriteData_1C = WrDataByte[28];wire [07:00] WriteData_1D = WrDataByte[29];wire [07:00] WriteData_1E = WrDataByte[30];wire [07:00] WriteData_1F = WrDataByte[31];// *******************************************************************************************************
// **   TIMING CHECKS                                                                                   **
// *******************************************************************************************************wire TimingCheckEnable = (RESET == 0) & (SDA_OE == 0);wire StopTimingCheckEnable = TimingCheckEnable && SCL;//--------------------------------
//-------仿真时时序约束需改动--------
//--------------------------------specifyspecparamtHI = 600,                                     // SCL pulse width - high
//         tLO = 1300,                                    // SCL pulse width - lowtLO = 600, tSU_STA = 600,                                 // SCL to SDA setup timetHD_STA = 600,                                 // SCL to SDA hold timetSU_DAT = 100,                                 // SDA to SCL setup timetSU_STO = 600,                                 // SCL to SDA setup timetSU_WP = 600,                                  // WP to SDA setup timetHD_WP = 1300,                                 // WP to SDA hold time
//         tBUF = 1300;                                   // Bus free timetBUF = 600; $width (posedge SCL, tHI);$width (negedge SCL, tLO);$width (posedge SDA &&& SCL, tBUF);$setup (posedge SCL, negedge SDA &&& TimingCheckEnable, tSU_STA);$setup (SDA, posedge SCL &&& TimingCheckEnable, tSU_DAT);$setup (posedge SCL, posedge SDA &&& TimingCheckEnable, tSU_STO);$setup (WP, posedge SDA &&& StopTimingCheckEnable, tSU_WP);$hold  (negedge SDA &&& TimingCheckEnable, negedge SCL, tHD_STA);$hold  (posedge SDA &&& StopTimingCheckEnable, WP, tHD_WP);endspecifyendmodule

三、testbench文件

`timescale 1ns / 1ps
module i2c_bit_shift_tb;reg Clk;reg Rst_n;reg [5:0] Cmd;reg Go;wire [7:0] Rx_DATA;reg [7:0] Tx_DATA;wire Trans_Done;wire ack_o;wire i2c_sclk;wire i2c_sdat;pullup PUP(i2c_sdat);localparam WR   = 6'b000001,   //写请求STA  = 6'b000010,   //起始位请求RD   = 6'b000100,   //读请求STO  = 6'b001000,   //停止位请求ACK  = 6'b010000,   //应答位请求NACK = 6'b100000;   //无应答请求i2c_bit_shift DUT(.Clk(Clk),.Rst_n(Rst_n),.Cmd(Cmd),.Go(Go),.Rx_DATA(Rx_DATA),.Tx_DATA(Tx_DATA),.Trans_Done(Trans_Done),.ack_o(ack_o),.i2c_sclk(i2c_sclk),.i2c_sdat(i2c_sdat));M24LC04B M24LC04B(.A0(0), .A1(0), .A2(0), .WP(0), .SDA(i2c_sdat), .SCL(i2c_sclk), .RESET(~Rst_n));always #10 Clk = ~Clk;initial beginClk = 1;Rst_n = 0;Cmd = 6'b000000;Go = 0;Tx_DATA = 8'd0;#2001;Rst_n = 1;#2000;//写数据操作,往EEPROM器件的B1地址写数据DA//第一次:起始位+EEPROM器件地址(7位)+写方向(1位)Cmd = STA | WR;Go = 1;Tx_DATA = 8'hA0 | 8'd0;//写方向@ (posedge Clk);Go = 0;@ (posedge Trans_Done);#200;//第二次:写8位EEPROM的寄存器地址Cmd = WR;Go = 1;Tx_DATA = 8'hB1;//写地址B1@ (posedge Clk);Go = 0;@ (posedge Trans_Done);#200;//第三次:写8位数据 + 停止位Cmd = WR | STO;Go = 1;Tx_DATA = 8'hda;//写数据DA@ (posedge Clk);Go = 0;@ (posedge Trans_Done);#200;#5000000; //仿真模型的两次操作时间间隔//读数据操作,从EEPROM器件的B1地址读数据//第一次:起始位+EEPROM器件地址(7位)+写方向(1位)Cmd = STA | WR;Go = 1;Tx_DATA = 8'hA0 | 8'd0;//写方向@ (posedge Clk);Go = 0;@ (posedge Trans_Done);#200;//第二次:写8位EEPROM的寄存器地址Cmd = WR;Go = 1;Tx_DATA = 8'hB1;//写地址B1@ (posedge Clk);Go = 0;@ (posedge Trans_Done);#200;//第三次:起始位+EEPROM器件地址(7位)+读方向(1位)Cmd = STA | WR;Go = 1;Tx_DATA = 8'hA0 | 8'd1;//读方向@ (posedge Clk);Go = 0;@ (posedge Trans_Done);#200;//第四次:读8位数据 + 停止位Cmd = RD | STO;Go = 1;@ (posedge Clk);Go = 0;@ (posedge Trans_Done);#200;#2000;$stop;endendmodule
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2019/10/23 23:32:08
// Design Name:
// Module Name: i2c_control_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module i2c_control_tb;reg Clk;reg Rst_n;reg wrreg_req;reg rdreg_req;reg [15:0]addr;reg addr_mode;reg [7:0]wrdata;wire [7:0]rddata;reg [7:0]device_id;wire RW_Done;wire ack;wire i2c_sclk;wire i2c_sdat;pullup PUP(i2c_sdat);i2c_control DUT(.Clk        (Clk      ),.Rst_n      (Rst_n    ),.wrreg_req  (wrreg_req),.rdreg_req  (rdreg_req),.addr       (addr     ),.addr_mode  (addr_mode),.wrdata     (wrdata   ),.rddata     (rddata   ),.device_id  (device_id),.RW_Done    (RW_Done  ),.ack        (ack      ),.i2c_sclk   (i2c_sclk ),.i2c_sdat   (i2c_sdat ));M24LC04B M24LC04B(.A0(0), .A1(0), .A2(0), .WP(0), .SDA(i2c_sdat), .SCL(i2c_sclk), .RESET(~Rst_n));initial Clk = 1;always #10 Clk = ~Clk;initial beginRst_n = 0;rdreg_req = 0;wrreg_req = 0;#2001;Rst_n = 1;#2000;write_one_byte(8'hA0,8'h0A,8'hd1);write_one_byte(8'hA0,8'h0B,8'hd2);write_one_byte(8'hA0,8'h0C,8'hd3);write_one_byte(8'hA0,8'h0F,8'hd4);read_one_byte(8'hA0,8'h0A);read_one_byte(8'hA0,8'h0B);read_one_byte(8'hA0,8'h0C);read_one_byte(8'hA0,8'h0F);$stop;    endtask write_one_byte;input [7:0]id;input [7:0]mem_address; input [7:0]data;beginaddr = {8'd0,mem_address};device_id = id;addr_mode = 0;wrdata = data;wrreg_req = 1;#20;wrreg_req = 0;@(posedge RW_Done);#5000000;endendtasktask read_one_byte;input [7:0]id;input [7:0]mem_address; beginaddr = {8'd0,mem_address};device_id = id;addr_mode = 0;rdreg_req = 1;#20;rdreg_req = 0;@(posedge RW_Done);#5000000;endendtaskendmodule

四、完整工程下载

芯路恒的开源工程,需要的自提。附文档。
链接:https://pan.baidu.com/s/1wdAYkX4ricvnc7v8yUNgRQ?pwd=FBMZ
提取码:FBMZ
–来自百度网盘超级会员V5的分享

FPGA:IIC验证镁光EEPROM仿真模型(纯Verilog)相关推荐

  1. FPGA纯verilog代码实现图像对数变换,提供工程源码和技术支持

    目录 1.图像对数变换理论 2.log系数的matlab生成 3.FPGA实现图像对数变换 4.vivado与matlab联合仿真 5.vivado工程介绍 6.上板调试验证并演示 7.福利:工程代码 ...

  2. FPGA纯verilog实现UDP通信,三速网自协商仲裁,动态ARP和Ping功能,提供工程源码和技术支持

    目录 1.前言 2.我这里已有的UDP方案 3.UDP详细设计方案 MAC层发送 MAC发送模式 ARP发送 IP层发送 IP发送模式 UDP发送 MAC层接收 ARP接收 IP层接收 UDP接收 S ...

  3. FPGA纯verilog代码读写N25Q128A QSPI Flash 提供工程源码和技术支持

    目录 1.N25Q128A芯片解读 2.N25Q128A读写时序 3.整体设计思路架构 4.verilog读写Flash驱动设计 5.verilog读写Flash控制器设计 6.FIFO缓存设计 7. ...

  4. FPGA纯Verilog实现任意尺寸图像缩放,串口指令控制切换,贴近真实项目,提供工程源码和技术支持

    目录 1.前言 2.目前主流的FPGA图像缩放方案 3.本方案的优越性 4.详细设计方案 5.vivado工程详解 6.上板调试验证并演示 7.福利:工程源码获取 1.前言 代码使用纯verilog实 ...

  5. IIC通信协议详解 PCF8591应用(Verilog实现FPGA)

    IIC通信协议详解 & PCF8591应用(Verilog实现/FPGA) 该文章结合PCF8591 8-bit AD/DA 模数/数模转换器来详细介绍IIC通信协议,尽量做到条理清晰,通俗易 ...

  6. EtherCAT 总线主站 FPGA 挂百兆网口串接伺服 ethercat 主站 FPGA verilog 代码 全部在 FPGA上实现,纯 Verilog 实现,无软核

    EtherCAT 总线 demo 板介绍 一.测试架构介绍 总线部分包括 EtherCAT 协议.Canopen 协议.1588 同步协议,全部在 FPGA上实现,纯 Verilog 实现,无软核,时 ...

  7. 重温FPGA设计流程(六、纯Verilog实现数字钟)

    软件:Vivado2017.4 板卡:Ego1 型号:xc7a35tcsg324-1 六.纯Verilog实现数字钟 clock1_top.v `timescale 1ns / 1ps module ...

  8. FPGA协同验证方法-资料整理

    https://www.cnblogs.com/limanjihe/p/9796998.html 用FPGA对ASIC进行原型验证的过程 https://max.book118.com/html/20 ...

  9. FPGA—IIC 设计

    FPGA-IIC 设计 串行同步半双工通信 特点 连接简单:只有两条总线(串行时钟总线SCL.串行数据总线SDA): 多主多从:可以有多个主机,多个从机: ID唯一:由器件地址决定: 传输速度快:I2 ...

最新文章

  1. 用 Python 画个生日蛋糕为朋友庆生
  2. BeautifulSoup中的.text方法和get_text()方法的区别
  3. java回显怎么实现_Java实现简单的server/client回显功能
  4. idea项目名后出现中括号别名
  5. vue2.0中ckeckbox(复选框)的使用心得,及对click事件和change的理解
  6. 对于一些敏感的数据(例如密码),为什么使用字符数组存储比使用String更安全?
  7. php装curl拓展出错
  8. python版本回退_版本回退
  9. 分享Monaco.ttf字体(Mac样式)
  10. Android5.0更新内容简介
  11. 如何远程访问办公室电脑(过年工作不打烊),亲测有效稳定
  12. 介绍一下115sha1链接使用方法
  13. java实现来电弹屏_客服系统如何实现1秒来电弹屏?
  14. 计算机管理 未分配磁盘,win7系统对未分配磁盘空间进行分区的操作方法
  15. 筋斗云教程(一): 运行筋斗云应用
  16. 凡子谷机器人创客教育_创客机器人教育基地
  17. 数学建模python实现基础编程练习4
  18. 一个教训:养成良好的编程习惯的重要性
  19. AWS DynamoDB基础使用
  20. tokenizer.encode_plus方法

热门文章

  1. python图书馆抢座代码_“我去图书馆”公众号代码抢座的实现
  2. 重装系统后桌面只有一个回收站的解决方法
  3. 基于好奇心的神经网络算法自监督预测算法
  4. monkey常用命令及其用法
  5. 单页面vue使用webwork
  6. 54. 将u-boot.bin从SD卡搬运到DDR内存中
  7. java枚举 tostring_Java枚举重写toString()
  8. RSA加密原理与过程
  9. webservice调用错误
  10. 一路在赶,别忘了珍惜现在--《爱的太晚》古巨基