OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/orpsocv2/bench/verilog
    from Rev 495 to Rev 655
    Reverse comparison

Rev 495 → Rev 655

/include/cfi_flash_def.h
0,0 → 1,49
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
// *****************************************
// Glogal Definition for Device : M58WR128F
// *****************************************
 
// TimeScale Directive
`timescale 1 ns / 1 ns
 
`define HIGH 1'b1
`define LOW 1'b0
`define Z 1'bZ
`define X 1'bX
`define FALSE 1'b0
`define TRUE 1'b1
`define UNLOCK 1'b0 // Unlocked Block Lock Status
`define LOCK 1'b1 // Locked Block Lock Status
`define UNLOCKDOWN 1'b0 // UnLocked-down Status
`define LOCKDOWN 1'b1 // Locked-down Status
`define BUSY 1'b0
`define READY 1'b1
`define BYTE_range 7:0
`define WORD_range 15:0
`define LOW_range 7:0
`define HIGH_range 15:8
`define WORDNP 16'hFFFF // Memory not programmed
`define Kbyte 1024
`define Kword 1024
`define INTEGER 15:0
 
/include/cfi_flash_TimingData.h
0,0 → 1,314
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
`include "cfi_flash_data.h"
`include "cfi_flash_UserData.h"
 
`define Reset_time 300000
 
// *********************************************
//
// Table 29
// Program/Erase Characteristics
//
// *********************************************
 
// Vpp = VppL
 
/*
// Too long!
`define ParameterBlockErase_time 800000000// 0.8 sec
`define MainBlockErase_time 800000000
*/
 
/* erase times much reduced for simulation - Julius */
`define ParameterBlockErase_time 8000// 800ns sec
`define MainBlockErase_time 8000
 
/*
`define WordProgram_time 150000 // 150 us
`define ParameterBlockProgram_time 272000 // 32000 us = 32 ms???????verificare
`define MainBlockProgram_time 700000 // 256000 us = 256 ms???????verificare
*/
 
`define WordProgram_time 1500 // 150 us
`define ParameterBlockProgram_time 2720 // 32000 us = 32 ms???????verificare
`define MainBlockProgram_time 7000 // 256000 us = 256 ms???????verificare
 
`define ProgramSuspendLatency_time 20000 // 20 us
`define EraseSuspendLatency_time 20000 // 20 us
`define MainBlankCheck_time 3200000
// Vpp = VppH
 
`define FastParameterBlockErase_time 800000000 // 0.8 sec
`define FastMainBlockErase_time 800000000 // 0.8 sec
`define FastWordProgram_time 150000 // 8 us
`define FastParameterBlockProgram_time 272000 // 32 ms
`define FastMainBlockProgram_time 700000 // 256000 us = 256 ms
 
`define BlockProtect_time 1800
`define BlockUnProtect_time 5000000
 
`define ProgramBuffer_time 700000
 
 
`define EnhBuffProgram_time 512000 //
`define EnhBuffProgramSetupPhase_time 5000
 
 
 
// **********************
//
// Timing Data Module :
// set timing values
//
// **********************
 
module TimingDataModule;
 
// ************************************
//
// AC Read Specifications
//
// Table 27
//
// ************************************
 
integer tAVAV; // Address Valid to Next Address Valid
integer tAVQV; // Address Valid to Output Valid (Random)
integer tAVQV1; // Address Valid to Output Valid (Page)
integer tELTV; // Chip Enable Low to Wait Valid
integer tELQV; // Chip Enable Low to Output Valid
integer tELQX; // Chip Enable Low to Output Transition
integer tEHTZ; // Chip Enable High to Wait Hi-Z
integer tEHQX;//tOH // Chip Enable High to Output Transition
integer tEHQZ; // Chip Enable High to Output Hi-Z
integer tGLQV; // Output Enable Low to Output Valid
integer tGLQX; // Output Enable Low to Output Transition
integer tGHQZ; // Output Enable High to Output Hi-Z
integer tAVLH;//tAVVH // Address Valid to (ADV#) Latch Enable High
integer tELLH; //tELVH // Chip Enable Low to Latch Enable High
integer tLHAX; //tVHAX // Latch Enable High to Address Transition
integer tLLLH; //tVLVH // Latch Enable Low to Latch Enable High
integer tLLQV; //tVLQV // Latch Enable Low to Output Valid
 
integer tGLTV; //// Output Enable Low to Wait Valid
integer tGLTX; //// Output Enable Low to Wait Transition
integer tGHTZ; //// Output Enable high to Wait Hi-Z
 
 
 
 
 
integer tAVKH; //tAVCH/L // Address Valid to Clock High
integer tELKH; //tELCH // Chip Enable Low to Clock High
integer tEHEL;// tEHEL // Chip Enable High to Chip Enable Low (reading)
integer tKHAX;//tCHAX // Clock High to Address Transition
integer tKHQV; //tCHQV // Clock High to Output Enable Valid
integer tKHTV; //tCHTV // Clock High to Wait Valid
integer tKHQX; //tCHQX // Clock High to Output Enable Transition
integer tKHTX; //tCHTX // Clock High to Wait Transition
integer tLLKH; //tVLCH/L // Latch Enable Low to Clock High
integer tLLKL; //tVLCH/L // Latch Enable Low to Clock High
integer tKHLL; //tCHVL //Clock valid to ADV# setup
integer tKHKH; //tCLK // Clock Period
integer tKHKL; //tCH/CL // Clock High to Clock Low
integer tKLKH; // Clock Low to Clock High
integer tCK_fall; //R203 // Clock Fall Time
integer tCK_rise; // Clock Rise Time
 
 
// *************************************************
//
// AC Write Specifications
//
// Table 28
//
// *************************************************
 
integer tAVWH; // Address Valid to Write Enable High
integer tDVWH; // Data Valid to Write Enable High
integer tELWL; // Chip Enable Low to Write Enable Low
integer tWHAV; //W18 // Write Enable High to Address Valid
integer tWHAX; // Write Enable High to Address Transition
integer tWHDX; // Write Enable High to Data Transition
integer tWHEH; // Write Enable High to Chip Enable High
integer tWHGL; // Write Enable High to Output Enable High
integer tWHLL; //W28 tWHVL // Write Enable High to Latch Enable Low
integer tWHWL; // Write Enable High to Latch Enable Low
integer tWHQV; // Write Enable High to Output Enable Valid
integer tWLWH; // Write Enable Low to Write Enable High
integer tQVVPL; //tQVVL // Output (Status Register) Valid to Vpp Low
integer tQVWPL; //tQVBL // Output (Status Register) Valid to Write Protect Low
integer tVPHWH; // Vpp High to Write Enable High
integer tWPHWH; //tBHWH // Write Protect High to Write Enable High
 
 
integer tELEH; // Chip Enable Low to Chip Enable High
 
 
//!// *************************************
//!//
//!// Power and Reset
//!//
//!// Table 20
//!//
//!// **************************************
 
integer tPHWL; //W1 // Reset High to Write Enable Low
integer tPLPH;//P1 // Reset High to Reset Low
 
integer tVDHPH; //tVCCPH // Supply voltages High to Reset High
 
 
 
initial begin
 
