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

news/2024/11/20 13:45:37/

目录

  • 日常·唠嗑
  • 一、程序设计
  • 二、镁光模型仿真验证
  • 三、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的分享


http://www.ppmy.cn/news/12532.html

相关文章

Linux文件目录与路径、内容查找命令及文件颜色知识总结

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java案例分…

2023.1.16 (一) 上午 关于人口老龄化的研究——老龄化的式子表示及建国以来的老龄化情况

2023.1.16&#xff08;一&#xff09;上午 关于人口老龄化的研究——老龄化的式子表示及建国以来的老龄化情况前言定义建模模型细节代码实现.in文件.out文件前言 今天研究一个简单一点的问题&#xff0c;预计2023.1.18正式结题做PPT展示。 定义 老龄人: 60岁≤ 的人 老龄化&…

测开-基础篇

目录 一、软件测试的生命周期 &#x1f351;软件的生命周期 &#x1f351;软件测试的生命周期 二、如何描述一个BUG&#xff1f; 三、BUG的等级 四、BUG的生命周期 五、面试题&#xff1a;关于BUG&#xff0c;与开发人员产生纠纷怎么办&#xff1f; 一、软件测试的生命周…

whistle抓包工具应用

原文地址&#xff1a;(67条消息) whistle抓包工具学习_BBC蟹耳总的博客-CSDN博客_w2 抓包 一、安装whistle 首先安装好whistle抓包工具&#xff0c;有以下两个步骤 在终端中全局安装whistle&#xff1a;npm install -g whistle可以通过whistle help查看相关信息&#xff0c;…

数组常用方法总结 (6) :includes / indexOf / lastIndexOf / valueOf / toString / isArray

includes 检测数组是否包含某值&#xff0c;返回值为布尔值&#xff0c;找到一个就会返回 true&#xff0c;如果直到遍历完数组都未找到匹配的值&#xff0c;则返回 false。arr.includes(value,index)第一个参数为想要查找的值。第二个参数为查找开始的位置&#xff0c;如果为…

【C语言进阶】自定义类型之结构体

目录一&#xff1a;结构体1.1&#xff1a;结构的基础知识&#xff1a; 1.2&#xff1a;结构的声明&#xff1a; 1.3&#xff1a;特殊声明&#xff08;匿名结构体&#xff09;&#xff1a; 1.4&#xff1a;结构的自引用&#xff1a; 1.5&#xff1a;结构体变量的定义和初始化&am…

python中的设计模式:单例模式、工厂模式

目录 一.设计模式 二.单例模式 二.工厂模式 优点: 总结 一.设计模式 设计模式是一种编程套路&#xff0c;可以极大的方便程序的开发。 最常见、最经典的设计模式,就是我们所学习的面向对象了。 除了面向对象外,在编程中也有很多既定的套路可以方便开发&#xff0c;我们称…

第328场周赛2537. 统计好子数组的数目

原题链接&#xff1a;统计好子数组的数目 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回 nums 中 好 子数组的数目。 一个子数组 arr 如果有 至少 k 对下标 (i, j) 满足 i < j 且 arr[i] arr[j] &#xff0c;那么称它是一个 好 子数组。 子数组 是原数组中一段…