1 // *******************************************************************************************************
\r
3 // ** M24LC02B.v - 24LC02B 2K-BIT I2C SERIAL EEPROM (VCC = +2.5V TO +5.5V) **
\r
5 // *******************************************************************************************************
\r
7 // ** COPYRIGHT (c) 2003 YOUNG ENGINEERING **
\r
8 // ** ALL RIGHTS RESERVED **
\r
10 // ** THIS PROGRAM IS CONFIDENTIAL AND A TRADE SECRET OF YOUNG ENGINEERING. THE RECEIPT OR **
\r
11 // ** POSSESSION OF THIS PROGRAM DOES NOT CONVEY ANY RIGHTS TO REPRODUCE OR DISCLOSE ITS **
\r
12 // ** CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN **
\r
13 // ** PART, WITHOUT THE SPECIFIC WRITTEN CONSENT OF YOUNG ENGINEERING. **
\r
15 // *******************************************************************************************************
\r
16 // ** Revision : 1.1 **
\r
17 // ** Modified Date : 07/19/2004 **
\r
18 // ** Revision History: **
\r
20 // ** 02/01/2003: Initial design **
\r
21 // ** 07/19/2004: Fixed the timing checks and the open-drain modeling for SDA. **
\r
23 // *******************************************************************************************************
\r
24 // ** TABLE OF CONTENTS **
\r
25 // *******************************************************************************************************
\r
26 // **---------------------------------------------------------------------------------------------------**
\r
27 // ** DECLARATIONS **
\r
28 // **---------------------------------------------------------------------------------------------------**
\r
29 // **---------------------------------------------------------------------------------------------------**
\r
30 // ** INITIALIZATION **
\r
31 // **---------------------------------------------------------------------------------------------------**
\r
32 // **---------------------------------------------------------------------------------------------------**
\r
34 // **---------------------------------------------------------------------------------------------------**
\r
35 // ** 1.01: START Bit Detection **
\r
36 // ** 1.02: STOP Bit Detection **
\r
37 // ** 1.03: Input Shift Register **
\r
38 // ** 1.04: Input Bit Counter **
\r
39 // ** 1.05: Control Byte Register **
\r
40 // ** 1.06: Byte Address Register **
\r
41 // ** 1.07: Write Data Buffer **
\r
42 // ** 1.08: Acknowledge Generator **
\r
43 // ** 1.09: Acknowledge Detect **
\r
44 // ** 1.10: Write Cycle Timer **
\r
45 // ** 1.11: Write Cycle Processor **
\r
46 // ** 1.12: Read Data Multiplexor **
\r
47 // ** 1.13: Read Data Processor **
\r
48 // ** 1.14: SDA Data I/O Buffer **
\r
50 // **---------------------------------------------------------------------------------------------------**
\r
51 // ** DEBUG LOGIC **
\r
52 // **---------------------------------------------------------------------------------------------------**
\r
53 // ** 2.01: Memory Data Bytes **
\r
54 // ** 2.02: Write Data Buffer **
\r
56 // **---------------------------------------------------------------------------------------------------**
\r
57 // ** TIMING CHECKS **
\r
58 // **---------------------------------------------------------------------------------------------------**
\r
60 // *******************************************************************************************************
\r
65 module M24LC02B (A0, A1, A2, WP, SDA, SCL, RESET);
\r
67 input A0; // unconnected pin
\r
68 input A1; // unconnected pin
\r
69 input A2; // unconnected pin
\r
71 input WP; // write protect pin
\r
73 inout SDA; // serial data I/O
\r
74 input SCL; // serial data clock
\r
76 input RESET; // system reset
\r
79 // *******************************************************************************************************
\r
80 // ** DECLARATIONS **
\r
81 // *******************************************************************************************************
\r
83 reg SDA_DO; // serial data - output
\r
84 reg SDA_OE; // serial data - output enable
\r
86 wire SDA_DriveEnable; // serial data output enable
\r
87 reg SDA_DriveEnableDlyd; // serial data output enable - delayed
\r
89 reg [03:00] BitCounter; // serial bit counter
\r
91 reg START_Rcvd; // START bit received flag
\r
92 reg STOP_Rcvd; // STOP bit received flag
\r
93 reg CTRL_Rcvd; // control byte received flag
\r
94 reg ADDR_Rcvd; // byte address received flag
\r
95 reg MACK_Rcvd; // master acknowledge received flag
\r
97 reg WrCycle; // memory write cycle
\r
98 reg RdCycle; // memory read cycle
\r
100 reg [07:00] ShiftRegister; // input data shift register
\r
102 reg [07:00] ControlByte; // control byte register
\r
103 wire RdWrBit; // read/write control bit
\r
105 reg [07:00] StartAddress; // memory access starting address
\r
106 reg [02:00] PageAddress; // memory page address
\r
108 reg [07:00] WrDataByte [0:7]; // memory write data buffer
\r
109 wire [07:00] RdDataByte; // memory read data
\r
111 reg [15:00] WrCounter; // write buffer counter
\r
113 reg [02:00] WrPointer; // write buffer pointer
\r
114 reg [07:00] RdPointer; // read address pointer
\r
116 reg WriteActive; // memory write cycle active
\r
118 reg [07:00] MemoryBlock [0:255]; // EEPROM data memory array
\r
120 integer LoopIndex; // iterative loop index
\r
122 integer tAA; // timing parameter
\r
123 integer tWC; // timing parameter
\r
126 // *******************************************************************************************************
\r
127 // ** INITIALIZATION **
\r
128 // *******************************************************************************************************
\r
130 initial tAA = 900; // SCL to SDA output delay
\r
131 initial tWC = 5000000; // memory write cycle time
\r
159 // *******************************************************************************************************
\r
160 // ** CORE LOGIC **
\r
161 // *******************************************************************************************************
\r
162 // -------------------------------------------------------------------------------------------------------
\r
163 // 1.01: START Bit Detection
\r
164 // -------------------------------------------------------------------------------------------------------
\r
166 always @(negedge SDA) begin
\r
167 if (SCL == 1) begin
\r
181 // -------------------------------------------------------------------------------------------------------
\r
182 // 1.02: STOP Bit Detection
\r
183 // -------------------------------------------------------------------------------------------------------
\r
185 always @(posedge SDA) begin
\r
186 if (SCL == 1) begin
\r
200 // -------------------------------------------------------------------------------------------------------
\r
201 // 1.03: Input Shift Register
\r
202 // -------------------------------------------------------------------------------------------------------
\r
204 always @(posedge SCL) begin
\r
205 ShiftRegister[00] <= SDA;
\r
206 ShiftRegister[01] <= ShiftRegister[00];
\r
207 ShiftRegister[02] <= ShiftRegister[01];
\r
208 ShiftRegister[03] <= ShiftRegister[02];
\r
209 ShiftRegister[04] <= ShiftRegister[03];
\r
210 ShiftRegister[05] <= ShiftRegister[04];
\r
211 ShiftRegister[06] <= ShiftRegister[05];
\r
212 ShiftRegister[07] <= ShiftRegister[06];
\r
215 // -------------------------------------------------------------------------------------------------------
\r
216 // 1.04: Input Bit Counter
\r
217 // -------------------------------------------------------------------------------------------------------
\r
219 always @(posedge SCL) begin
\r
220 if (BitCounter < 10) BitCounter <= BitCounter + 1;
\r
223 // -------------------------------------------------------------------------------------------------------
\r
224 // 1.05: Control Byte Register
\r
225 // -------------------------------------------------------------------------------------------------------
\r
227 always @(negedge SCL) begin
\r
228 if (START_Rcvd & (BitCounter == 8)) begin
\r
229 if (!WriteActive & (ShiftRegister[07:04] == 4'b1010)) begin
\r
230 if (ShiftRegister[00] == 0) WrCycle <= 1;
\r
231 if (ShiftRegister[00] == 1) RdCycle <= 1;
\r
233 ControlByte <= ShiftRegister[07:00];
\r
242 assign RdWrBit = ControlByte[00];
\r
244 // -------------------------------------------------------------------------------------------------------
\r
245 // 1.06: Byte Address Register
\r
246 // -------------------------------------------------------------------------------------------------------
\r
248 always @(negedge SCL) begin
\r
249 if (CTRL_Rcvd & (BitCounter == 8)) begin
\r
250 if (RdWrBit == 0) begin
\r
251 StartAddress <= ShiftRegister[07:00];
\r
252 RdPointer <= ShiftRegister[07:00];
\r
264 // -------------------------------------------------------------------------------------------------------
\r
265 // 1.07: Write Data Buffer
\r
266 // -------------------------------------------------------------------------------------------------------
\r
268 always @(negedge SCL) begin
\r
269 if (ADDR_Rcvd & (BitCounter == 8)) begin
\r
270 if ((WP == 0) & (RdWrBit == 0)) begin
\r
271 WrDataByte[WrPointer] <= ShiftRegister[07:00];
\r
273 WrCounter <= WrCounter + 1;
\r
274 WrPointer <= WrPointer + 1;
\r
279 // -------------------------------------------------------------------------------------------------------
\r
280 // 1.08: Acknowledge Generator
\r
281 // -------------------------------------------------------------------------------------------------------
\r
283 always @(negedge SCL) begin
\r
284 if (!WriteActive) begin
\r
285 if (BitCounter == 8) begin
\r
286 if (WrCycle | (START_Rcvd & (ShiftRegister[07:04] == 4'b1010))) begin
\r
291 if (BitCounter == 9) begin
\r
294 if (!RdCycle) begin
\r
302 // -------------------------------------------------------------------------------------------------------
\r
303 // 1.09: Acknowledge Detect
\r
304 // -------------------------------------------------------------------------------------------------------
\r
306 always @(posedge SCL) begin
\r
307 if (RdCycle & (BitCounter == 8)) begin
\r
308 if ((SDA == 0) & (SDA_OE == 0)) MACK_Rcvd <= 1;
\r
312 always @(negedge SCL) MACK_Rcvd <= 0;
\r
314 // -------------------------------------------------------------------------------------------------------
\r
315 // 1.10: Write Cycle Timer
\r
316 // -------------------------------------------------------------------------------------------------------
\r
318 always @(posedge STOP_Rcvd) begin
\r
319 if (WrCycle & (WP == 0) & (WrCounter > 0)) begin
\r
326 always @(posedge STOP_Rcvd) begin
\r
331 // -------------------------------------------------------------------------------------------------------
\r
332 // 1.11: Write Cycle Processor
\r
333 // -------------------------------------------------------------------------------------------------------
\r
335 always @(posedge WriteActive) begin
\r
336 for (LoopIndex = 0; LoopIndex < WrCounter; LoopIndex = LoopIndex + 1) begin
\r
337 PageAddress = StartAddress[02:00] + LoopIndex;
\r
339 MemoryBlock[{StartAddress[07:03],PageAddress[02:00]}] = WrDataByte[LoopIndex[02:00]];
\r
343 // -------------------------------------------------------------------------------------------------------
\r
344 // 1.12: Read Data Multiplexor
\r
345 // -------------------------------------------------------------------------------------------------------
\r
347 always @(negedge SCL) begin
\r
348 if (BitCounter == 8) begin
\r
349 if (WrCycle & ADDR_Rcvd) begin
\r
350 RdPointer <= StartAddress + WrPointer + 1;
\r
353 RdPointer <= RdPointer + 1;
\r
358 assign RdDataByte = MemoryBlock[RdPointer[07:00]];
\r
360 // -------------------------------------------------------------------------------------------------------
\r
361 // 1.13: Read Data Processor
\r
362 // -------------------------------------------------------------------------------------------------------
\r
364 always @(negedge SCL) begin
\r
366 if (BitCounter == 8) begin
\r
370 else if (BitCounter == 9) begin
\r
371 SDA_DO <= RdDataByte[07];
\r
373 if (MACK_Rcvd) SDA_OE <= 1;
\r
376 SDA_DO <= RdDataByte[7-BitCounter];
\r
381 // -------------------------------------------------------------------------------------------------------
\r
382 // 1.14: SDA Data I/O Buffer
\r
383 // -------------------------------------------------------------------------------------------------------
\r
385 bufif1 (SDA, 1'b0, SDA_DriveEnableDlyd);
\r
387 assign SDA_DriveEnable = !SDA_DO & SDA_OE;
\r
388 always @(SDA_DriveEnable) SDA_DriveEnableDlyd <= #(tAA) SDA_DriveEnable;
\r
391 // *******************************************************************************************************
\r
392 // ** DEBUG LOGIC **
\r
393 // *******************************************************************************************************
\r
394 // -------------------------------------------------------------------------------------------------------
\r
395 // 2.01: Memory Data Bytes
\r
396 // -------------------------------------------------------------------------------------------------------
\r
398 wire [07:00] MemoryByte00 = MemoryBlock[00];
\r
399 wire [07:00] MemoryByte01 = MemoryBlock[01];
\r
400 wire [07:00] MemoryByte02 = MemoryBlock[02];
\r
401 wire [07:00] MemoryByte03 = MemoryBlock[03];
\r
402 wire [07:00] MemoryByte04 = MemoryBlock[04];
\r
403 wire [07:00] MemoryByte05 = MemoryBlock[05];
\r
404 wire [07:00] MemoryByte06 = MemoryBlock[06];
\r
405 wire [07:00] MemoryByte07 = MemoryBlock[07];
\r
407 wire [07:00] MemoryByte08 = MemoryBlock[08];
\r
408 wire [07:00] MemoryByte09 = MemoryBlock[09];
\r
409 wire [07:00] MemoryByte0A = MemoryBlock[10];
\r
410 wire [07:00] MemoryByte0B = MemoryBlock[11];
\r
411 wire [07:00] MemoryByte0C = MemoryBlock[12];
\r
412 wire [07:00] MemoryByte0D = MemoryBlock[13];
\r
413 wire [07:00] MemoryByte0E = MemoryBlock[14];
\r
414 wire [07:00] MemoryByte0F = MemoryBlock[15];
\r
416 // -------------------------------------------------------------------------------------------------------
\r
417 // 2.02: Write Data Buffer
\r
418 // -------------------------------------------------------------------------------------------------------
\r
420 wire [07:00] WriteData_0 = WrDataByte[00];
\r
421 wire [07:00] WriteData_1 = WrDataByte[01];
\r
422 wire [07:00] WriteData_2 = WrDataByte[02];
\r
423 wire [07:00] WriteData_3 = WrDataByte[03];
\r
424 wire [07:00] WriteData_4 = WrDataByte[04];
\r
425 wire [07:00] WriteData_5 = WrDataByte[05];
\r
426 wire [07:00] WriteData_6 = WrDataByte[06];
\r
427 wire [07:00] WriteData_7 = WrDataByte[07];
\r
430 // *******************************************************************************************************
\r
431 // ** TIMING CHECKS **
\r
432 // *******************************************************************************************************
\r
434 wire TimingCheckEnable = (RESET == 0) & (SDA_OE == 0);
\r
438 tHI = 600, // SCL pulse width - high
\r
439 tLO = 1300, // SCL pulse width - low
\r
440 tSU_STA = 600, // SCL to SDA setup time
\r
441 tHD_STA = 600, // SCL to SDA hold time
\r
442 tSU_DAT = 100, // SDA to SCL setup time
\r
443 tSU_STO = 600; // SCL to SDA setup time
\r
445 $width (posedge SCL, tHI);
\r
446 $width (negedge SCL, tLO);
\r
448 $setup (SCL, negedge SDA &&& TimingCheckEnable, tSU_STA);
\r
449 $setup (SDA, posedge SCL &&& TimingCheckEnable, tSU_DAT);
\r
450 $setup (SCL, posedge SDA &&& TimingCheckEnable, tSU_STO);
\r
452 $hold (negedge SDA &&& TimingCheckEnable, SCL, tHD_STA);
\r