Files
UHD-Fairwaves/fpga/models/M24LC024B.v
2014-04-07 17:34:55 -07:00

477 lines
19 KiB
Verilog

//
// Copyright 2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Modified 11/14/07 to simulate the 24lc024, which responds to the address pins
// *******************************************************************************************************
// ** **
// ** M24LC024B.v - 24LC02B 2K-BIT I2C SERIAL EEPROM (VCC = +2.5V TO +5.5V) **
// ** **
// *******************************************************************************************************
// ** **
// ** COPYRIGHT (c) 2003 YOUNG ENGINEERING **
// ** ALL RIGHTS RESERVED **
// ** **
// ** THIS PROGRAM IS CONFIDENTIAL AND A TRADE SECRET OF YOUNG ENGINEERING. THE RECEIPT OR **
// ** POSSESSION OF THIS PROGRAM DOES NOT CONVEY ANY RIGHTS TO REPRODUCE OR DISCLOSE ITS **
// ** CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN **
// ** PART, WITHOUT THE SPECIFIC WRITTEN CONSENT OF YOUNG ENGINEERING. **
// ** **
// *******************************************************************************************************
// ** Revision : 1.1 **
// ** Modified Date : 07/19/2004 **
// ** Revision History: **
// ** **
// ** 02/01/2003: Initial design **
// ** 07/19/2004: Fixed the timing checks and the open-drain modeling for SDA. **
// ** **
// *******************************************************************************************************
// ** 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/10ps
module M24LC024B (A0, A1, A2, WP, SDA, SCL, RESET);
input A0; // unconnected pin
input A1; // unconnected pin
input A2; // unconnected pin
input WP; // write protect pin
inout SDA; // serial data I/O
input SCL; // serial data clock
input RESET; // system reset
// *******************************************************************************************************
// ** DECLARATIONS **
// *******************************************************************************************************
reg SDA_DO; // serial data - output
reg SDA_OE; // serial data - output enable
wire SDA_DriveEnable; // serial data output enable
reg SDA_DriveEnableDlyd; // serial data output enable - delayed
reg [03:00] BitCounter; // serial bit counter
reg START_Rcvd; // START bit received flag
reg STOP_Rcvd; // STOP bit received flag
reg CTRL_Rcvd; // control byte received flag
reg ADDR_Rcvd; // byte address received flag
reg MACK_Rcvd; // master acknowledge received flag
reg WrCycle; // memory write cycle
reg RdCycle; // memory read cycle
reg [07:00] ShiftRegister; // input data shift register
reg [07:00] ControlByte; // control byte register
wire RdWrBit; // read/write control bit
reg [07:00] StartAddress; // memory access starting address
reg [02:00] PageAddress; // memory page address
reg [07:00] WrDataByte [0:7]; // memory write data buffer
wire [07:00] RdDataByte; // memory read data
reg [15:00] WrCounter; // write buffer counter
reg [02:00] WrPointer; // write buffer pointer
reg [07:00] RdPointer; // read address pointer
reg WriteActive; // memory write cycle active
reg [07:00] MemoryBlock [0:255]; // EEPROM data memory array
integer LoopIndex; // iterative loop index
integer tAA; // timing parameter
integer tWC; // timing parameter
// *******************************************************************************************************
// ** INITIALIZATION **
// *******************************************************************************************************
initial tAA = 900; // SCL to SDA output delay
initial tWC = 5000000; // memory write cycle time
//initial tWC = 50000; // shortened memory write cycle time to speed up sims
initial begin
SDA_DO = 0;
SDA_OE = 0;
end
initial begin
START_Rcvd = 0;
STOP_Rcvd = 0;
CTRL_Rcvd = 0;
ADDR_Rcvd = 0;
MACK_Rcvd = 0;
end
initial begin
BitCounter = 0;
ControlByte = 0;
end
initial begin
WrCycle = 0;
RdCycle = 0;
WriteActive = 0;
end
// *******************************************************************************************************
// ** CORE LOGIC **
// *******************************************************************************************************
// -------------------------------------------------------------------------------------------------------
// 1.01: START Bit Detection
// -------------------------------------------------------------------------------------------------------
always @(negedge SDA) begin
if (SCL == 1) begin
START_Rcvd <= 1;
STOP_Rcvd <= 0;
CTRL_Rcvd <= 0;
ADDR_Rcvd <= 0;
MACK_Rcvd <= 0;
WrCycle <= #1 0;
RdCycle <= #1 0;
BitCounter <= 0;
end
end
// -------------------------------------------------------------------------------------------------------
// 1.02: STOP Bit Detection
// -------------------------------------------------------------------------------------------------------
always @(posedge SDA) begin
if (SCL == 1) begin
START_Rcvd <= 0;
STOP_Rcvd <= 1;
CTRL_Rcvd <= 0;
ADDR_Rcvd <= 0;
MACK_Rcvd <= 0;
WrCycle <= #1 0;
RdCycle <= #1 0;
BitCounter <= 10;
end
end
// -------------------------------------------------------------------------------------------------------
// 1.03: Input Shift Register
// -------------------------------------------------------------------------------------------------------
always @(posedge SCL) begin
ShiftRegister[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) begin
if (BitCounter < 10) BitCounter <= BitCounter + 1;
end
// -------------------------------------------------------------------------------------------------------
// 1.05: Control Byte Register
// -------------------------------------------------------------------------------------------------------
always @(negedge SCL) begin
if (START_Rcvd & (BitCounter == 8)) begin
if (!WriteActive & (ShiftRegister[07:04] == 4'b1010)
& (ShiftRegister[3:1] == {A2,A1,A0})) begin
if (ShiftRegister[00] == 0) WrCycle <= 1;
if (ShiftRegister[00] == 1) RdCycle <= 1;
ControlByte <= ShiftRegister[07:00];
CTRL_Rcvd <= 1;
end
START_Rcvd <= 0;
end
end
assign RdWrBit = ControlByte[00];
// -------------------------------------------------------------------------------------------------------
// 1.06: Byte Address Register
// -------------------------------------------------------------------------------------------------------
always @(negedge SCL) begin
if (CTRL_Rcvd & (BitCounter == 8)) begin
if (RdWrBit == 0) begin
StartAddress <= ShiftRegister[07:00];
RdPointer <= ShiftRegister[07:00];
ADDR_Rcvd <= 1;
end
WrCounter <= 0;
WrPointer <= 0;
CTRL_Rcvd <= 0;
end
end
// -------------------------------------------------------------------------------------------------------
// 1.07: Write Data Buffer
// -------------------------------------------------------------------------------------------------------
always @(negedge SCL) begin
if (ADDR_Rcvd & (BitCounter == 8)) begin
if ((WP == 0) & (RdWrBit == 0)) begin
WrDataByte[WrPointer] <= ShiftRegister[07:00];
WrCounter <= WrCounter + 1;
WrPointer <= WrPointer + 1;
end
end
end
// -------------------------------------------------------------------------------------------------------
// 1.08: Acknowledge Generator
// -------------------------------------------------------------------------------------------------------
always @(negedge SCL) begin
if (!WriteActive) begin
if (BitCounter == 8) begin
if (WrCycle | (START_Rcvd & (ShiftRegister[07:04] == 4'b1010))) begin
SDA_DO <= 0;
SDA_OE <= 1;
end
end
if (BitCounter == 9) begin
BitCounter <= 0;
if (!RdCycle) begin
SDA_DO <= 0;
SDA_OE <= 0;
end
end
end
end
// -------------------------------------------------------------------------------------------------------
// 1.09: Acknowledge Detect
// -------------------------------------------------------------------------------------------------------
always @(posedge SCL) begin
if (RdCycle & (BitCounter == 8)) begin
if ((SDA == 0) & (SDA_OE == 0)) MACK_Rcvd <= 1;
end
end
always @(negedge SCL) MACK_Rcvd <= 0;
// -------------------------------------------------------------------------------------------------------
// 1.10: Write Cycle Timer
// -------------------------------------------------------------------------------------------------------
always @(posedge STOP_Rcvd) begin
if (WrCycle & (WP == 0) & (WrCounter > 0)) begin
WriteActive = 1;
#(tWC);
WriteActive = 0;
end
end
always @(posedge STOP_Rcvd) begin
#(1.0);
STOP_Rcvd = 0;
end
// -------------------------------------------------------------------------------------------------------
// 1.11: Write Cycle Processor
// -------------------------------------------------------------------------------------------------------
always @(posedge WriteActive) begin
for (LoopIndex = 0; LoopIndex < WrCounter; LoopIndex = LoopIndex + 1) begin
PageAddress = StartAddress[02:00] + LoopIndex;
MemoryBlock[{StartAddress[07:03],PageAddress[02:00]}] = WrDataByte[LoopIndex[02:00]];
end
end
// -------------------------------------------------------------------------------------------------------
// 1.12: Read Data Multiplexor
// -------------------------------------------------------------------------------------------------------
always @(negedge SCL) begin
if (BitCounter == 8) begin
if (WrCycle & ADDR_Rcvd) begin
RdPointer <= StartAddress + WrPointer + 1;
end
if (RdCycle) begin
RdPointer <= RdPointer + 1;
end
end
end
assign RdDataByte = MemoryBlock[RdPointer[07:00]];
// -------------------------------------------------------------------------------------------------------
// 1.13: Read Data Processor
// -------------------------------------------------------------------------------------------------------
always @(negedge SCL) begin
if (RdCycle) begin
if (BitCounter == 8) begin
SDA_DO <= 0;
SDA_OE <= 0;
end
else if (BitCounter == 9) begin
SDA_DO <= RdDataByte[07];
if (MACK_Rcvd) SDA_OE <= 1;
end
else begin
SDA_DO <= RdDataByte[7-BitCounter];
end
end
end
// -------------------------------------------------------------------------------------------------------
// 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] MemoryByte00 = MemoryBlock[00];
wire [07:00] MemoryByte01 = MemoryBlock[01];
wire [07:00] MemoryByte02 = MemoryBlock[02];
wire [07:00] MemoryByte03 = MemoryBlock[03];
wire [07:00] MemoryByte04 = MemoryBlock[04];
wire [07:00] MemoryByte05 = MemoryBlock[05];
wire [07:00] MemoryByte06 = MemoryBlock[06];
wire [07:00] MemoryByte07 = MemoryBlock[07];
wire [07:00] MemoryByte08 = MemoryBlock[08];
wire [07:00] MemoryByte09 = MemoryBlock[09];
wire [07:00] MemoryByte0A = MemoryBlock[10];
wire [07:00] MemoryByte0B = MemoryBlock[11];
wire [07:00] MemoryByte0C = MemoryBlock[12];
wire [07:00] MemoryByte0D = MemoryBlock[13];
wire [07:00] MemoryByte0E = MemoryBlock[14];
wire [07:00] MemoryByte0F = MemoryBlock[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];
// *******************************************************************************************************
// ** TIMING CHECKS **
// *******************************************************************************************************
wire TimingCheckEnable = (RESET == 0) & (SDA_OE == 0);
specify
specparam
tHI = 600, // SCL pulse width - high
tLO = 1300, // SCL pulse width - low
tSU_STA = 600, // SCL to SDA setup time
tHD_STA = 600, // SCL to SDA hold time
tSU_DAT = 100, // SDA to SCL setup time
tSU_STO = 600; // SCL to SDA setup time
$width (posedge SCL, tHI);
$width (negedge SCL, tLO);
$setup (SCL, negedge SDA &&& TimingCheckEnable, tSU_STA);
$setup (SDA, posedge SCL &&& TimingCheckEnable, tSU_DAT);
$setup (SCL, posedge SDA &&& TimingCheckEnable, tSU_STO);
$hold (negedge SDA &&& TimingCheckEnable, SCL, tHD_STA);
endspecify
endmodule