setTiming(`t_access);
end
 
// **********************
//
// FUNCTION getTime :
// return time value
//
// **********************
 
function getTime;
 
input [8*31 : 0] time_str;
 
begin
 
 
end
endfunction
 
// **********************
//
// Task setTiming :
// set timing values
//
// **********************
 
task setTiming;
 
input time_access;
 
integer time_access;
 
begin
 
// ***********************************************
//
// AC Read Specifications
//
// Table 27
//
// ***********************************************
 
tELQX = 0;
tEHQX = 0;
tGLQX = 0;
tGHQZ = 15;
tELLH = 10;
 
tAVAV = time_access;
tAVQV = time_access;
tELQV = time_access;
tLLQV = time_access;
tEHTZ = 20;
tAVQV1 = 25;
tELTV = 17;
tEHEL = 17;
tCK_fall = 3;
tCK_rise = 3;
tEHQZ = 20;
tGLQV = 25;
tAVLH = 10;
tLHAX = 9;
tLLLH = 10;
 
tAVKH = 9;
tELKH = 9;
tKHAX = 10;
tKHQV = 17;
tKHTV = 17;
tKHQX = 3;
tKHTX = 3;
tLLKH = 9;
tLLKL = 9;
tKHLL = 3;
tKHKH = 19.2;
tKHKL = 5;
tKLKH = 5;
tGLTV = 17;
tGLTX = 0;
tGHTZ = 20;
 
// *************************************************
//
// AC Write Specifications
//
// Table 28
//
// *************************************************
 
tELWL = 0;
tWHAV = 0;
tWHAX = 0;
tWHDX = 0;
tWHEH = 0;
tWHGL = 0;
tWHLL = 7;
tQVVPL = 0;
tQVWPL = 0;
tVPHWH = 200;
tWPHWH = 200;
tAVWH = 50;
tDVWH = 50;
tWHWL = 20;
tWHQV = tAVQV + 35; //tAVQV+35
tWLWH = 50;
tELEH = 50;
// *************************************
//
// Power and Reset
//
// Table 20
//
// **************************************
 
tPHWL = 150;
tPLPH = 100;
tVDHPH = 300;
 
 
end
endtask
 
endmodule
 
/include/cfi_flash_BankLib.h
0,0 → 1,280
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
 
// ****************************************************
//
// Block Library :
//
// define the architecture of the blocks and banks
//
// ****************************************************
 
`include "cfi_flash_def.h"
`include "cfi_flash_data.h"
`include "cfi_flash_UserData.h"
 
`define BLOCK_dim 259
`define BLOCKDIM_range 0 : `BLOCK_dim - 1
`define BLOCKADDR_dim 16
`define BLOCKADDR_range `BLOCKADDR_dim - 1 : 0
 
// *********
//
// Parameter Block & Main Block
 
//
// *********
 
`define ParameterBlock_num 4
`define ParameterBlock_size 16 // Size of Parameter Block (Kword)
`define MainBlock_num 255
`define MainBlock_size 64 // Size of Main Block (Kword)
 
 
 
module BankLib;
 
integer BlockBoundaryStartAddr [`BLOCK_dim - 1 : 0]; // Block Boundary Start Address
integer BlockBoundaryEndAddr [`BLOCK_dim - 1 : 0]; // Block Boundary End Address
integer count;
 
initial
begin
 
begin: block_building
for (count = 0; count <= `BLOCK_dim - 1; count = count + 1)
BuildBlockBoundary(`organization, count, BlockBoundaryStartAddr[count], BlockBoundaryEndAddr[count]);
 
end
 
end
 
// ******************************************************************
//
// TASK BuildBlockBoundary: Build the Blocks Boundaries in two arrays
//
// ******************************************************************
 
task BuildBlockBoundary;
input organize;
input n_block;
output StartAddr;
output EndAddr;
 
reg [8*6:1] organize;
integer n_block;
integer StartAddr;
integer EndAddr;
 
begin
if (organize == "top") begin
if (n_block == 0) EndAddr = - 1;
if (n_block > `MainBlock_num - 1 && n_block <= `MainBlock_num + `ParameterBlock_num - 1) // parameter block
begin
StartAddr = EndAddr + 1;
EndAddr = StartAddr + `ParameterBlock_size * `Kword - 1;
end
else // Main block
begin
StartAddr = EndAddr + 1;
EndAddr = StartAddr + `MainBlock_size * `Kword - 1;
end
 
end else begin // organize = "bottom"
if (n_block == 0) EndAddr = - 1;
if (n_block > `ParameterBlock_num - 1)
begin
StartAddr = (`ParameterBlock_num * `ParameterBlock_size * `Kword ) +
(n_block - `ParameterBlock_num) * `MainBlock_size * `Kword;
EndAddr = StartAddr + `MainBlock_size * `Kword - 1;
end
//!
else // parameter block
begin
StartAddr = EndAddr + 1;
EndAddr = StartAddr + `ParameterBlock_size * `Kword - 1;
end
 
end
//!$display("n_block=%d, StartAddr =%h, EndAddr =%h", n_block, StartAddr , EndAddr);
end
endtask
 
 
 
// *********************************************
// FUNCTION getBlock : return block from address
//
// *********************************************
 
function [`INTEGER] getBlock; // BLOCK_dim in binary is 9 bit size
 
input address;
 
reg [`ADDRBUS_dim - 1 : 0] address;
reg found;
integer count;
 
begin
// $display ("function getBlock got address %h", address);
count = 0;
found = 0;
while ((count <= `BLOCK_dim) && (! found))
begin
 
if ((BlockBoundaryStartAddr[count] <= address) && (address <= BlockBoundaryEndAddr[count])) found= 1;
else count = count + 1;
 
end
if (!found) $display("%t address= %h !Error in Block Library : specified block address is out of range",$time,address);
getBlock= count;
end
endfunction
 
 
// ***************************
//
// FUNCTION getBlockAddress :
// return the block address
//
// ***************************
 
function [`ADDRBUS_dim - 1 : 0] getBlockAddress;
 
input block;
 
integer block;
 
begin
 
getBlockAddress = BlockBoundaryStartAddr[block];
 
end
endfunction
 
 
// *********************************************
//
// FUNCTION isParameterBlock :
// return true if the address
// is in a parameter block
//
// *********************************************
 
function isParameterBlock;
 
input address;
 
reg [`ADDRBUS_dim - 1 : 0] address;
reg prm;
integer count;
 
begin
 
prm = `FALSE;
if (`organization=="bottom") begin
 
for (count = 0; count <= `ParameterBlock_num - 1; count = count + 1) begin: cycle
 
if ((BlockBoundaryStartAddr[count] <= address) && (address <= BlockBoundaryEndAddr[count]))
begin
prm= `TRUE;
disable cycle;
end
end
end else begin
for (count = `BLOCK_dim - `ParameterBlock_num + 1; count <= `BLOCK_dim - 1; count = count + 1) begin: cycle1
 
if ((BlockBoundaryStartAddr[count] <= address) && (address <= BlockBoundaryEndAddr[count]))
begin
prm= `TRUE;
disable cycle1;
end
end
end
isParameterBlock = prm;
end
endfunction
 
 
// *********************************************
//
// FUNCTION isMainBlock :
// return true if the address is in a main block
//
// *********************************************
 
function isMainBlock;
 
input address;
 
reg [`ADDRBUS_dim - 1 : 0] address;
reg main;
integer count;
 
begin
 
main = `FALSE;
 
if (`organization=="bottom") begin
for (count = `BLOCK_dim - 1; count >= `BLOCK_dim - `ParameterBlock_num + 1; count = count - 1) begin: cycle2
 
if ((BlockBoundaryStartAddr[count] <= address) && (address <= BlockBoundaryEndAddr[count]))
begin
main = `TRUE;
disable cycle2;
end
end
end else begin
for (count = 0; count <= `MainBlock_num - 1; count = count + 1) begin: cycle3
 
 
if ((BlockBoundaryStartAddr[count] <= address) && (address <= BlockBoundaryEndAddr[count]))
begin
main = `TRUE;
disable cycle3;
end
end
end
isMainBlock = main;
end
endfunction
 
 
endmodule
/include/cfi_flash_UserData.h
0,0 → 1,36
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
 
// ************************************
//
// User Data definition file :
//
// here are defined all parameters
// that the user can change
//
// ************************************
 
`define organization "top" // top or bottom
`define BLOCKPROTECT "on" // if on the blocks are locked at power-up
`define TimingChecks "on" // on for checking timing constraints
`define t_access 100 // Access Time 100 ns, 110 ns
`define FILENAME_mem "cfi-flash.vmem" // Memory File Name
/include/cfi_flash_data.h
0,0 → 1,214
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
 
// ******
//
// data.h
//
// ******
 
// ********************
//
// Main Characteristics
//
// ********************
 
`define ADDRBUS_dim 24 // - Address Bus pin numbers
`define DATABUS_dim 16 // - Data Bus pin numbers
`define MEMORY_dim 1 << `ADDRBUS_dim // - Memory Dimension
`define LAST_ADDR (`MEMORY_dim) - 1 // - Last Address
 
// ********************
//
// Address & Data range
//
// ********************
 
`define ADDRBUS_range `ADDRBUS_dim - 1 : 0
`define DATABUS_range `DATABUS_dim - 1 : 0
 
// *****************
//
// Init Memory Files
//
// *****************
 
`define CFI_dim 9'h157
`define CFI_range `CFI_dim - 1:9'h10
// *******************
//
// Protection Register
//
// *******************
 
 
`define REG_addrStart 16'h0
`define REG_addrEnd 16'h15
 
`define REGSTART_addr 9'h80 // Protection Register Start Address
`define REGEND_addr 9'h109 // Protection Register End Address
`define REG_dim `REGEND_addr - `REGSTART_addr + 1
 
`define REG_addrRange `REG_addrEnd:`REG_addrStart
 
`define REG_addrbitStart 8'd0
`define REG_addrbitEnd 8'd8
`define REG_addrbitRange `REG_addrbitEnd:`REG_addrbitStart
 
`define PROTECTREGLOCK_addr 9'h80 // Protection Register Lock Address
 
 
`define UDNREGSTART_addr 9'h81
`define UDNREGEND_addr 9'h84
`define UDNprotect_bit 8'hFE
 
`define UPREGSTART_addr 9'h85
`define UPREGEND_addr 9'h88
`define UPprotect_bit 8'hFD // serve ad indentificare quale bit deve essere 0 nel lock regi
`define PRL_default 16'h0002 // Protection Register Lock default definito anche in def
 
// *****************************
//
// Extended User OTP
//
// *****************************
 
`define ExtREG_dim 8'h20
 
 
`define ExtREG_regiondim 8'h8
`define ExtREGSTART_regionaddr 9'h8A // Ext Protection Register Start Address
`define ExtREGEND_regionaddr 9'h109 // Ext Protection Register End Address
 
`define ExtPROTECTREGLOCK_addr 9'h89 // Ext Protection Register Lock Address
`define ExtPRL_default 16'hFFFF // Protection Register Lock default
 
 
 
// ***********************
//
// Voltage Characteristics
//
// ***********************
`define Voltage_range 35:0
`define VDDmin 36'd01700
`define VDDmax 36'd02000
`define VDDQmin 36'd01700
`define VDDQmax 36'd03600
`define VPPmin 36'd00900
`define VPPmax 36'd03600
`define VPPHmin 36'd08500
`define VPPHmax 36'd09500
 
// **********************
//
// Configuration Register
//
// **********************
 
`define ConfigurationReg_dim 16
`define ConfigReg_default 16'hF94F
 
// ********************
//
// Electronic Signature
//
// ********************
 
`define ManufacturerCode 8'h89
`define TopDeviceCode 8'h19
`define BottomDeviceCode 8'h1C
`define SignAddress_dim 9
`define SignAddress_range `SignAddress_dim - 1 : 0
 
 
 
// *********************
//
// Write Buffer constant
//
// *********************
 
 
`define ProgramBuffer_addrDim 9 // Program Buffer address dimension
`define ProgramBuffer_addrRange `ProgramBuffer_addrDim - 1:0
`define ProgramBuffer_dim 512 // Buffer Size= 2 ^ ProgramBuffer_addrDim
`define ProgramBuffer_range `ProgramBuffer_dim - 1:0
 
// *********************
//
// Buffer Enhanced Program constant
//
// *********************
 
`define BuffEnhProgramBuffer_dim 512
`define BuffEnhProgramBuffer_range `BuffEnhProgramBuffer_dim - 1 : 0
`define BuffEnhProgramBuffer_addrDim 9
`define BuffEnhProgramBuffer_addrRange `BuffEnhProgramBuffer_addrDim - 1:0
 
// Warning and Error Messages
 
`define NoError_msg 0 // No Error Found
`define CmdSeq_msg 1 // Sequence Command Unknown
`define SuspCmd_msg 2 // Cannot execute this command during suspend
`define SuspAcc_msg 3 // Cannot access this address due to suspend
`define AddrRange_msg 4 // Address out of range
`define AddrTog_msg 5 // Cannot change block address during command sequence
`define SuspAccWarn_msg 6 // It isn't possible access this address due to suspend
`define InvVDD_msg 7 // Voltage Supply must be: VDD>VDDmin or VDD<VDDmax
`define InvVPP_msg 8 // Voltage Supply must be: VDD>VDDmin or VDD<VDDmax
`define BlockLock_msg 9 // Cannot complete operation when the block is locked
`define ByteToggle_msg 10 // Cannot toggle BYTE_N while busy
`define NoUnLock_msg 11 // Invalid UnLock Block command in Locked-Down Block
`define AddrCFI_msg 12 // CFI Address out of range
`define PreProg_msg 13 // Program Failure due to cell failure
`define NoBusy_msg 14 // Device is not Busy
`define NoSusp_msg 15 // Nothing previus suspend command
`define Suspend_msg 16 // Device is Suspend mode
`define UDNlock_msg 17 // Unique Device Number Register is locked
`define UPlock_msg 18 // User Programmable Register is locked
`define ExitPHASE_BEFP_msg 19
`define WrongEraseConfirm_msg 20 // Wrong Erase Confirm code
`define SignAddrRange_msg 21 // Signature Address out of range
`define CFIAddrRange_msg 22 // CFI Address out of range
`define WrongBlankCheckConfirm_msg 23 // Wrong Blank Check Confirm code command
`define BlankCheckFailed_msg 24 // Blank Check Failed
`define ProgramPHASE_BEFP_msg 25 // End of Program or Verify Phase on Enhanced Factory Program
`define BlkBuffer_msg 26 // Program Buffer cannot cross block boundary
`define ExtREGLock_msg 27 // Extended User Programmable Register is locked
`define LeastAddr0 28 // Significative bit [%d,0] of Start Address must be 0
`define ProtRegAddrRange_msg 29 // Protect Register Address out of range
`define BuffSize_msg 30 // Buffer size is too large
`define WrongBlankCheckBlock 31 // No main block
 
// ******************
//
// Valid Access Times
//
// ******************
 
`define tAccess_1 100
`define tAccess_2 110
 
 
 
 
/include/cfi_flash_CUIcommandData.h
0,0 → 1,106
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
 
// **********************
//
// COMMAND USER INTERFACE
//
// **********************
 
// Read Commands
 
`define RD_cmd 8'hFF // Read Memory Array
`define RSR_cmd 8'h70 // Read Status Register
`define RSIG_cmd 8'h90 // Read Electronic Signature
`define RCFI_cmd 8'h98 // Read CFI
 
 
// Program/Erase Commands
 
`define PG_cmd 8'h40 // Program
`define PES_cmd 8'hB0 // Program/Erase Suspend
`define PER_cmd 8'hD0 // Program/Erase Resume
`define BLKEE_cmd 8'h20 // Block Erase
`define BLKEEconfirm_cmd 8'hD0 // Block Erase Confirm
`define CLRSR_cmd 8'h50 // Clear Status Register
`define PRREG_cmd 8'hC0 // Protection Register Program //verificare se va bene x OTP register program setup
 
 
// Protect Commands
 
`define BL_cmd 8'h60 // Block Lock //setup??
`define BUL_cmd 8'h60 // Block UnLock
`define BLD_cmd 8'h60 // Block lock-down
`define BLDconfirm_cmd 8'h2F // Block Lock-down confirm
`define BLconfirm_cmd 8'h01 // Block Lock Confirm
`define BULconfirm_cmd 8'hD0 // Block unLock Confirm
 
 
// Additional Features Commands
 
`define PB_cmd 8'hE8 // Program Buffer
`define PBcfm_cmd 8'hD0 // Close Sequence of Program Buffer Command
 
 
// Configuration Register
 
`define SCR_cmd 8'h60 // Set Configuration Register
`define SCRconfirm_cmd 8'h03 // Set Configuration Register confirm
 
// Additional Features Commands //aggiunto
`define BLNKCHK_cmd 8'hBC // Blank Check Command
`define BLNKCHKconfirm_cmd 8'hD0 // Blank Check Confirm
 
 
// Factory Program Commands
`define BuffEnhProgram_cmd 8'h80 // Enhanced Setup Command
`define BuffEnhProgramCfrm_cmd 8'hD0 // Enhanced Setup confirm
 
`define EnhSetup_cmd 8'h80 // Enhanced Setup Command
`define EnhSetup_cfrm 8'hD0 // Enhanced Setup confirm
 
 
// CUI Status
 
// Read Bus Status Operation
 
`define ReadArray_bus 2'b00 // Read Memory Array
`define ReadSignature_bus 2'b01 // Read Electronic Signature
`define ReadStatusReg_bus 2'b10 // Read Status Register
`define ReadCFI_bus 2'b11 // Read CFI
 
 
// Program/Erase Controller Status
 
`define Free_pes 0 // No Operation
`define Program_pes 1 // Programming
`define ProgramBuff_pes 7 // Programming
 
 
`define BlockErase_pes 2 // Erasing Block
`define ChipErase_pes 3 // Chip Erasing
`define BlockEraseSuspend_pes 4 // Block Erase Suspend
`define ProgramEraseSuspend_pes 5 // Program/Erase Resume
`define ProgramEraseWait_pes 6 // Program/Erase Wait
`define Reset_pes 10 // Reset status
 
 
 
/x28fxxxp30.v
0,0 → 1,3793
// _/ _/_/
// _/_/ _/_/_/
// _/_/_/_/ _/_/_/
// _/_/_/_/_/ _/_/_/ ____________________________________________
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/ _/_/_/ / 28F256P30 /
// _/_/_/_/_/ _/_/_/ / /
// _/_/_/_/_/_/ _/_/_/ / 256Mbit /
// _/_/_/_/_/_/ _/_/_/ / single die /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/ _/_/_/ / Verilog Behavioral Model /
// _/_/_/ _/_/_/ _/_/_/ / Version 1.3 /
// _/_/_/ _/_/_/ _/_/_/ / /
// _/_/_/ _/_/_/_/_/_/ / Copyright (c) 2010 Numonyx B.V. /
// _/_/_/ _/_/_/_/_/ /___________________________________________/
// _/_/_/ _/_/_/_/
// _/_/ _/_/_/
//
//
// NUMONYX
`include "cfi_flash_def.h"
`include "cfi_flash_CUIcommandData.h"
`include "cfi_flash_data.h"
`include "cfi_flash_UserData.h"
`include "cfi_flash_BankLib.h"
`include "cfi_flash_TimingData.h"
 
// **********************************
//
// Timing Lib Module :
//
// checks all timing constraints
//
// **********************************
 
module TimingLibModule(A, DQ, W_N, G_N, E_N, L_N, WP_N, CK, VPP);
 
input [`ADDRBUS_dim-1:0] A; // Address Bus
input [`DATABUS_dim-1:0] DQ; // Data I/0 Bus
 
input W_N, G_N, E_N, L_N, WP_N, CK;
input [`Voltage_range] VPP;
 
integer AddValid_time;
integer AddNotValid_time;
integer DataValid_time;
integer DataXX_time;
 
integer WriteEnableLow_time;
integer WriteEnableHigh_time;
integer OutputEnableLow_time;
integer OutputEnableHigh_time;
integer LatchEnableHigh_time;
integer LatchEnableLow_time;
integer ChipEnableLow_time;
integer ChipEnableHigh_time;
integer RisingEdge_time;
integer FallingEdge_time;
 
integer WaitValid_time;
 
integer WriteProtectHigh_time;
integer WriteProtectLow_time;
integer VPPSupplyHigh_time;
integer VPPSupplyLow_time;
 
reg afterReset;
 
reg isValid;
reg dataValid;
reg addressValid;
reg reading;
reg writing;
reg dataXX;
time temp;
 
 
initial begin
 
AddValid_time = 0;
AddNotValid_time = 0;
DataValid_time = 0;
DataXX_time = 0;
 
WriteEnableLow_time = 0;
WriteEnableHigh_time = 0;
OutputEnableLow_time = 0;
OutputEnableHigh_time = 0;
LatchEnableHigh_time = 0;
LatchEnableLow_time = 0;
ChipEnableLow_time = 0;
ChipEnableHigh_time = 0;
 
WaitValid_time = 0;
 
WriteProtectHigh_time = 0;
WriteProtectLow_time = 0;
 
RisingEdge_time = 0;
FallingEdge_time = 0;
 
dataValid = `FALSE;
dataXX = `FALSE;
addressValid = `FALSE;
 
reading = `FALSE;
writing = `FALSE;
 
afterReset = `FALSE;
 
end
 
 
// **************
//
// Change address
//
// **************
 
always @(A) begin : AddressCheck
 
if (`TimingChecks == "off")
disable AddressCheck;
 
if ($time > `Reset_time)
begin
if (isAddValid(A)) // Address Valid
begin
temp = $time - AddValid_time;
checkTiming("tAVAV", TimingData_man.tAVAV, temp, "min");
 
temp = $time - WriteEnableHigh_time;
checkTiming("tWHAV", TimingData_man.tWHAV, temp, "min");
 
AddValid_time = $time;
addressValid = `TRUE;
end
 
else
begin
if (isAddXX(A) || isAddZZ(A)) // Address XXXX o ZZZZ
begin
if (addressValid)
begin
temp = $time - LatchEnableHigh_time;
checkTiming("tLHAX", TimingData_man.tLHAX, temp, "min");
 
temp = $time - WriteEnableHigh_time;
checkTiming("tWHAX", TimingData_man.tWHAX, temp, "min");
 
AddNotValid_time = $time;
end
addressValid = `FALSE;
end
end
end
end
 
 
// ***********
//
// Change data
//
// ***********
 
always @(DQ) begin : DataCheck
 
if (`TimingChecks == "off")
disable DataCheck;
 
if ($time > `Reset_time)
begin
 
if (isDataValid(DQ)) // Data Valid
begin
if (ConfigReg_man.isSynchronous) // Synchronous mode
 
begin
if (reading)
if (ConfigReg_man.isRisingClockEdge)
begin
temp = $time - RisingEdge_time;
end
else
begin
temp = $time - FallingEdge_time;
 
end
end
 
else // Asynchronous mode
begin
temp = $time - AddValid_time;
 
temp = $time - LatchEnableLow_time;
 
temp = $time - ChipEnableLow_time;
 
if (reading)
begin
temp = $time - OutputEnableLow_time;
temp = $time - WriteEnableHigh_time;
end
 
DataValid_time = $time;
dataValid = `TRUE;
dataXX = `FALSE;
end
end
else
begin
if (isDataXX(DQ)) // Data XXXX
begin
if (dataValid)
begin
temp = $time - AddNotValid_time;
 
temp = $time - ChipEnableHigh_time;
checkTiming("tEHQX", TimingData_man.tEHQX, temp, "min");
 
temp = $time - OutputEnableHigh_time;
 
end
 
else
begin
temp = $time - ChipEnableLow_time;
checkTiming("tELQX", TimingData_man.tELQX, temp, "min");
 
if (reading)
begin
temp = $time - OutputEnableLow_time;
checkTiming("tGLQX", TimingData_man.tGLQX, temp, "min");
end
end
 
 
DataXX_time = $time;
dataValid = `FALSE;
dataXX = `TRUE;
end
 
else
if (isDataZZ(DQ))
begin
if (dataXX)
begin
temp = $time - ChipEnableHigh_time;
checkTiming("tEHQZ", TimingData_man.tEHQZ, temp, "max");
temp = $time - OutputEnableHigh_time;
checkTiming("tGHQZ", TimingData_man.tGHQZ, temp, "max");
end
 
if (dataValid)
begin
temp = $time - WriteEnableHigh_time;
checkTiming("tWHDX", TimingData_man.tWHDX, temp, "min");
end
dataValid = `FALSE;
dataXX = `FALSE;
end
end
end
end
 
// ******************
//
// Change Chip Enable
//
// ******************
 
always @(posedge E_N) begin : ChipHighCheck // Chip Enable High
 
if (`TimingChecks == "off")
disable ChipHighCheck;
 
if ($time > `Reset_time)
begin
temp = $time - WriteEnableHigh_time;
checkTiming("tWHEH", TimingData_man.tWHEH, temp, "min");
 
ChipEnableHigh_time = $time;
end
end
 
always @(negedge E_N) begin : ChipLowCheck // Chip Enable Low
 
if (`TimingChecks == "off")
disable ChipLowCheck;
 
if ($time > `Reset_time)
begin
ChipEnableLow_time = $time;
end
 
end
 
always @(posedge L_N) begin : LatchLowCheck // Latch Enable High
 
if (`TimingChecks == "off")
disable LatchLowCheck;
 
if ($time > `Reset_time)
begin
temp = $time - AddValid_time;
checkTiming("tAVLH", TimingData_man.tAVLH, temp, "min");
temp = $time - LatchEnableLow_time;
checkTiming("tLLLH", TimingData_man.tLLLH, temp, "min");
temp = $time - ChipEnableLow_time;
checkTiming("tELLH", TimingData_man.tELLH, temp, "min");
LatchEnableHigh_time = $time;
end
end
 
always @(negedge L_N) begin : LatchHighCheck // Latch Enable Low
 
if (`TimingChecks == "off")
disable LatchHighCheck;
 
if ($time > `Reset_time)
begin
temp = $time - WriteEnableHigh_time;
checkTiming("tWHLL", TimingData_man.tWHLL, temp, "min");
 
temp = $time - RisingEdge_time;
checkTiming("tKHLL", TimingData_man.tKHLL, temp, "min");
 
LatchEnableLow_time = $time;
end
 
end
 
always @(posedge G_N) begin : OutputHighCheck // Output Enable High
 
if (`TimingChecks == "off")
disable OutputHighCheck;
 
if ($time > `Reset_time)
begin
OutputEnableHigh_time = $time;
reading = `FALSE;
end
 
end
 
always @(negedge G_N) begin : OutputLowCheck // Output Enable Low
 
if (`TimingChecks == "off")
disable OutputLowCheck;
 
if ($time > `Reset_time)
begin
 
temp = $time - WriteEnableHigh_time;
checkTiming("tWHGL", TimingData_man.tWHGL, temp, "min");
 
 
OutputEnableLow_time = $time;
reading = `TRUE;
end
 
end
 
always @(posedge W_N) begin : WriteHighCheck // Write Enable High
 
if (`TimingChecks == "off")
disable WriteHighCheck;
 
if ($time > `Reset_time)
begin
 
temp = $time - AddValid_time;
checkTiming("tAVWH", TimingData_man.tAVWH, temp, "min");
 
if (writing)
begin
temp = $time - WriteEnableLow_time;
checkTiming("tWLWH", TimingData_man.tWLWH, temp, "min");
end
temp = $time - DataValid_time;
checkTiming("tDVWH", TimingData_man.tDVWH, temp, "min");
 
temp = $time - WriteProtectHigh_time;
checkTiming("tWPHWH", TimingData_man.tWPHWH, temp, "min");
 
temp = $time - VPPSupplyHigh_time;
checkTiming("tVPHWH", TimingData_man.tVPHWH, temp, "min");
 
WriteEnableHigh_time = $time;
writing = `FALSE;
end
end
 
always @(negedge W_N) begin : WriteLowCheck // Write Enable Low
 
if (`TimingChecks == "off")
disable WriteLowCheck;
 
if ($time > `Reset_time)
begin
temp = $time - ChipEnableLow_time;
checkTiming("tELWL", TimingData_man.tELWL, temp, "min");
 
temp = $time - WriteEnableHigh_time;
checkTiming("tWHWL", TimingData_man.tWHWL, temp, "min");
 
WriteEnableLow_time = $time;
writing = `TRUE;
end
end
 
always @(posedge WP_N) begin : WPHighCheck // Write Protect High
 
if (`TimingChecks == "off")
disable WPHighCheck;
 
if ($time > `Reset_time)
begin
WriteProtectHigh_time = $time;
end
end
 
always @(negedge WP_N) begin : WPLowCheck // Write Protect Low
 
if (`TimingChecks == "off")
disable WPLowCheck;
 
if ($time > `Reset_time)
begin
temp = $time - DataValid_time;
checkTiming("tQVWPL", TimingData_man.tQVWPL, temp, "min");
 
WriteProtectLow_time = $time;
end
end
 
always @(posedge VPP) begin : VPPHighCheck // Write Protect High
 
if (`TimingChecks == "off")
disable VPPHighCheck;
 
if ($time > `Reset_time)
begin
VPPSupplyHigh_time = $time;
end
end
 
always @(negedge VPP) begin : VPPLowCheck // Write Protect Low
 
if (`TimingChecks == "off")
disable VPPLowCheck;
 
if ($time > `Reset_time)
begin
temp = $time - DataValid_time;
checkTiming("tQVVPL", TimingData_man.tQVVPL, temp, "min");
 
VPPSupplyLow_time = $time;
 
end
end
 
always @(posedge CK) begin : RisingCKCheck
 
if (`TimingChecks == "off")
disable RisingCKCheck;
 
if ($time > `Reset_time)
begin
temp = $time - LatchEnableLow_time;
checkTiming("tLLKH", TimingData_man.tLLKH, temp, "min");
 
RisingEdge_time = $time;
end
end
 
always @(negedge CK) begin : FallingCKCheck
 
if (`TimingChecks == "off")
disable FallingCKCheck;
 
if ($time > `Reset_time)
begin
temp = $time - LatchEnableLow_time;
checkTiming("tLLKL", TimingData_man.tLLKL, temp, "min");
FallingEdge_time = $time;
end
end
 
 
 
// **********************************************
//
// FUNCTION isAddValid :
// return true if the input address is valid
//
// **********************************************
 
function isAddValid;
 
input [`ADDRBUS_dim - 1 : 0] Add;
 
reg [`ADDRBUS_dim - 1 : 0] Add;
 
reg valid;
integer count;
 
begin
 
valid = `TRUE;
begin : cycle
for (count = 0; count <= `ADDRBUS_dim - 1; count = count + 1)
begin
if ((Add[count] !== 1'b0) && (Add[count] !== 1'b1))
begin
valid = `FALSE;
disable cycle;
end
end
end
isAddValid = valid;
end
endfunction
 
 
// *********************************************
//
// FUNCTION isAddXX :
// return true if the input address is XXXX
//
// *********************************************
 
function isAddXX;
 
input [`ADDRBUS_dim - 1 : 0] Add;
 
reg [`ADDRBUS_dim - 1 : 0] Add;
 
reg allxx;
integer count;
 
begin
 
allxx = `TRUE;
begin : cycle
for (count = 0; count <= `ADDRBUS_dim - 1; count = count + 1)
begin
if (Add[count] !== 1'bx)
begin
allxx = `FALSE;
disable cycle;
end
end
end
isAddXX = allxx;
end
endfunction
 
// *********************************************
//
// FUNCTION isAddZZ :
// return true if the input address is ZZZZ
//
// *********************************************
 
function isAddZZ;
 
input [`ADDRBUS_dim - 1 : 0] Add;
 
reg [`ADDRBUS_dim - 1 : 0] Add;
 
reg allzz;
integer count;
 
begin
 
allzz = `TRUE;
begin : cycle
for (count = 0; count <= `ADDRBUS_dim - 1; count = count + 1)
begin
if (Add[count] !== 1'bz)
begin
allzz = `FALSE;
disable cycle;
end
end
end
isAddZZ = allzz;
end
endfunction
 
// **********************************************
//
// FUNCTION isDataValid :
// return true if the data is valid
//
// **********************************************
 
function isDataValid;
 
input [`DATABUS_dim - 1 : 0] Data;
 
reg [`DATABUS_dim - 1 : 0] Data;
 
reg valid;
integer count;
 
begin
 
valid = `TRUE;
begin : cycle
for (count = 0; count <= `DATABUS_dim - 1; count = count + 1)
begin
if ((Data[count] !== 1'b0) && (Data[count] !== 1'b1))
begin
valid = `FALSE;
disable cycle;
end
end
end
isDataValid = valid;
end
endfunction
 
// ***************************************
//
// FUNCTION isDataXX :
// return true if the data is unknown
//
// ***************************************
 
function isDataXX;
 
input [`DATABUS_dim - 1 : 0] Data;
 
reg [`DATABUS_dim - 1 : 0] Data;
 
reg allxx;
integer count;
 
begin
 
allxx = `TRUE;
begin : cycle
for (count = 0; count <= `DATABUS_dim - 1; count = count + 1)
begin
if (Data[count] !== 1'bx)
begin
allxx = `FALSE;
disable cycle;
end
end
end
isDataXX = allxx;
end
endfunction
 
// ************************************
//
// FUNCTION isDataZZ :
// return true if the data is Hi-Z
//
// ************************************
 
function isDataZZ;
 
input [`DATABUS_dim - 1 : 0] Data;
 
reg [`DATABUS_dim - 1 : 0] Data;
 
reg allzz;
integer count;
 
begin
 
allzz = `TRUE;
begin : cycle
for (count = 0; count <= `DATABUS_dim - 1; count = count + 1)
begin
if (Data[count] !== 1'bz)
begin
allzz = `FALSE;
disable cycle;
end
end
end
isDataZZ = allzz;
end
endfunction
 
// *****************************
//
// Task Check Timing
// check timing constraints
//
// *****************************
 
task checkTiming;
input [8*6:1] tstr;
input [31:0] tOK, tcheck;
input [8*3:1] check_str;
begin
if ((check_str == "min") && (tcheck < tOK)) begin
$display ("[%t] !ERROR: %0s timing constraint violation!! ", $time, tstr);
end
 
else
if ((check_str == "max") && (tcheck > tOK))
$display ("[%t] !ERROR: %0s timing constraint violation!! ", $time, tstr);
end
endtask
 
 
endmodule
 
 
// Protect Manager
// implements the architecture of the memory blocks
 
module BlockLockModule(address, WP_N, RP_N, Info);
input [`ADDRBUS_range] address;
input WP_N, RP_N;
input Info;
 
reg LockArray [`BLOCK_dim - 1 : 0];
reg LockDownArray [`BLOCK_dim - 1 : 0];
 
reg [`BYTE_range] Status;
integer count;
initial begin // constructor sequence
for (count = 0; count <= `BLOCK_dim - 1; count = count + 1) // all blocks are locked at power-up
begin
LockDownArray[count] = `UNLOCKDOWN;
if (`BLOCKPROTECT == "on") LockArray[count] = `LOCK;
else LockArray[count] = `UNLOCK;
end
end
 
always @(negedge RP_N) begin
initLockArray;
end
 
task initLockArray;
begin
for (count = 0; count <= `BLOCK_dim - 1; count = count + 1) // all blocks are locked at power-up
begin
LockDownArray[count] = `UNLOCKDOWN;
LockArray[count] = `LOCK;
end
end
endtask
 
 
 
// ********************************************
//
// FUNCTION isLocked : return the status of the
// specified block
//
// ********************************************
 
function IsLocked; // boolean function primitive
input [`ADDRBUS_range] address;
integer n_block;
 
begin
n_block = BankLib_man.getBlock(address);
IsLocked = (LockArray[n_block] == `LOCK) ? `TRUE : `FALSE;
end
endfunction
 
// ********************************************
//
// FUNCTION isLocked : return the status of the
// specified block
//
// ********************************************
 
function IsUnLocked; // boolean function primitive
input [`ADDRBUS_range] address;
integer n_block;
 
begin
n_block = BankLib_man.getBlock(address);
IsUnLocked = (LockArray[n_block] == `UNLOCK) ? `TRUE : `FALSE;
end
endfunction
 
 
function getLockBit; // boolean function primitive
input [`ADDRBUS_range] address;
integer n_block;
 
begin
n_block = BankLib_man.getBlock(address);
getLockBit = LockArray[n_block];
end
endfunction
 
function getLockDownBit; // boolean function primitive
input [`ADDRBUS_range] address;
integer n_block;
 
begin
n_block = BankLib_man.getBlock(address);
getLockDownBit = LockDownArray[n_block];
end
endfunction
 
 
// ********************************
//
// Task UnLock :
// implements Block UnLock Command
//
// ********************************
 
task UnLock;
output [`BYTE_range] Status;
reg [`BYTE_range] Status;
 
integer n_block;
begin
n_block = BankLib_man.getBlock(address);
Status = `NoError_msg;
if (LockDownArray[n_block]==`LOCKDOWN && WP_N==`LOW) Status = `NoUnLock_msg;
else LockArray[n_block] = `UNLOCK;
end
endtask
 
// ********************************
//
// Task Lock :
// implements Block Lock Command
//
// ********************************
 
task Lock;
output [`BYTE_range] Status;
reg [`BYTE_range] Status;
 
integer n_block;
begin
n_block = BankLib_man.getBlock(address);
Status = `NoError_msg;
LockArray[n_block] = `LOCK;
end
endtask
 
// *****************************************
//
// Task LockDown :
// implements the Block Lock-Down Command
//
// *****************************************
 
task LockDown;
output [`BYTE_range] Status;
reg [`BYTE_range] Status;
 
integer n_block;
begin
n_block = BankLib_man.getBlock(address);
Status = `NoError_msg;
LockDownArray[n_block] = `LOCKDOWN;
end
endtask
 
 
endmodule
 
 
// *************************
//
// CFI Query Module
// Implements the CFI memory
//
// *************************
 
module CFIqueryModule(); //, isCFI);
 
//input isCFI;
 
reg [`BYTE_range] CFIarray [0:`CFI_dim];
reg error;
reg [8*20:1] CFI_file;
integer i;
 
initial begin
if (`organization == "top") CFI_file = "CFImemory_top.vmf";
else CFI_file= "CFImemory_bottom.vmf";
 
for (i=0; i <= `CFI_dim; i = i + 1) CFIarray[i] = {8{`HIGH}}; // CFI Memory Init
$readmemb(CFI_file,CFIarray);
end
 
always @(posedge error) begin
Kernel.SetWarning(`RCFI_cmd,16'h00,`CFIAddrRange_msg);
error = `FALSE;
end
 
function [`WORD_range] Get;
 
input [`ADDRBUS_range] address;
begin
if (address[`BYTE_range] >= 9'h10 && address[`BYTE_range] <= `CFI_dim ) //verificare se tener conto che il primo indirizzo accessibile e' 10h
begin
if (address[`BYTE_range] >= 9'h39 && address[`BYTE_range] <= 9'h109) begin
Get = 8'hXX;
error = `TRUE;
end else begin
 
Get[`LOW_range] = CFIarray[address[`BYTE_range]];
Get[`HIGH_range] = 8'h00;
end
end else
begin
Get = 8'hXX;
error = `TRUE;
end
end
endfunction
 
endmodule
 
// ********************************
//
// Data Error Module
//
// search for errors in data.h
//
// ********************************
 
module DataErrorModule;
 
reg SevError;
 
initial begin
 
SevError = `FALSE;
 
if ((`organization != "top") && (`organization != "bottom"))
begin
SevError = `TRUE;
$display("!Error: BLOCK ORGANIZATION INVALID: it must be top or bottom!!!");
end
 
if ((`BLOCKPROTECT != "on") && (`BLOCKPROTECT != "off"))
begin
SevError = `TRUE;
$display("!Error: BLOCK PROTECT INVALID: it must be on or off!!!");
end
 
if ((`TimingChecks != "on") && (`TimingChecks != "off"))
begin
SevError = `TRUE;
$display("!Error: TIMING CHECKS INVALID: it must be on or off!!!");
end
 
 
if ((`t_access != 100) && (`t_access != 110))
begin
SevError = `TRUE;
$display("!Error: Access time INVALID: it must be 100 ns or 110 ns!!!");
end
 
 
if (SevError) $finish;
end
 
endmodule
 
// ******************************************
//
// Configuration Register module :
//
// implements the configuration register
//
// ******************************************
 
module ConfigRegModule(address,Info);
input [`ADDRBUS_range] address;
input Info;
 
reg [`ConfigurationReg_dim - 1 : 0] CR_reg;
reg [`BYTE_range] Status;
 
// **********************
//
// Setting default values
//
// **********************
 
`define ReadMode_bit 15
`define ClockLatency_MSBbit 14
`define ClockLatency_LSBbit 11
`define WaitPolarity_bit 10
`define WaitConfig_bit 8
`define BurstType_bit 7
`define ValidClockEdge_bit 6
`define WrapBurst_bit 3
`define BurstLength_MSBbit 2
`define BurstLength_LSBbit 0
 
// Interpreter Config Reg\\
 
wire isASynchronous = CR_reg[`ReadMode_bit] ? `TRUE : `FALSE;
wire isSynchronous = CR_reg[`ReadMode_bit] ? `FALSE : `TRUE;
wire [3:0] Xlatency = (CR_reg[`ClockLatency_MSBbit : `ClockLatency_LSBbit]<2 &&
CR_reg[`ClockLatency_MSBbit : `ClockLatency_LSBbit]>15) ? 0 :
CR_reg[`ClockLatency_MSBbit : `ClockLatency_LSBbit];
wire isWaitPolActiveHigh = CR_reg[`WaitPolarity_bit] ? `TRUE : `FALSE;
wire isWaitBeforeActive = CR_reg[`WaitConfig_bit] ? `TRUE : `FALSE;
wire isRisingClockEdge = CR_reg[`ValidClockEdge_bit] ? `TRUE : `FALSE;
wire isWrapBurst = CR_reg[`WrapBurst_bit] ? `FALSE : `TRUE;
wire isNoWrapBurst = CR_reg[`WrapBurst_bit] ? `TRUE : `FALSE;
 
wire [4:0] BurstLength = CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 1 ? 4 :
CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 2 ? 8 :
CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 3 ? 16:
0; // continous Burst
 
 
wire [2:0] BurstLength_bit = CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 1 ? 2 :
CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 2 ? 3 :
CR_reg[`BurstLength_MSBbit : `BurstLength_LSBbit] == 3 ? 4:
0; // continous Burst
 
initial begin
Status = `NoError_msg;
CR_reg = `ConfigReg_default;
end
 
always @(isSynchronous) begin
if (Info)
if (isSynchronous)
$write("[%t] Synchronous Read Mode\n",$time);
else
$write("[%t] ASynchronous Read Mode\n",$time);
end
// **********************
//
// ReSet to default value
//
// **********************
always @(Kernel.ResetEvent) begin
Status = `NoError_msg;
CR_reg = `ConfigReg_default;
end
 
// **************************************
//
// FUNCTION getConfigReg :
//
// return the Configuration Register
//
// **************************************
 
function [`ConfigurationReg_dim - 1 : 0] getConfigReg;
input required;
begin
getConfigReg = CR_reg;
end
endfunction
 
// *************************************
//
// FUNCTION putConfigReg :
//
// write the Configuration Register
//
// *************************************
 
task putConfigReg;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
 
integer count;
 
begin
CR_reg = address[`ConfigurationReg_dim - 1 : 0];
 
outStatus = Status;
 
end
endtask
 
 
endmodule
 
// ***************************
//
// Electronic Signature Module
//
// ***************************
 
module SignatureModule;
 
reg error;
integer i;
integer n_block;
 
initial begin
end
 
always @(posedge error) begin
Kernel.SetWarning(`RSIG_cmd,16'h00,`SignAddrRange_msg);
error = `FALSE;
end
 
function [`WORD_range] Get;
 
input [`ADDRBUS_range] address;
begin
if (address[`SignAddress_range] == 9'h00)
begin
Get[`LOW_range] = `ManufacturerCode;
Get[`HIGH_range] = 8'h00;
end
else if (address[`SignAddress_range] == 9'h01)
begin
if (`organization == "top") Get[`LOW_range] = `TopDeviceCode;
else Get[`LOW_range] = `BottomDeviceCode;
 
Get[`HIGH_range] = 8'h89;
end
else if (address[`SignAddress_range] == 9'h02)
begin
Get[`LOW_range] = { 6'b0, BlockLock_man.getLockDownBit(address), BlockLock_man.getLockBit(address) };
Get[`HIGH_range] = 8'h00;
end
else if (address[`SignAddress_range] == 9'h05) // Configuration Register
Get = ConfigReg_man.getConfigReg(0);
else if ((address[`SignAddress_range] >= `REGSTART_addr) && (address[`SignAddress_range] <= `REGEND_addr))
begin
Get = ProtectReg_man.RegisterMemory[address[`SignAddress_range] - `REGSTART_addr ];
 
end
else begin
Get = 8'hXX;
error = `TRUE;
end
end
endfunction
 
endmodule
 
// ********************
//
// CUI decoder module :
// decode commands
//
// ********************
 
module CUIdecoder1(DataBus,Name,Cmd,CmdAllowed,Info);
input [`BYTE_range] DataBus, Cmd;
input [8*35:1] Name;
input Info;
input CmdAllowed;
always @Kernel.CUIcommandEvent begin
#1;
if (DataBus == Cmd && CmdAllowed) begin // is a First Command ?
#1 -> Kernel.VerifyEvent;
Kernel.CommandDecode1[Cmd] = !Kernel.CommandDecode1[Cmd];
if (Info) $display("[%t] Command Issued: %0s",$time,Name);
end
else begin
if (`FALSE) $display("[%t] The %0s instruction decode unit is waiting for operation to complete.",$time,Name);
@(Kernel.CompleteEvent or Kernel.ErrorEvent)
if (`FALSE) $display("[%t] The %0s instruction decode unit is listening for next command.",$time,Name);
end
end
endmodule
 
 
// ********************
//
// CUIdecoder manager :
// decode commands
//
// ********************
 
module CUIdecoder2(DataBus,Name,Cmd1,Cmd2,CmdAllowed,Info);
input [`BYTE_range] DataBus, Cmd1, Cmd2;
input [8*27:1] Name;
input Info;
input CmdAllowed;
 
always @Kernel.CUIcommandEvent begin
if (DataBus == Cmd1 && CmdAllowed) begin
#1 -> Kernel.VerifyEvent;
 
@Kernel.CUIcommandEvent
 
if (DataBus == Cmd2 && CmdAllowed) begin
#1 -> Kernel.VerifyEvent;
 
Kernel.CommandDecode2[{Cmd1,Cmd2}] = !Kernel.CommandDecode2[{Cmd1,Cmd2}];
if (Info) $display("[%t] Command Issued: %0s",$time,Name);
end
end
else begin
if (`FALSE) $display("%t The %0s instruction decode unit is waiting for operation to complete.",$time,Name);
@(Kernel.CompleteEvent or Kernel.ErrorEvent)
if (`FALSE) $display("%t The %0s instruction decode unit is listening for next command",$time,Name);
end
end
 
endmodule
 
 
// ****************************
//
// CUI Decoder Manager :
// decode the cUI commands
//
// ****************************
 
module CUIdecoder_Busy1(DataBus,Name,Cmd,CmdAllowed,Info);
input [`BYTE_range] DataBus, Cmd;
input [8*8:1] Name;
input Info;
input CmdAllowed;
 
always @Kernel.CUIcommandEvent begin
if ((DataBus == Cmd) && CmdAllowed) begin
-> Kernel.VerifyEvent;
Kernel.CommandDecode1[Cmd] = !Kernel.CommandDecode1[Cmd];
if (Info) $display("[%t] Command Issued: %0s",$time,Name);
end
 
 
 
end
 
endmodule
 
 
// Erase Manager
// manage the erase functionality
 
module EraseModule(address, data, progVoltOK, progHighVoltOK,Info);
input [`ADDRBUS_range] address;
input [`WORD_range] data;
 
input progVoltOK, progHighVoltOK;
 
input Info;
event ErrorCheckEvent, CompleteEvent;
 
reg [`BYTE_range] Status;
reg [`ADDRBUS_range] hold_address;
reg [`BLOCKADDR_range] hold_block;
 
reg Busy, Suspended, first_time;
integer i;
time startTime, delayTime,Erase_time;
 
initial begin // constructor sequence
Busy = `FALSE;
Suspended = `FALSE;
Erase_time = `MainBlockErase_time;
delayTime = Erase_time;
 
end
 
 
function IsBusy; // boolean function primitive
input obbl; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
function IsSuspended; // boolean function primitive
input obbl; // all functions require a parameter
IsSuspended = Suspended; // return Boolean value
endfunction
 
function IsAddrSuspended; // boolean function primitive
input [`ADDRBUS_range] addr;
IsAddrSuspended = (Suspended && (addr == hold_address));
endfunction
 
function IsBlockSuspended; // boolean function primitive
input [`ADDRBUS_range] addr;
IsBlockSuspended = (Suspended && ((BankLib_man.getBlock(addr) == BankLib_man.getBlock(/*hold_*/addr/*ess*/))));
endfunction
 
// *********************
//
// Task checkConfirm :
// check confirm code
//
// *********************
 
task checkConfirm;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
 
begin
 
if (data == `BLKEEconfirm_cmd) outStatus = `NoError_msg;
else outStatus = `WrongEraseConfirm_msg;
 
end
endtask
 
 
task Suspend;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
delayTime = delayTime - ($time - startTime);
#`EraseSuspendLatency_time
outStatus = `NoError_msg;
Status = `Suspend_msg;
Suspended = `TRUE;
-> CompleteEvent;
end
endtask
 
task Resume;
output [`BYTE_range] Status;
begin
Suspended = `FALSE;
BlockErase(Status);
end
endtask
 
task BlockErase;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
 
 
if (progHighVoltOK)
if (BankLib_man.isMainBlock(address)) Erase_time = `FastMainBlockErase_time;
else Erase_time = `FastParameterBlockErase_time;
else
if (BankLib_man.isMainBlock(address)) Erase_time = `MainBlockErase_time;
else Erase_time = `ParameterBlockErase_time;
 
delayTime = Erase_time;
hold_address = address;
hold_block = BankLib_man.getBlock(address);
 
 
 
fork
begin : Operation
Busy = `TRUE;
startTime = $time;
-> ErrorCheckEvent;
#delayTime Memory_man.EraseBlock(hold_block,Status);
delayTime = Erase_time;
-> CompleteEvent;
end
@CompleteEvent
disable Operation;
join
outStatus = Status;
Busy = `FALSE;
end
endtask
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (BlockLock_man.IsLocked(hold_address))
Status = `BlockLock_msg;
else if (Memory_man.IsBlockSuspended(hold_address))
Status = `SuspCmd_msg;
else if (!progVoltOK)
Status = `InvVDD_msg;
 
if (Status != `NoError_msg)
->CompleteEvent;
else
fork : ErrorCheck
@(negedge progVoltOK) Status = `InvVDD_msg;
@(Status) -> CompleteEvent;
@(CompleteEvent) disable ErrorCheck;
join
end
 
endmodule //end module Erase
 
 
// *********************
//
// Memory Manager :
// the memory array
//
// *********************
 
module MemoryModule(Info);
input Info;
reg [`WORD_range] memory [0:(`MEMORY_dim) - 1]; // the Memory: word organization
 
initial begin
LoadMemory;
end
 
task LoadMemory; // Initialize and load the memory from a file
integer i;
begin
#0 if (Info) $display("[%t] Inizialize the Memory to default value",$time);
for (i = 0; i < `MEMORY_dim; i = i + 1) memory[i] = {16{`HIGH}}; // Memory Init
if (`FILENAME_mem !== "") begin
$readmemh(`FILENAME_mem, memory);
 
if (Info) $display("[%t] Load Memory from file: %s",$time, `FILENAME_mem);
else if (Info) $display("[%t] Warning: File: %s not found",$time, `FILENAME_mem);
end
end
endtask
 
 
function [`WORD_range] Get;
input [`ADDRBUS_range] address;
Get = memory[address];
endfunction
 
 
function IsSuspended;
input [`ADDRBUS_range] address;
IsSuspended = Program_man.IsAddrSuspended(address) || Erase_man.IsAddrSuspended(address) || ProgramBuffer_man.IsAddrSuspended(address);
endfunction
 
function IsBlockSuspended;
input [`ADDRBUS_range] address;
IsBlockSuspended = Program_man.IsBlockSuspended(address) || Erase_man.IsBlockSuspended(address);
endfunction
 
 
task Program;
input [`WORD_range] data;
input [`ADDRBUS_range] address;
output [`BYTE_range] Status;
begin
Status = `NoError_msg;
memory[address] = memory[address] & data;
if (memory[address] != data) Status = `PreProg_msg;
end
endtask
 
task EraseBlock;
input [`INTEGER] block;
output [`BYTE_range] ErrFlag;
 
reg [`ADDRBUS_range] start_address;
reg [`ADDRBUS_range] end_address;
reg [`ADDRBUS_range] address;
 
begin
ErrFlag = `NoError_msg;
start_address = BankLib_man.getBlockAddress(block);
end_address = BankLib_man.BlockBoundaryEndAddr[block];
 
if (start_address > end_address)
begin
address = start_address;
start_address = end_address;
end_address = address;
end
for (address = start_address; address <= end_address; address = address + 1)
memory[address] = `WORDNP;
 
end
endtask
 
task BlockBlankCheck;
input [`INTEGER] block;
output [`BYTE_range] ErrFlag;
 
reg [`ADDRBUS_range] start_address;
reg [`ADDRBUS_range] end_address;
reg [`ADDRBUS_range] address;
 
begin
ErrFlag = `NoError_msg;
start_address = BankLib_man.BlockBoundaryStartAddr[block];
end_address = BankLib_man.BlockBoundaryEndAddr[block];
 
if (start_address > end_address)
begin
address = start_address;
start_address = end_address;
end_address = address;
end
ErrFlag = `NoError_msg;
address = start_address;
while (memory[address] == `WORDNP && address <= end_address )
address = address + 1;
if (memory[address] != `WORDNP)
ErrFlag = `BlankCheckFailed_msg;
 
end
endtask
 
 
 
endmodule //end MemoryModule
 
 
// ***************************************
//
// Output Buffer :
//
// manage the communication between
// the memory and the output data bus
//
// ***************************************
 
module OutputBufferModule(DataInput, DataInputBurst, DataOutput, OutputEnable);
input [`WORD_range] DataInput;
input [`WORD_range] DataInputBurst;
output [`WORD_range] DataOutput;
input OutputEnable;
reg [`WORD_range] DataOutput;
time timeDataV, timeDataX, timeDataZ;
 
initial begin
timeDataV=0;
timeDataX=0;
timeDataZ=0;
SetZ(0);
end
 
task SetValid;
input [63:0] delayTime;
begin
 
if ((delayTime+$time > timeDataV) || (timeDataV < $time)) begin
timeDataV = delayTime + $time;
 
 
disable waitValid;
 
 
disable goValid;
 
end
end
endtask
 
always
fork
begin: goValid
 
#(timeDataV - $time)
if (OutputEnable == 1'b0) begin
if (ConfigReg_man.isASynchronous) DataOutput = DataInput;
else DataOutput = DataInputBurst;
end
end // goValid
begin: waitValid
wait (`FALSE);
end
join
 
task SetX;
input [63:0] delayTime;
begin
if ((delayTime+$time < timeDataX) || (timeDataX < $time)) begin
timeDataX = delayTime + $time;
disable waitX;
 
 
end
end
endtask
 
always fork
begin : goX
#(timeDataX - $time) if ((OutputEnable == `LOW) || (timeDataZ > timeDataX))
DataOutput = 16'hX;
end // goX
begin: waitX
wait (`FALSE);
end
join
 
task SetZ;
input [63:0] delayTime;
begin
if ((delayTime+$time < timeDataZ) || (timeDataZ < $time)) begin
timeDataZ = delayTime + $time;
disable waitZ;
if (timeDataZ < timeDataV)
disable goValid;
if (timeDataZ < timeDataX)
disable goX;
end
end
endtask
 
always begin: waitZ
#(timeDataZ - $time) DataOutput = 16'hZ;
wait (`FALSE);
end
 
endmodule
 
 
// *********************************
//
// Program module :
//
// manage the program operation
//
// *********************************
 
module ProgramModule(address,data, progVoltOK, progHighVoltOK, Info);
input [`WORD_range] data;
input [`ADDRBUS_range] address;
input progVoltOK,progHighVoltOK;
input Info;
event ErrorCheckEvent, CompleteEvent;
reg [`BYTE_range] Status;
reg [`WORD_range] hold_data;
reg [`ADDRBUS_range] hold_address;
reg Busy, Suspended;
 
integer i;
time startTime, delayTime, WordProgram_time;
 
initial begin // constructor sequence
Busy = `FALSE;
Suspended = `FALSE;
WordProgram_time = `WordProgram_time;
delayTime = WordProgram_time;
end
 
always @(progHighVoltOK) begin
if (progHighVoltOK) WordProgram_time=`FastWordProgram_time;
else WordProgram_time=`WordProgram_time;
end
 
function IsBusy; // boolean function primitive
input obbl; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
function IsSuspended; // boolean function primitive
input obbl; // all functions require a parameter
IsSuspended = Suspended; // return Boolean value
endfunction
 
function IsAddrSuspended; // boolean function primitive
input [`ADDRBUS_range] addr;
IsAddrSuspended = (Suspended && (addr == hold_address));
endfunction
 
function IsBlockSuspended; // return true if block is suspended
input [`ADDRBUS_range] addr; begin
IsBlockSuspended = (Suspended && (BankLib_man.getBlock(addr) == BankLib_man.getBlock(/*hold_*/addr/*ess*/)));
end
endfunction
 
 
task Suspend;
output [`BYTE_range] suspErrFlag;
reg [`BYTE_range] suspErrFlag;
begin
delayTime = delayTime - ($time - startTime);
#`ProgramSuspendLatency_time suspErrFlag = `NoError_msg;
Status = `Suspend_msg;
Suspended = `TRUE;
-> CompleteEvent;
end
endtask
 
task Resume;
output [`BYTE_range] ErrFlag;
begin
Suspended = `FALSE;
Program(ErrFlag);
end
endtask
 
task Program;
output [`BYTE_range] outErrFlag;
reg [`BYTE_range] outErrFlag;
begin
if (delayTime == WordProgram_time) begin
hold_data = data;
hold_address = address;
end
fork
begin : Operation
Busy = `TRUE;
startTime = $time;
-> ErrorCheckEvent;
#delayTime Memory_man.Program(hold_data,hold_address,Status);
delayTime = `WordProgram_time;
-> CompleteEvent;
end
@CompleteEvent disable Operation;
join
outErrFlag = Status;
Busy = `FALSE;
end
endtask
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (BlockLock_man.IsLocked(hold_address))
Status = `BlockLock_msg;
else
if (Memory_man.IsSuspended(hold_address))
Status = `SuspAcc_msg;
else if (!progVoltOK)
Status = `InvVDD_msg;
 
if (Status != `NoError_msg) ->CompleteEvent;
else
fork : ErrorCheck
@(negedge progVoltOK) Status = `InvVDD_msg;
@(Status) -> CompleteEvent;
@(CompleteEvent) disable ErrorCheck;
join
end
 
endmodule // end PrograModule
 
 
// *********************************
//
// Buffer Ehnanced Program module :
//
// program buffer functionality
//
// *********************************
 
module BuffEnhancedFactProgramModule(address, data, progVoltOK, progHighVoltOK, Info);
input [`ADDRBUS_range] address;
input [`WORD_range] data;
input progVoltOK, progHighVoltOK, Info;
 
event ErrorCheckEvent,ErrorCheckEvent_inVerify, CompleteEvent, WatchAddressEvent;
reg [`BYTE_range] Status;
reg [`WORD_range] hold_data, hold_StartBlock;
reg [`ADDRBUS_range] hold_address, startAddress;
reg [`WORD_range] bufferData [`BuffEnhProgramBuffer_range];
 
reg Busy;
time Program_time;
integer i,Len;
 
initial begin // constructor sequence
Busy = `FALSE;
Status = `NoError_msg;
Program_time = `WordProgram_time;
EmptyBuffer;
end
 
task EmptyBuffer;
begin
for (i = 0; i < `BuffEnhProgramBuffer_dim; i = i + 1)
bufferData[i] = 16'hFFFF;
Len=0;
end
endtask
 
function IsBusy; // boolean function primitive
input obbl; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
task Setup;
output [`BYTE_range] outStatus;
begin
Status = `NoError_msg;
Len =0;
startAddress = address;
hold_address = address;
 
hold_StartBlock = BankLib_man.getBlock(address);
-> ErrorCheckEvent;
#0 outStatus=Status;
if (Status == `NoError_msg) begin
if (Info) $display("[%t] Enhanced Factory Program -> Setup Phase",$time);
if (Info) $display("[%t] Enhanced Factory Program: Start address: %h",$time,startAddress);
#`EnhBuffProgramSetupPhase_time;
Busy = `TRUE;
end
end
endtask
 
task Exit;
output [`BYTE_range] outStatus;
begin
Busy = `FALSE;
outStatus = Status;
if (Info) $display("[%t] Enhanced Factory Program -> Exit Phase",$time);
if (Len != `BuffEnhProgramBuffer_dim)
$display("[%t] Warning --- The buffer must be completely filled for programming to occur",$time);
end
endtask
 
task Load;
output [`BYTE_range] outStatus;
begin
if (BankLib_man.getBlock(address) != hold_StartBlock) Status = `ExitPHASE_BEFP_msg;
else begin
bufferData[Len] = data;
if (Info) $display("[%t] Enhanced Factory Program -> Load: data[%d]=%h ",$time,Len,bufferData[Len]);
Len = Len + 1;
if (Len == `BuffEnhProgramBuffer_dim) Status = `ProgramPHASE_BEFP_msg;
end
outStatus = Status;
end
endtask
 
task Program;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
fork
begin : Operation
if (Info) $display("[%t] Enhanced Factory Program {Program Phase}",$time);
#`EnhBuffProgram_time
 
if (Info) $display("[%t] Enhanced Factory Program {End of Program Phase}",$time);
for (i = startAddress;i < (`BuffEnhProgramBuffer_dim + startAddress); i = i + 1) begin
Memory_man.Program(bufferData[i - startAddress],i,Status);
end
-> CompleteEvent; //end of program
end
@CompleteEvent begin
disable Operation;
end
join
if (Status == `ProgramPHASE_BEFP_msg) begin //prova
Status = `NoError_msg;
end
outStatus = Status;
end
endtask
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (BlockLock_man.IsLocked(hold_address))
Status = `BlockLock_msg;
else if (!progVoltOK)
Status = `InvVDD_msg;
else if (!progHighVoltOK)
Status = `InvVPP_msg;
if (Status != `NoError_msg)
->CompleteEvent;
else
fork : ErrorCheck
@(negedge progVoltOK) Status = `InvVDD_msg;
@(negedge progHighVoltOK) Status = `InvVPP_msg;
@(CompleteEvent) disable ErrorCheck;
join
end
 
 
 
endmodule
 
// ******************************************
//
// Protect Register module :
//
// operations on the protection register
//
// ******************************************
 
module ProtectRegModule(address, data, voltOK, Info);
input [`ADDRBUS_range] address;
input [`DATABUS_range] data;
input voltOK, Info;
reg [`WORD_range] RegisterMemory[`REG_dim - 1 :0];
reg [`BYTE_range] Status;
reg Busy;
reg [`ADDRBUS_range] AddressLatched;
event ErrorCheckEvent, CompleteEvent;
integer i;
reg [`ADDRBUS_range] hold_addr;
reg [`DATABUS_range] hold_data;
 
 
initial begin // constructor sequence
Busy = `FALSE;
RegisterMemory[0] = `PRL_default;
for (i = 1; i < `REG_dim; i = i + 1) begin
RegisterMemory[i] = `WORDNP;
end
end
 
 
function IsBusy; // boolean function primitive
input required; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
function UDNisLocked; // boolean function primitive
input obbl; // input is required
if ((RegisterMemory[`PROTECTREGLOCK_addr - `REGSTART_addr] | `UDNprotect_bit) == `UDNprotect_bit)
UDNisLocked = `TRUE;
else
UDNisLocked = `FALSE;
endfunction
 
function UPisLocked; // boolean function primitive
input obbl; // input is required
UPisLocked = ((RegisterMemory[`PROTECTREGLOCK_addr - `REGSTART_addr] | `UPprotect_bit) == `UPprotect_bit) ? `TRUE : `FALSE;
endfunction
 
function isUDNaddress;
input [`ADDRBUS_range] address;
if ((address >= `UDNREGSTART_addr) && ( address <= `UDNREGEND_addr)) // Check UDN register Address Bound
isUDNaddress = `TRUE;
else isUDNaddress = `FALSE;
endfunction
 
function isUPaddress;
input [`ADDRBUS_range] address;
if ((address >= `UPREGSTART_addr) && (address <= `UPREGEND_addr)) // Check UP register Address Bound
isUPaddress = `TRUE;
else isUPaddress = `FALSE;
endfunction
 
function [`BYTE_range] ExtIndexPRL; // bit index of PRL register
input [`ADDRBUS_range] addr;
ExtIndexPRL=(addr - `ExtREGSTART_regionaddr) / `ExtREG_regiondim;
endfunction
 
function isExtLocked; // boolean function primitive
input [`ADDRBUS_range] addr; // input is required
reg [`BYTE_range] bitIndex;
begin
bitIndex = ExtIndexPRL(addr); // protect bit index of Extended Protection Register Memory
isExtLocked = !(RegisterMemory[(`ExtPROTECTREGLOCK_addr - `REGSTART_addr)][bitIndex]);
end
endfunction
 
function isExtValidAddress;
input [`ADDRBUS_range] address;
if ((address >= `ExtREGSTART_regionaddr) && (address <= `ExtREGEND_regionaddr) ) // Check ExtRegister Address Bound
isExtValidAddress = `TRUE;
else isExtValidAddress = `FALSE;
endfunction
 
task Program;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
Busy = `TRUE;
hold_addr = address[`REG_addrbitRange];
hold_data = data;
if (Info) $write("[%t] OTP Program Memory[%h]=%h\n",$time,hold_addr,data);
fork
begin : Operation
-> ErrorCheckEvent;
#`WordProgram_time RegisterMemory[hold_addr - `REGSTART_addr] = RegisterMemory[hold_addr - `REGSTART_addr] & hold_data;
-> CompleteEvent;
end
@CompleteEvent disable Operation;
join
outStatus = Status;
Busy = `FALSE;
end
endtask
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (( address < `REGSTART_addr) || ( address > `REGEND_addr)) // Check Address Bound
Status = `AddrRange_msg;
else if ( isUDNaddress(address) && UDNisLocked(1'bX) )
Status = `UDNlock_msg;
else if ((isUPaddress(address) && UPisLocked(1'bX)))
Status = `UPlock_msg;
else if ( isExtValidAddress(hold_addr) & isExtLocked(hold_addr) )
Status = `ExtREGLock_msg;
else if (Kernel.Suspended)
Status = `SuspCmd_msg;
else if (!voltOK)
Status = `InvVDD_msg;
 
if (Status != `NoError_msg)
->CompleteEvent;
else
fork : ErrorCheck
@(negedge voltOK) Status = `InvVDD_msg;
@(Status) -> CompleteEvent;
@(CompleteEvent) disable ErrorCheck;
join
end
endmodule //end ProtectRegModule
 
 
// Read Manager
// Manage the read operation
 
module ReadModule(dataOutput,address,voltOK,Info);
output [`WORD_range] dataOutput;
input [`ADDRBUS_range] address;
input voltOK;
input Info;
reg [`WORD_range] dataOutput, regRead;
reg [1:0] Mode, oldMode;
reg [`BYTE_range] Status;
 
integer i;
 
initial begin
regRead = 0;
Mode = `ReadArray_bus;
oldMode = `ReadArray_bus;
dataOutput = `DATABUS_dim'hzzzz;
end
 
task SetMode;
input [1:0] newMode;
output [`BYTE_range] Status;
begin
Status = `NoError_msg;
if (Info && (newMode!=Mode)) begin
case (newMode)
`ReadArray_bus : $display ("[%t] Device now in Read Array mode ", $time);
`ReadCFI_bus : $display ("[%t] Device now in Read CFI mode ", $time);
`ReadSignature_bus : $display ("[%t] Device now in Read Electronic Signature Mode ", $time);
`ReadStatusReg_bus : $display ("[%t] Device now in Read Status Register Mode ", $time);
default : $display ("[%t] !!!Model Error: Read mode not recognized!!!", $time);
endcase
 
oldMode=Mode;
Mode = newMode;
end
end
endtask
 
 
always @Kernel.ResetEvent begin
Mode = `ReadArray_bus;
end
 
always @(negedge Kernel.Ready) begin // Configure according to status register
Mode = `ReadStatusReg_bus;
end
 
always @Kernel.ReadEvent begin // Main execution of a read is based on an event
 
 
case (Mode)
`ReadArray_bus : begin
dataOutput = Memory_man.Get(address);
if (Info) $display("[%t] Data Read result: memory[%h]=%h", $time,address,dataOutput);
end
`ReadCFI_bus : begin
dataOutput = CFIquery_man.Get(address);
if (Info) $display("[%t] Data Read result: CFI_memory[%h]=%h", $time,address,dataOutput);
end
`ReadSignature_bus : begin
dataOutput = Signature_man.Get(address);
if (Info) $display("[%t] Read Device Identifier(addr=%h) :%h", $time,address,dataOutput);
end
 
`ReadStatusReg_bus : begin
dataOutput = SR_man.SR;
if (Info) $display("[%t] Read Status Register: %b", $time,dataOutput[`BYTE_range]);
end
 
default : $display("[%t] !!!Model Error: Read mode not recognized!!!", $time);
endcase
if ((Mode == `ReadArray_bus) && (Memory_man.IsSuspended(address) == `TRUE)) begin
dataOutput = 16'hXX;
Kernel.SetWarning(`RD_cmd,8'hXX,`SuspAcc_msg);
end
end
 
endmodule
// end Module Read
 
 
// *************************************************
//
// Status Register module :
//
// implements the Status Register of the device
//
// *************************************************
 
module StatusRegModule(Info);
input Info;
 
 
reg EraseStatus, ProgramStatus,
VpenStatus, BlockProtectionStatus, BW_status;
 
reg [`BYTE_range] Status;
 
wire [7:0] SR = {Kernel.Ready, // bit 7
Erase_man.IsSuspended(1'bX), // bit 6
EraseStatus, // bit 5
ProgramStatus, // bit 4
VpenStatus, // bit 3
Program_man.IsSuspended(1'bX) || ProgramBuffer_man.IsSuspended(1'bX), // bit 2
BlockProtectionStatus, // bit 1
BW_status}; // bit 0
wire [7:0] SR_Info = SR;
 
 
 
//-----------------
// Init
//-----------------
 
initial begin
EraseStatus=1'b0;
ProgramStatus=1'b0;
VpenStatus=1'b0;
BlockProtectionStatus=1'b0;
BW_status=1'b0;
end
 
 
always @(SR_Info) if (Kernel.Ready!=1'bZ)
if (Info) $display("[%t] Status Register Update: %b",$time, SR_Info);
 
always @(Kernel.ResetEvent) begin
Clear(Status);
end
 
 
always @(Kernel.Ready,ProtectReg_man.Busy, BuffEnhancedFactProgram_man.Busy)
begin
if (Kernel.Ready)
BW_status = `FALSE;
else
if (BuffEnhancedFactProgram_man.Busy == `TRUE)
BW_status=`TRUE;
 
end
 
always @(Kernel.ErrorEvent) begin //Update status register bits upon specific errors
#0;
case(Kernel.GetError(1'bX))
`InvVDD_msg : begin VpenStatus = `TRUE; end
`InvVPP_msg : begin VpenStatus = `TRUE; end
`BlockLock_msg : begin BlockProtectionStatus = `TRUE; end
`UDNlock_msg : begin ProgramStatus = `TRUE; end
`UPlock_msg : begin ProgramStatus = `TRUE; end
 
`ProtRegAddrRange_msg : begin
BlockProtectionStatus = `TRUE;
end
`ExtREGLock_msg : begin
BlockProtectionStatus = `TRUE;
end
 
`CmdSeq_msg : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
`AddrRange_msg : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
`AddrTog_msg : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
`PreProg_msg : begin ProgramStatus = `TRUE; end
`WrongEraseConfirm_msg : begin ProgramStatus = `TRUE; EraseStatus = `TRUE; end
`WrongBlankCheckConfirm_msg : begin
ProgramStatus = `TRUE; EraseStatus = `TRUE;
end
`BlankCheckFailed_msg : begin
EraseStatus = `TRUE;
end
`LeastAddr0: begin
ProgramStatus = `TRUE;
end
 
endcase
case(Kernel.GetCmd(4'h1))
`PG_cmd : begin ProgramStatus = `TRUE; end
`PRREG_cmd : begin ProgramStatus = `TRUE; end
`PB_cmd : begin ProgramStatus = `TRUE; end
`BLKEE_cmd : begin EraseStatus = `TRUE; end
`BL_cmd : if (Kernel.GetCmd(4'h2) == `BLconfirm_cmd) ProgramStatus = `TRUE;
`BUL_cmd : if (Kernel.GetCmd(4'h2) ==`BULconfirm_cmd) EraseStatus = `TRUE;
`BLD_cmd : if (Kernel.GetCmd(4'h2) ==`BLDconfirm_cmd) ProgramStatus = `TRUE;
`BuffEnhProgram_cmd :
if (Kernel.GetCmd(4'h2) == `BuffEnhProgramCfrm_cmd)
ProgramStatus = `TRUE;
 
endcase
end
 
task Clear;
output [`BYTE_range] Status;
begin
Status = `NoError_msg;
EraseStatus = `FALSE;
ProgramStatus = `FALSE;
VpenStatus = `FALSE;
BlockProtectionStatus = `FALSE;
BW_status = `FALSE;
end
endtask
 
endmodule // end module status register
 
 
// *************
//
// Kernel Module
//
// *************
 
module KernelModule(VDD, VDDQ, VPP, Info);
input [`Voltage_range] VDD, VDDQ, VPP;
input Info;
event CUIcommandEvent, VerifyEvent, ErrorEvent, CompleteEvent, ResetEvent, ReadEvent, ProgramCompleteEvent, EraseCompleteEvent;
 
reg voltOK, progVoltOK, eraseVoltOK, lockVoltOK, ioVoltOK, lockOverrideOK;
reg progHighVoltOK, eraseHighVoltOK;
reg [8'hFF:0] CommandDecode1;
reg [16'hFFFF:0] CommandDecode2;
reg [7:0] lastStatus, lastCmd1, lastCmd2;
 
// Device Status
 
wire Ready = (!Program_man.Busy && !ProgramBuffer_man.Busy && !BuffEnhancedFactProgram_man.Busy
&& !Erase_man.Busy && !ProtectReg_man.Busy && !BlankCheck_man.Busy);
 
 
wire Suspended = Program_man.Suspended || Erase_man.Suspended || ProgramBuffer_man.Suspended;
 
initial begin // constructor sequence
CommandDecode1 = 8'h00; // initialize decode success status variables
CommandDecode2 = 16'h0000;
end
 
 
always @(voltOK) begin
if (!voltOK) begin
$display("[%t] !ERROR: Invalid VDD Voltage.",$time);
-> ErrorEvent;
end
else
$display("[%t] VDD Voltage is OK",$time);
end
 
always @(ioVoltOK) begin
if (!ioVoltOK) begin
$display("[%t] !ERROR: Invalid VDDQ I/O voltage.", $time);
-> ErrorEvent;
end
else
$display("[%t] VDDQ Voltage is OK",$time);
end
 
always @(VDD) begin
if ((VDD < `VDDmin) | (VDD > `VDDmax))
voltOK = `FALSE;
else
voltOK = `TRUE;
end
 
 
always @(VDDQ) begin // check i/o voltage constraints
if ((VDDQ >= `VDDQmin) && (VDDQ <= `VDDQmax))
ioVoltOK = `TRUE;
else
ioVoltOK = `FALSE;
end
 
always @(VPP) begin // program/erase/lock
if ((VPP>=`VPPmin && VPP<=`VPPmax)) begin
progVoltOK = `TRUE;
eraseVoltOK = `TRUE;
lockVoltOK = `TRUE;
progHighVoltOK = `FALSE;
eraseHighVoltOK = `FALSE;
end
else if ((VPP>=`VPPHmin) && (VPP<=`VPPHmax)) begin
progVoltOK = `TRUE;
eraseVoltOK = `TRUE;
lockVoltOK = `TRUE;
progHighVoltOK = `TRUE;
eraseHighVoltOK = `TRUE;
end
else begin
progVoltOK = `FALSE;
eraseVoltOK = `FALSE;
lockVoltOK = `FALSE;
progHighVoltOK = `FALSE;
eraseHighVoltOK = `FALSE;
end
end
 
 
function [7:0] GetError;
input required;
GetError = lastStatus;
endfunction
 
function [7:0] GetCmd;
input commandNum;
GetCmd = (commandNum == 1) ? lastCmd1 : lastCmd2;
endfunction
 
task SetWarning;
input [7:0] Cmd1, Cmd2;
input [7:0] Status;
begin
Report(Cmd1,Cmd2,Status);
lastStatus = Status;
end
endtask
 
task SetError;
input [7:0] Cmd1, Cmd2;
input [7:0] ErrFlag;
begin
SetWarning(Cmd1,Cmd2,ErrFlag);
-> ErrorEvent; // Only errors set error event
end
endtask
 
 
task Report;
input [7:0] Cmd1, Cmd2;
input [7:0] Status;
begin
lastStatus = Status;
lastCmd1 = Cmd1;
lastCmd2 = Cmd2;
if ((lastStatus != `NoError_msg) || Info) begin //Display error .
$write("[%t] ",$time);
case(Status)
`NoError_msg : begin $write(" Command Completion Successful "); end
`CmdSeq_msg : begin $write(" !Error: [Invalid Command]\n Sequence Command Unknown"); -> ErrorEvent; end
`SuspCmd_msg : begin $write(" !Error: [Invalid Command]\n Cannot execute this command during suspend"); -> ErrorEvent; end
`SuspAcc_msg : begin $write(" !Error: [Invalid Command]\n Cannot access this address due to suspend"); -> ErrorEvent; end
`SignAddrRange_msg : begin $write(" !Error: [Invalid Address]\n Signature Address out of range"); end
`CFIAddrRange_msg : begin $write(" !Error: [Invalid Address]\n CFI Address out of range"); end
`AddrRange_msg : begin $write(" !Error: [Invalid Address]\n Address out of range"); -> ErrorEvent; end
`AddrTog_msg : begin $write(" !Error: [Program Buffer]\n Cannot change block address during command sequence"); -> ErrorEvent; end
`BuffSize_msg : begin $write(" !Error: [Program Buffer]\n Buffer size is too large (Max Size is %d) ",`ProgramBuffer_dim); -> ErrorEvent; end
`InvVDD_msg : begin $write(" !Error: [Invalid Supply]\n Voltage Supply must be: VDD>VDDmin and VDD<VDDmax "); -> ErrorEvent; end
`InvVPP_msg : begin $write(" !Error: [Invalid Program Supply]\n Program Supply Voltage must be: VPP>VPPHmin and VPP<VPPHmax for this Operation"); -> ErrorEvent; end
`ByteToggle_msg : begin $write(" !Error: [BYTE_N Toggled]\n Cannot toggle BYTE_N while busy"); -> ErrorEvent; end
`PreProg_msg : begin $write(" !Error: [Program Failure]\n Program Failure due to cell failure"); -> ErrorEvent; end
`UDNlock_msg : begin $write(" !Error: [Program Failure]\n Unique Device Number Register is locked"); -> ErrorEvent; end
`UPlock_msg : begin $write(" !Error: [Program Failure]\n User Programmable Register is locked"); -> ErrorEvent; end
`ExtREGLock_msg : begin $write(" !Error: [Program Failure]\n Extended User Programmable OTP is locked"); -> ErrorEvent; end
`NoUnLock_msg : begin $write(" #Warning: [Locked Down Warning]\n Invalid UnLock Block command in Locked-Down Block"); end
`SuspAccWarn_msg : begin $write(" #Warning: [Invalid Access]\n It isn't possible access this address due to suspend"); end
`BlockLock_msg : begin $write(" !Error: [Locked Error]\n Cannot complete operation when the block is locked "); -> ErrorEvent; end
`BlkBuffer_msg : begin $write(" !Error: [Program Buffer] Program Buffer cannot cross block boundary"); end
`AddrCFI_msg : begin $write(" #Warning: [Invalid CFI Address]\n CFI Address out of range"); end
`NoBusy_msg : begin $write(" #Warning: [NO Busy]\n Device is not Busy"); end
`NoSusp_msg : begin $write(" #Warning: [NO Suspend]\n Nothing previus suspend command"); end
`Suspend_msg : begin $write(" Suspend of "); end
`WrongEraseConfirm_msg : begin
$write(" !Error: [Wrong Erase Confirm Code ");
-> ErrorEvent;
end
`LeastAddr0 : begin
$write(" !Error: [Program Failure]\n Least Significative bit [%2d downto 0] of Start Address must be 0",`ProgramBuffer_addrDim-1);
-> ErrorEvent;
end
`WrongBlankCheckConfirm_msg : begin
$write(" !Error: [Confirm Code] Wrong Blank Check Confirm Code ");
-> ErrorEvent;
end
 
`WrongBlankCheckBlock: begin
$write(" !Error: [Blank Check Failure]\n The block must be a main block");
-> ErrorEvent;
end
 
`BlankCheckFailed_msg : begin $write(" !Error: [Blank Check]\n Blank Check Failed ");
-> ErrorEvent;
end
 
default : begin $write(" !ERROR: [Unknown error]\n Flag=%h, cmd1=%hh, cmd2=%hh",Status,Cmd1,Cmd2); -> ErrorEvent; end
endcase
case (Cmd1)
16'hXX : $display(" !Error: [General Error}\n Error not defined");
`RD_cmd : $display(" { Read Array }");
`RSR_cmd : $display(" { Read Status Register }");
`RSIG_cmd : $display(" { Read Electronic Signature }");
`RCFI_cmd : $display(" { Read CFI }");
`PG_cmd : $display(" { Program }");
`BuffEnhProgram_cmd : $display(" { Buffer Enhanced Factory Program }");
 
`SCR_cmd | `BL_cmd | `BUL_cmd | `BLD_cmd
: begin
if (Cmd2 == `SCRconfirm_cmd) $display(" { Set Configuration Register }");
if (Cmd2 == `BLconfirm_cmd) $display(" { Block Lock }");
if (Cmd2 == `BULconfirm_cmd) $display(" { Block UnLock }");
if (Cmd2 == `BLDconfirm_cmd) $display(" { Block Lock-Down }");
end
`PER_cmd : $display(" { Program/Erase Resume }");
`PRREG_cmd : $display(" { Protection Register Command }");
`BLKEE_cmd : $display(" { Block Erase }");
`BLNKCHK_cmd : $display(" { Blank Check }");
`CLRSR_cmd : $display(" { Clear Status Register }");
`PES_cmd : $display(" { Program/Erase Suspend }");
`PB_cmd : $display(" { Write to Buffer and Program }");
default : $display(" {unknown command: %hh}", Cmd1);
endcase
end
end
endtask
 
task CheckTime;
input [8*6:1] tstr;
input [31:0] tdiff, tprev;
begin
if ($time - tprev < tdiff) begin
$display ("[%t] !ERROR: %0s timing constraint violation: %0d-%0d < %0dns ", $time, tstr, $time, tprev, tdiff);
-> ErrorEvent;
end
end
endtask
 
endmodule // end module Kernel
 
 
 
 
 
module x28fxxxp30(A, DQ, W_N, G_N, E_N, L_N, K, WAIT, WP_N, RP_N, VDD, VDDQ, VPP, Info);
 
// Signal Bus
input [`ADDRBUS_dim-1:0] A; // Address Bus
inout [`DATABUS_dim-1:0] DQ; // Data I/0 Bus
// Control Signal
input W_N; // Write Enable
input G_N; // Output Enable
input E_N; // Chip Enable
input L_N; // Latch Enable
input K; // Clock
input WP_N; // Write Protect
input RP_N; // Reset/Power-Down
 
// Voltage signal rappresentad by integer Vector which correspond to millivolts
input [`Voltage_range] VDD; // Supply Voltage
input [`Voltage_range] VDDQ; // Input/Output Supply Voltage
input [`Voltage_range] VPP; // Optional Supply Voltage for fast Program & Erase
 
// Others Signal
output WAIT; // Wait
reg wait_;
assign WAIT = wait_;
input Info; // Enable/Disable Information of the operation in the memory
wire CLK;
assign CLK = (K ~^ ConfigReg_man.isRisingClockEdge);
reg CLOCK;
// === Internal Signal ===
// Chip Enable
wire CE_N = E_N & Kernel.voltOK & RP_N;
 
// Output Enable
wire OE_N = G_N | CE_N | !Kernel.ioVoltOK | !RP_N;
// Write Enable
wire WE_N = W_N | CE_N;
 
// Latch Enable
 
wire LE_N = L_N | CE_N;
// === Bus Latch ===
// Data Bus
wire [`DATABUS_dim-1:0] DataBusIn;
wire [`DATABUS_dim-1:0] DataBurst;
 
// read burst is in wait state
wire isWait;
 
// Address Bus
reg [`ADDRBUS_dim - 1:0] AddrBusIn;
 
// Status
//aggiunti stati buffenha...e blank....
reg [`BYTE_range] KernelStatus, ReadStatus, EraseStatus, ProgramStatus, BuffEnhancedProgramStatus,
LockStatus, ConfigStatus, BufferStatus,BlankCheckStatus,ProgramBufferStatus,
SuspendStatus, ResumeStatus, ClearSRStatus, ProtectRegStatus;
 
 
reg [`BYTE_range] status=`Free_pes;
 
//address latching in read operation
always @(negedge LE_N) if (W_N==`HIGH) begin
if (KernelStatus == `READY && ConfigReg_man.isASynchronous)
@(posedge LE_N) begin
if (L_N)
 
AddrBusIn = A; // AddressBus has been Latched
 
end
end
 
always @(negedge LE_N) if (W_N==`HIGH) begin :latching_a
if (KernelStatus == `READY) begin
if(ConfigReg_man.isSynchronous)
fork
begin : L_Address
 
@(posedge LE_N) if (L_N) begin
AddrBusIn = A; // AddressBus has been Latched
disable K_Address;
 
end
end
begin : K_Address
 
@(posedge CLK) begin
 
AddrBusIn = A; // AddressBus has been Latched
disable L_Address;
end
end
join
 
end
end
 
 
always @(negedge WE_N) begin
if (KernelStatus==`READY)
@(posedge WE_N) begin
if(OE_N==`HIGH)
AddrBusIn = A; // AddressBus has been Latched
 
end
end
 
integer i;
integer n_block;
 
// Wait Driver
time timeWaitDriver,timeWaitDriverZ;
 
reg PB_init=0;
reg P_init=0;
reg BP_init=0;
reg Prog_init=0;
 
always @(PB_init,P_init,BP_init) begin
Prog_init=(PB_init ||P_init || BP_init);
end
 
wire [`BYTE_range] AccessTime;
 
// ****************
//
// Modules Istances
//
// ****************
 
DataErrorModule DataError_man(); // Check for errors on UserData.h
 
CUIdecoder1 ReadArray_Command (DQ[`LOW_range], "Read Array ", `RD_cmd, (Kernel.Ready && !Prog_init), Info),
ReadSR_Command (DQ[`LOW_range], "Read Status Register ", `RSR_cmd, !Prog_init, Info),
ReadSign_Command (DQ[`LOW_range], "Read Electronic Signature ", `RSIG_cmd, (Kernel.Ready && !Prog_init), Info),
ReadCFI_Command (DQ[`LOW_range], "Read CFI ", `RCFI_cmd, (Kernel.Ready && !Prog_init), Info),
Program_Command (DQ[`LOW_range], "Program ", `PG_cmd, (Kernel.Ready && !Prog_init), Info),
 
ProgramBuffer_Command (DQ[`LOW_range], "Program Buffer ", `PB_cmd, (Kernel.Ready && !Prog_init), Info),
ProgramReg_Command (DQ[`LOW_range], "Protection Register Program ", `PRREG_cmd, (Kernel.Ready && !Prog_init), Info),
Resume_Command (DQ[`LOW_range], "Resume ", `PER_cmd, (Kernel.Ready && Kernel.Suspended), Info),
BlockErase_Command (DQ[`LOW_range], "Block Erase ", `BLKEE_cmd,(Kernel.Ready && !Prog_init), Info),
ClearSR_Command (DQ[`LOW_range], "Clear Status Register ", `CLRSR_cmd, (Kernel.Ready && !Prog_init), Info),
 
BlankCheck_Command (DQ[`LOW_range], "Blank Check ", `BLNKCHK_cmd, (Kernel.Ready && !Prog_init), Info),
BuffEnhactoryProgram_Command (DQ[`LOW_range], "Buffer Enh.Factory Program [Setup]", `BuffEnhProgram_cmd,(Kernel.Ready && !Prog_init), Info);
 
 
CUIdecoder_Busy1 Suspend_Command (DQ[`LOW_range], "Suspend ", `PES_cmd, !Kernel.Ready, Info);
 
CUIdecoder2 BlockLock_Command (DQ[`LOW_range], "Block Lock ", `BL_cmd, `BLconfirm_cmd, (Kernel.Ready && !Prog_init), Info),
BlockUnlock_Command (DQ[`LOW_range], "Block UnLock ", `BUL_cmd, `BULconfirm_cmd, (Kernel.Ready && !Prog_init), Info),
BlockLockDown_Command (DQ[`LOW_range], "Block Lock-Down ", `BLD_cmd, `BLDconfirm_cmd, (Kernel.Ready && !Prog_init), Info),
SetConfigReg_Command (DQ[`LOW_range], "Set Configuration Register ", `SCR_cmd, `SCRconfirm_cmd, (Kernel.Ready && !Prog_init), Info);
 
KernelModule Kernel (VDD, VDDQ, VPP, Info);
ReadModule Read_man (DataBusIn, AddrBusIn, Kernel.ioVoltOK, Info);
OutputBufferModule OutputBuffer_man (DataBusIn, DataBurst, DQ, OE_N);
StatusRegModule SR_man (Info);
MemoryModule Memory_man (Info);
ProgramModule Program_man (AddrBusIn, DQ, Kernel.progVoltOK, Kernel.progHighVoltOK, Info);
 
BuffEnhancedFactProgramModule BuffEnhancedFactProgram_man(AddrBusIn, DQ, Kernel.progVoltOK, Kernel.progHighVoltOK, Info);
ProtectRegModule ProtectReg_man (AddrBusIn, DQ, Kernel.progVoltOK, Info);
EraseModule Erase_man (AddrBusIn, DQ, Kernel.eraseVoltOK, Kernel.progHighVoltOK, Info);
 
 
BlankCheckModule BlankCheck_man (AddrBusIn, DQ, Kernel.eraseVoltOK, Kernel.progHighVoltOK, Info);
 
BlockLockModule BlockLock_man (AddrBusIn, WP_N, RP_N, Info);
ProgramBufferModule ProgramBuffer_man (AddrBusIn, DQ, Kernel.progVoltOK, Info);
SignatureModule Signature_man (); // , `FALSE);
CFIqueryModule CFIquery_man (); // , `TRUE);
ConfigRegModule ConfigReg_man (AddrBusIn,Info); // implements the Configuration Register
BurstModule Burst_man (AddrBusIn, DataBurst, isWait, CLK, CLOCK, L_N, G_N,W_N, Info);
 
BankLib BankLib_man ();
TimingDataModule TimingData_man ();
TimingLibModule TimingLib_man (A,DQ,W_N,G_N,E_N,L_N,WP_N,K,VPP);
 
initial begin
 
$timeformat(-9, 0, " ns", 12); // Format time displays to screen
-> Kernel.ResetEvent; // Reset Device
KernelStatus = `BUSY; // Device is Busy
$display ("[%t] --- Device is Busy (start up time) --- ", $time);
#(TimingData_man.tVDHPH) KernelStatus = `READY; // End of Start-Up Time
$display ("[%t] --- Device is Ready (end of start-up time) --- ", $time);
 
AddrBusIn = `ADDRBUS_dim'hZ;
 
wait_ = 1'hZ;
CLOCK = 1'b0;
end
 
// Recognize command input
always @(negedge WE_N) begin
if (KernelStatus==`READY)
@(posedge WE_N) begin
 
-> Kernel.CUIcommandEvent; // new command has been written into Kernel.
 
end
end
 
// Check error
always @(Kernel.CUIcommandEvent) begin : Timeout
#3
-> Kernel.ErrorEvent;
disable Verify;
end
 
// Verify command issued
always @(Kernel.CUIcommandEvent) begin : Verify
@(Kernel.VerifyEvent)
 
disable Timeout;
end
 
// Default to Read Array command
always @(negedge OE_N) begin
if (OE_N == `LOW && (ConfigReg_man.isASynchronous)) begin
if (L_N==0) AddrBusIn=A;
#1
-> Kernel.ReadEvent;
end
end
 
// Page Read
always @(A) begin
if ((OE_N == `LOW) && (A !== `ADDRBUS_dim'hZ) && (A !== `ADDRBUS_dim'hx) && (ConfigReg_man.isASynchronous)) begin
AddrBusIn = A;
#0 -> Kernel.ReadEvent;
end
end
 
 
// Reset the Kernel
always @(negedge RP_N) begin
-> Kernel.ResetEvent;
if (Info) $display ("[%t] Device has been reset ", $time);
KernelStatus = `BUSY;
@(posedge RP_N) KernelStatus = `READY;
end
 
// ----- Recognize Command Input -----
always @(Kernel.CommandDecode1[`RD_cmd]) if (KernelStatus==`READY) begin // Read Array
Read_man.SetMode(`ReadArray_bus, ReadStatus);
Kernel.Report(`RD_cmd, 8'hXX, ReadStatus);
#1 -> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode1[`RSR_cmd]) if (KernelStatus==`READY) begin // Read Status Register
Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
Kernel.Report(`RSR_cmd, 8'hXX, ReadStatus);
#1 -> Kernel.CompleteEvent;
end
 
 
always @(Kernel.CommandDecode1[`RSIG_cmd]) if (KernelStatus==`READY ) begin // Read Electronic Signature
Read_man.SetMode(`ReadSignature_bus, ReadStatus);
Kernel.Report(`RSIG_cmd, 8'hXX, ReadStatus);
#1 -> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode1[`RCFI_cmd]) if (KernelStatus==`READY) begin // Read CFI
Read_man.SetMode(`ReadCFI_bus, ReadStatus);
Kernel.Report(`RCFI_cmd, 8'hXX, ReadStatus);
#1 -> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode1[`PG_cmd]) if (KernelStatus==`READY) begin // Program
P_init=1;
@Kernel.CUIcommandEvent
#1 -> Kernel.VerifyEvent;
Program_man.Program(ProgramStatus);
Kernel.Report(`PG_cmd, 8'hXX, ProgramStatus);
-> Kernel.CompleteEvent;
P_init=0;
end
 
 
always @(Kernel.CommandDecode1[`PRREG_cmd]) if (KernelStatus==`READY) begin // Protection Register Program
@Kernel.CUIcommandEvent
#1 -> Kernel.VerifyEvent;
ProtectReg_man.Program(ProtectRegStatus);
Kernel.Report(`PRREG_cmd, 8'hXX, ProtectRegStatus);
-> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode1[`PES_cmd]) if (KernelStatus==`READY) begin // Suspend
if (Program_man.IsBusy(1'bX))
Program_man.Suspend(SuspendStatus);
else if (ProgramBuffer_man.IsBusy(1'bX))
ProgramBuffer_man.Suspend(SuspendStatus);
else if (Erase_man.IsBusy(1'bX))
Erase_man.Suspend(SuspendStatus);
-> Kernel.CompleteEvent;
end
 
 
always @(Kernel.CommandDecode1[`PER_cmd]) if (KernelStatus==`READY) begin // Program/Erase Resume
ResumeStatus = `NoError_msg;
if (Program_man.IsSuspended(1'bX)) begin
Program_man.Resume(ProgramStatus);
Kernel.Report(`PG_cmd, 8'hXX, ProgramStatus);
end
else if (ProgramBuffer_man.IsSuspended(1'bX)) begin
ProgramBuffer_man.Resume(BufferStatus);
Kernel.Report(`PB_cmd, 8'hXX, BufferStatus);
end
else if (Erase_man.IsSuspended(1'bX)) begin
Erase_man.Resume(EraseStatus);
Kernel.Report(`BLKEE_cmd, 8'hXX, EraseStatus);
end
else
ResumeStatus = `NoSusp_msg;
Kernel.Report(`PER_cmd, 8'hXX, ResumeStatus);
-> Kernel.CompleteEvent;
 
end
 
always @(Kernel.CommandDecode1[`BLKEE_cmd]) if (KernelStatus==`READY) begin // Block Erase
Read_man.SetMode(`ReadStatusReg_bus,ReadStatus);
EraseStatus=`NoError_msg;
@Kernel.CUIcommandEvent
Erase_man.checkConfirm(EraseStatus);
#1 -> Kernel.VerifyEvent;
if (EraseStatus != `NoError_msg)
Kernel.Report(`BLKEE_cmd, `BLKEEconfirm_cmd, EraseStatus);
else
begin
Erase_man.BlockErase(EraseStatus);
Kernel.Report(`BLKEE_cmd, `BLKEEconfirm_cmd , EraseStatus);
-> Kernel.CompleteEvent;
end
end
 
always @(Kernel.CommandDecode1[`CLRSR_cmd]) if (KernelStatus==`READY) begin // Clear Status Register
SR_man.Clear(ClearSRStatus);
Kernel.Report(`CLRSR_cmd, 8'hXX, ClearSRStatus);
#1 -> Kernel.CompleteEvent;
end
 
 
//aggiunta ************************************************
// PB Fast Program Commands
always @(Kernel.CommandDecode1[`PB_cmd]) if (KernelStatus==`READY) begin // Write to Program and Buffer
ProgramBufferStatus = `NoError_msg;
PB_init=1;
Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
@Kernel.CUIcommandEvent
ProgramBuffer_man.SetCount(ProgramBufferStatus);
#1 -> Kernel.VerifyEvent;
if (ProgramBufferStatus == `NoError_msg) begin
for (i=1; i <= ProgramBuffer_man.GetCount(1'bX); i=i+1) begin : GetData
@Kernel.CUIcommandEvent
#1;
 
ProgramBuffer_man.Load(ProgramBufferStatus);
#1 -> Kernel.VerifyEvent;
if (ProgramBufferStatus != `NoError_msg)
disable GetData;
end
@Kernel.CUIcommandEvent
if (DQ[`BYTE_range] != `PBcfm_cmd)
ProgramBufferStatus = `CmdSeq_msg;
else begin
#1 -> Kernel.VerifyEvent;
ProgramBuffer_man.Program(ProgramBufferStatus);
end
end
Kernel.Report(`PB_cmd, 8'hXX, ProgramBufferStatus);
->Kernel.CompleteEvent;
PB_init=0;
end
//*************************************************************************
 
always @(Kernel.CommandDecode2[{`BL_cmd,`BLconfirm_cmd}]) if (KernelStatus==`READY) begin // Block Lock
BlockLock_man.Lock(LockStatus);
Kernel.Report(`BL_cmd, `BLconfirm_cmd, LockStatus);
-> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode2[{`BUL_cmd,`BULconfirm_cmd}]) if (KernelStatus==`READY) begin // Block UnLock
BlockLock_man.UnLock(LockStatus);
Kernel.Report(`BUL_cmd,`BULconfirm_cmd, LockStatus);
-> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode2[{`BLD_cmd,`BLDconfirm_cmd}]) if (KernelStatus==`READY) begin // Block Lock-Down
BlockLock_man.LockDown(LockStatus);
Kernel.Report(`BLD_cmd,`BLDconfirm_cmd, LockStatus);
-> Kernel.CompleteEvent;
end
 
always @(Kernel.CommandDecode2[{`SCR_cmd,`SCRconfirm_cmd}]) if (KernelStatus==`READY) begin // Set Configuration Register
ConfigReg_man.putConfigReg(ConfigStatus);
Kernel.Report(`SCR_cmd,`SCRconfirm_cmd, ConfigStatus);
-> Kernel.CompleteEvent;
end
 
 
// BC
always @(Kernel.CommandDecode1[`BLNKCHK_cmd]) if (KernelStatus==`READY) begin // Blank Check
BlankCheckStatus=`NoError_msg;
Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
@Kernel.CUIcommandEvent
BlankCheck_man.checkConfirm(BlankCheckStatus);
#1 -> Kernel.VerifyEvent;
if (BlankCheckStatus != `NoError_msg) begin
Kernel.Report(`BLNKCHK_cmd, `BLNKCHKconfirm_cmd, BlankCheckStatus);
end else
begin
BlankCheck_man.BlankCheck(BlankCheckStatus);
Kernel.Report(`BLNKCHK_cmd, `BLNKCHKconfirm_cmd, BlankCheckStatus);
end
-> Kernel.CompleteEvent;
 
end
// BEFP
always @(Kernel.CommandDecode1[`BuffEnhProgram_cmd]) if (KernelStatus==`READY) begin // Buffer Enhanced Factory Program: Setup Phase
Read_man.SetMode(`ReadStatusReg_bus, ReadStatus);
BP_init=1;
@Kernel.CUIcommandEvent
#1 -> Kernel.VerifyEvent;
if (Kernel.Suspended | !Kernel.Ready)
BuffEnhancedProgramStatus = `SuspCmd_msg;
else begin
if (DQ[`LOW_range]!=`BuffEnhProgramCfrm_cmd)
BuffEnhancedProgramStatus=`CmdSeq_msg;
else begin
if (Info) $display("[%t] Command Issued: Buffer Enh.Factory Program [Confirm]",$time);
BuffEnhancedFactProgram_man.Setup(BuffEnhancedProgramStatus);
if (BuffEnhancedProgramStatus == `NoError_msg) begin
while (BuffEnhancedProgramStatus == `NoError_msg) begin // Loop Program - Enhanced Factory Program: Program Phase
if (Info) $display("[%t] Enhanced Factory Program -> Load Phase",$time);
while (BuffEnhancedProgramStatus == `NoError_msg ) begin // Loop Load - Enhanced Factory Program: Load Phase
@Kernel.CUIcommandEvent
#1 -> Kernel.VerifyEvent;
BuffEnhancedFactProgram_man.Load(BuffEnhancedProgramStatus);
end
if (BuffEnhancedProgramStatus==`ProgramPHASE_BEFP_msg) begin
BuffEnhancedFactProgram_man.Program(BuffEnhancedProgramStatus);
end
end
BuffEnhancedFactProgram_man.Exit(BuffEnhancedProgramStatus);
end
end
if (BuffEnhancedProgramStatus == `ExitPHASE_BEFP_msg)
BuffEnhancedProgramStatus = `NoError_msg;
end
Kernel.Report(`BuffEnhProgram_cmd,`BuffEnhProgramCfrm_cmd, BuffEnhancedProgramStatus);
-> Kernel.CompleteEvent;
BP_init=0;
end
 
 
 
//***********************************************************
 
// Decode Delays for Page Mode Reads
 
//******************************************************
 
// Page mode
always
begin :nopage
@(A[`ADDRBUS_dim - 1:4])
disable page;
 
OutputBuffer_man.SetValid(TimingData_man.tAVQV);
end
 
// Page mode
always
begin :page
@(A[3:0]) //pagina di 16 words
OutputBuffer_man.SetValid(TimingData_man.tAVQV1);
end
 
 
// Output Buffer delays
 
always @(negedge E_N) begin
OutputBuffer_man.SetX(TimingData_man.tELQX);
OutputBuffer_man.SetValid(TimingData_man.tELQV);
 
end
 
always @(negedge G_N) begin
#0;
OutputBuffer_man.SetX(TimingData_man.tGLQX);
OutputBuffer_man.SetValid(TimingData_man.tGLQV);
 
end
 
always @(posedge CLK) begin
CLOCK = !CLOCK;
end
 
always @(negedge CLK) begin
CLOCK = !CLOCK;
end
 
 
 
reg waiting=1;
 
always @(posedge G_N) begin
 
waiting=1;
 
end
 
 
 
always @(CLK) begin
 
if ((!G_N) && (CE_N == `LOW) && (ConfigReg_man.isSynchronous) && (CLK)) begin
 
if (ConfigReg_man.isWaitBeforeActive && Burst_man.firstEOWL && waiting) begin
OutputBuffer_man.SetX(TimingData_man.tKHQX);
@(posedge (CLK))
OutputBuffer_man.SetX(TimingData_man.tKHQX);
OutputBuffer_man.SetValid(TimingData_man.tKHQV);
waiting=0;
 
end else begin
OutputBuffer_man.SetX(TimingData_man.tKHQX);
OutputBuffer_man.SetValid(TimingData_man.tKHQV);
end
end
end
 
always @(negedge L_N) if(W_N==`HIGH)begin
if (ConfigReg_man.isSynchronous && CE_N==`LOW) begin
OutputBuffer_man.SetValid(TimingData_man.tLLQV);
 
end
end
 
 
always @(RP_N) begin
if (RP_N == `HIGH)
OutputBuffer_man.SetValid(TimingData_man.tPHWL);
end
 
always @(posedge CE_N) begin
OutputBuffer_man.SetZ(TimingData_man.tEHQZ);
end
 
always @(posedge G_N) begin
OutputBuffer_man.SetZ(TimingData_man.tGHQZ);
OutputBuffer_man.SetZ(TimingData_man.tGHTZ);
 
end
 
 
 
////////////////////////////////
always @(CE_N) begin
if (CE_N == `LOW && W_N==`HIGH && G_N == `LOW) begin
if (ConfigReg_man.isSynchronous)
wait_ = #(TimingData_man.tELTV) ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tELTV) !ConfigReg_man.isWaitPolActiveHigh;
end
else
wait_ = #(TimingData_man.tEHTZ) 1'hZ;
end
 
always @(G_N) begin
if (G_N == `LOW && CE_N == `LOW && W_N==`HIGH) begin
if (ConfigReg_man.isSynchronous) begin
wait_ = #(TimingData_man.tGLTV) ConfigReg_man.isWaitPolActiveHigh;
end else begin
wait_ = #(TimingData_man.tGLTV) !ConfigReg_man.isWaitPolActiveHigh;
end
end
else begin if (G_N == `HIGH )
wait_ = #(TimingData_man.tGHTZ) 1'hZ;
disable Burst_man.pollingBurst;
end
end
 
 
 
 
always @(isWait) begin
 
if ((CE_N == `LOW) && (G_N == `LOW) && ConfigReg_man.isSynchronous ) begin
if (CLK) begin
if (isWait == `LOW ) begin
if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
end else begin
if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
end
 
end else
fork
begin
@(posedge(CLK))
if (isWait == `LOW) begin
if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
end else begin
if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
end
end
 
begin
@(isWait)
if (CLK) begin
if (isWait == `LOW) begin
if(!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) ConfigReg_man.isWaitPolActiveHigh;
end else begin
if (!Burst_man.nWait) wait_ = #(TimingData_man.tKHTV) !ConfigReg_man.isWaitPolActiveHigh;
else wait_ = #(TimingData_man.tKHTX) !ConfigReg_man.isWaitPolActiveHigh;
end
 
end
end
 
join
end else if (G_N == `HIGH && isWait == `HIGH && W_N==`HIGH)
$display("%t --- WARNING --- WAIT should be deasserted but OE# is not yet LOW. Please check the timings!",$time);
end
 
 
endmodule
 
 
 
// *********************************
//
// Burst module :
//
// manage the Read Burst operation
//
// *********************************
 
module BurstModule(address, data, ISWAIT, CLK, CLOCK, L_N, G_N, W_N, Info);
input [`ADDRBUS_range] address;
output [`WORD_range] data;
reg [`WORD_range] data;
 
input CLK;
input CLOCK;
input L_N;
input G_N;
input W_N;
output ISWAIT;
input Info;
 
reg [`ADDRBUS_range] Start_address, Sync_address,new_address;
reg EnableBurst, isValidData, IsNowWait, endSingleSynchronous;
reg [2:0] incLSBaddress, incMSBaddress, temp_address;
 
wire isSingleSynchronous = (Read_man.Mode != `ReadArray_bus) ? `TRUE : `FALSE;
 
integer WaitState,nWait,nRead,xLatency;
//aggiunta per il calcolo degli nwait
integer boundary,offset;
reg firstEOWL;
 
initial begin // constructor sequence
Start_address = `ADDRBUS_dim'h000000;
EnableBurst = `FALSE;
endSingleSynchronous = `FALSE;
data = 16'hZZ;
nWait = 0;
IsNowWait = `FALSE;
isValidData = `FALSE;
xLatency=0;
nRead=0;
WaitState=0;
firstEOWL=0;
end
 
always @(G_N) if (G_N==`TRUE) begin
IsNowWait = `FALSE;
isValidData = `FALSE;
EnableBurst = `FALSE;
endSingleSynchronous = `FALSE;
data = 16'hZZ;
nWait = 0;
xLatency=0;
nRead=0;
WaitState=0;
firstEOWL=0;
end
 
 
always @(isValidData) begin
case (isValidData)
 
1: if (!ConfigReg_man.isWaitBeforeActive) begin
IsNowWait = `TRUE;
end
 
0: begin if (!ConfigReg_man.isWaitBeforeActive)
IsNowWait = `FALSE;
 
end
endcase
end
 
 
assign ISWAIT = (IsNowWait) ? `TRUE : `FALSE;
 
 
always @(negedge L_N) if(W_N==`HIGH) begin : pollingBurst
fork : pollingBurst
 
begin: L_lacthing
@(posedge L_N) if (ConfigReg_man.isSynchronous) begin
#1;
Start_address = address;
Sync_address = address;
firstEOWL=0;
disable K_lacthing;
@(posedge CLK) begin
 
case(ConfigReg_man.BurstLength)
 
0: begin
boundary =16;
offset = address[3:0];
end
16:begin
boundary =16;
offset = address[3:0];
end
 
8: begin
boundary =8;
offset = address[2:0];
end
 
 
4:begin
boundary =4;
offset = address[1:0];
end
endcase
xLatency = ConfigReg_man.Xlatency;
WaitState = xLatency - (boundary - offset);
if (WaitState < 0) WaitState =0;
nWait = 0;
EnableBurst = `TRUE;
data = 16'hXX;
nRead = 0;
isValidData = `FALSE;
endSingleSynchronous=`FALSE;
disable pollingBurst;
end
end
else EnableBurst = `FALSE;
end
 
begin: K_lacthing
@(posedge CLK) if (ConfigReg_man.isSynchronous && L_N==`LOW) begin
#1;
Start_address = address;
Sync_address = address;
firstEOWL=0;
disable L_lacthing;
 
@(posedge CLK) begin
 
case(ConfigReg_man.BurstLength)
 
0: begin
boundary =16;
offset = address[3:0];
end
16:begin
boundary =16;
offset = address[3:0];
end
 
8: begin
boundary =8;
offset = address[2:0];
end
 
 
4:begin
boundary =4;
offset = address[1:0];
end
endcase
xLatency = ConfigReg_man.Xlatency;
WaitState = xLatency - (boundary - offset); //
if (WaitState < 0) WaitState =0;
nWait = 0;
EnableBurst = `TRUE;
data = 16'hXX;
nRead = 0;
isValidData = `FALSE;
endSingleSynchronous=`FALSE;
disable pollingBurst;
end
end
else EnableBurst = `FALSE;
end
join
$display(" %t address=%h",$time,Start_address);
end
 
 
always @(posedge (CLK)) if(G_N==`LOW) begin
if (EnableBurst) begin
if (xLatency == 2 && ConfigReg_man.isWaitBeforeActive)
IsNowWait = `TRUE;
 
if (xLatency == 1) begin
isValidData = `TRUE;
if (offset == 4'd15 && ConfigReg_man.isWaitBeforeActive && WaitState!=0 && (ConfigReg_man.isNoWrapBurst || ConfigReg_man.BurstLength == 5'd00)) begin
IsNowWait = `FALSE;
 
end
 
end
if (xLatency) xLatency = xLatency - 1; //vuol dire se xLatency e' >1 o diverso da zero????
end
end
 
always @(nRead) begin
if (isSingleSynchronous && nRead>=1) begin //End of SingleBurstRead???
endSingleSynchronous=`TRUE;
isValidData = `FALSE;
end
if((offset + nRead) == 4'd15 && ConfigReg_man.isWaitBeforeActive && WaitState!=0 && (ConfigReg_man.isNoWrapBurst || ConfigReg_man.BurstLength == 5'd00)) begin
IsNowWait = `FALSE;
 
end
end
 
 
always @(CLK) begin
if (EnableBurst) begin
if (!xLatency) begin // burst is ongoing(after xLatency)
if (!G_N) begin
if (nWait || endSingleSynchronous) data = `DATABUS_dim'hXXXX; //Wait State;
else begin // Read is Possible!
// -- \\
case (Read_man.Mode)
`ReadArray_bus : begin
data = Memory_man.Get(Sync_address);
@(posedge (CLK)) if (Info && !G_N) $write("[%t] Burst Read: Memory[%h]=%h\n",$time,Sync_address,data);
end
`ReadCFI_bus : begin
data = CFIquery_man.Get(Sync_address);
@(posedge (CLK)) if (Info && !G_N) $write("[%t] Burst Read: CFIMemory[%h]=%h\n",$time,Sync_address,data);
end
`ReadSignature_bus : begin
data = Signature_man.Get(Sync_address);
@(posedge (CLK)) if (Info && !G_N) $write("[%t] Burst Read: Electronic Signature[%h]=%h\n",$time,Sync_address,data);
end
`ReadStatusReg_bus : begin
data = SR_man.SR;
@(posedge (CLK)) if (Info && !G_N) $write("[%t] Burst Read: StatusRegister: %b\n",$time,data[`BYTE_range]);
end
default : $display("[%t] !!!Model Error: Read mode not recognized!!!", $time);
endcase
// -- \\
end
if((CLK)) begin
if (!nWait) // Wait State??? if no calculate next address
begin
new_address = Sync_address + 1;
nRead = nRead + 1;
end
if (!isSingleSynchronous) begin
 
// Calcultate Address for Sequential and Wrap Burst
if ((ConfigReg_man.BurstLength != 5'd00) && ConfigReg_man.isWrapBurst) begin
case (ConfigReg_man.BurstLength_bit)
3'd2: new_address = {Sync_address[`ADDRBUS_dim - 1 : 2], new_address[1:0] };
3'd3: new_address = {Sync_address[`ADDRBUS_dim - 1 : 3], new_address[2:0] };
3'd4: new_address = {Sync_address[`ADDRBUS_dim - 1 : 4], new_address[3:0] };
endcase
end
// Calculate Next Wait State
if (ConfigReg_man.isNoWrapBurst || (ConfigReg_man.BurstLength == 5'd00) ) //Calculate WAIT STATE
if ((new_address[3:0]==4'd0) && (Sync_address[3:0] == 4'd15)) begin
if(!ConfigReg_man.isWaitBeforeActive) begin
 
if (nWait<WaitState && !firstEOWL) begin
nWait = nWait+1; // Another Wait State???
isValidData = `FALSE;
end else begin
nWait = 0; // end of wait state
Sync_address = new_address;
isValidData = `TRUE;
firstEOWL =1;
 
end
 
end else begin
if (nWait<WaitState-1 && !firstEOWL ) begin
nWait = nWait+1; // Another Wait State???
IsNowWait = `FALSE;
end else begin
nWait = 0; // end of wait state
Sync_address = new_address;
IsNowWait = `TRUE;
firstEOWL =1;
 
end
end
 
end
if (!nWait)
if ((nRead<ConfigReg_man.BurstLength) || (ConfigReg_man.BurstLength==5'd00) // Read Data is Over Burst Lenght???
&& !endSingleSynchronous) // end of SingleSinchronous Burst Read ???
Sync_address = new_address;
end // !isSyn
end //aggiunta
end //G_N
end // XLatency
end //Enable Burst
end
 
 
endmodule // end Burst Module
 
 
// Erase Manager
// manage the erase functionality
 
module BlankCheckModule(address, data, progVoltOK, progHighVoltOK,Info);
 
input [`WORD_range] data;
input [`ADDRBUS_range] address;
input progVoltOK, progHighVoltOK;
input Info;
 
event ErrorCheckEvent, CompleteEvent;
 
reg [`BYTE_range] Status;
reg [`ADDRBUS_range] hold_address;
reg [`BLOCKADDR_range] hold_block;
 
 
reg Busy;
integer i;
time startTime, delayTime, Erase_time;
 
initial begin // constructor sequence
Busy = `FALSE;
Erase_time = `MainBlockErase_time; //modificato
delayTime = Erase_time;
end
 
always @(progVoltOK,progHighVoltOK,address) begin
if (progHighVoltOK)
if (BankLib_man.isMainBlock(address)) Erase_time=`FastMainBlockErase_time;
else Erase_time=`FastParameterBlockErase_time;
else
if (BankLib_man.isMainBlock(address)) Erase_time=`MainBlockErase_time;
else Erase_time=`ParameterBlockErase_time;
end
 
 
function IsBusy; // boolean function primitive
input obbl; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
 
 
// *********************
//
// Task checkConfirm :
// check confirm code
//
// *********************
 
task checkConfirm;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
 
begin
 
if (data == `BLNKCHKconfirm_cmd) outStatus = `NoError_msg;
else outStatus = `WrongBlankCheckConfirm_msg;
end
endtask
 
 
 
 
 
// ****************
//
// Task Blank Check
//
// ****************
 
task BlankCheck;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
 
integer hold_block;
reg [`ADDRBUS_range] hold_address;
 
begin
hold_address = address;
hold_block = BankLib_man.getBlock(hold_address);
if (BankLib_man.isMainBlock(address)) begin
// Main Block
delayTime = `MainBlankCheck_time;
end else // Parameter Block
-> ErrorCheckEvent;
disable Operation;
 
fork
begin: Operation
Busy = `TRUE;
startTime = $time;
-> ErrorCheckEvent;
#delayTime
Memory_man.BlockBlankCheck(hold_block, Status);
-> CompleteEvent;
end
@CompleteEvent
disable Operation;
join
outStatus = Status;
Busy = `FALSE;
end
endtask
 
 
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (!progVoltOK)
Status = `InvVDD_msg;
if (BankLib_man.isParameterBlock(address)) begin
Status = `WrongBlankCheckBlock;
$display("parameter block");
end
if (Status != `NoError_msg) begin
->CompleteEvent;
disable ErrorCheck;
end
else
fork : ErrorCheck
@(negedge progVoltOK) Status = `InvVDD_msg;
@(Status) -> CompleteEvent;
@(CompleteEvent) disable ErrorCheck;
join
end
 
endmodule //end module Erase
 
 
// *********************************
//
// Program Buffer module :
//
// program buffer functionality
//
// *********************************
 
module ProgramBufferModule(address,data,voltOK,Info);
input [`ADDRBUS_range] address;
input [`WORD_range] data;
input voltOK, Info;
event ErrorCheckEvent, CompleteEvent, WatchAddressEvent;
reg [`BYTE_range] Status;
reg [`DATABUS_dim-1:0] Count;
 
reg [`WORD_range] bufferData [`ProgramBuffer_range];
 
reg [`ADDRBUS_range] AddressLatched, startAddress,newAddress;
reg Busy, Suspended, Empty;
time startTime, delayTime;
integer i;
 
initial begin // constructor sequence
Busy = `FALSE;
Suspended = `FALSE;
Empty = `TRUE;
delayTime = `ProgramBuffer_time;
end
 
function IsBusy; // boolean function primitive
input obbl; // all functions require a parameter
IsBusy = Busy; // return Boolean value
endfunction
 
function IsSuspended; // boolean function primitive
input obbl; // all functions require a parameter
IsSuspended = Suspended; // return Boolean value
endfunction
 
function IsAddrSuspended; // boolean function primitive
input [`ADDRBUS_range] addr;
IsAddrSuspended = (Suspended && ((addr >= startAddress) && (addr < (startAddress + Count))));
endfunction
 
 
function [`DATABUS_dim-1:0] GetCount;
input required;
GetCount = Count;
endfunction
 
task SetCount; // sets the number of writes
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
outStatus = `NoError_msg;
AddressLatched = address;
Count = data + 1;
 
if (Count > `ProgramBuffer_dim)
outStatus = `BuffSize_msg;
else if (BankLib_man.getBlock(AddressLatched) != BankLib_man.getBlock(AddressLatched + Count - 1))
outStatus = `BlkBuffer_msg;
else
-> WatchAddressEvent;
end
endtask
 
task Suspend;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
delayTime = delayTime - ($time - startTime);
#`ProgramSuspendLatency_time;
outStatus = `NoError_msg;
Status = `Suspend_msg;
Suspended = `TRUE;
-> CompleteEvent;
end
endtask
 
task Resume;
output [`BYTE_range] Status;
begin
Suspended = `FALSE;
Program(Status);
end
endtask
 
task Load;
output [`BYTE_range] Status;
begin
if (Empty) begin
startAddress = address;
if (Info) $display("[%t] Buffer start address: %h",$time,startAddress);
Empty = `FALSE;
end
bufferData[address[`ProgramBuffer_addrRange]] = data;
 
end
endtask
 
task Program;
output [`BYTE_range] outStatus;
reg [`BYTE_range] outStatus;
begin
 
fork
begin : Operation
Busy = `TRUE;
startTime = $time;
-> ErrorCheckEvent;
-> WatchAddressEvent; // disable address watch
#delayTime
for (i = startAddress;i < ( Count + startAddress); i = i + 1) begin
Memory_man.Program(bufferData[i[`ProgramBuffer_addrRange]],i,Status);
 
end
delayTime = `ProgramBuffer_time;
-> CompleteEvent;
end
@CompleteEvent
disable Operation;
 
join
if(!Suspended)
for (i = 0; i < `ProgramBuffer_dim; i = i + 1) begin
bufferData[i] =16'hFFFF;
end
Empty = `TRUE;
outStatus = Status;
Busy = `FALSE;
end
endtask
 
always @(ErrorCheckEvent) begin
Status = `NoError_msg;
if (BlockLock_man.IsLocked(AddressLatched))
Status = `BlockLock_msg;
else if (Suspended)
Status = `SuspAcc_msg;
else if (!voltOK)
Status = `InvVDD_msg;
 
if (Status != `NoError_msg)
->CompleteEvent;
else
fork : ErrorCheck
@(negedge voltOK) Status = `InvVDD_msg;
@(Status) -> CompleteEvent;
@(CompleteEvent) disable ErrorCheck;
join
end
 
always @(WatchAddressEvent) fork : AddressWatch
while (`TRUE)
@address
if (BankLib_man.getBlock(address) != BankLib_man.getBlock(AddressLatched)) begin
Status = `AddrTog_msg;
-> CompleteEvent;
end
@WatchAddressEvent
disable AddressWatch;
join
 
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.