diff --git a/lib/models/memory/flash/serial/S25fl032p/Model_Manual_English.pdf b/lib/models/memory/flash/serial/S25fl032p/Model_Manual_English.pdf new file mode 100644 index 0000000..954c3f6 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl032p/Model_Manual_English.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl032p/Model_Manual_Japanese.pdf b/lib/models/memory/flash/serial/S25fl032p/Model_Manual_Japanese.pdf new file mode 100644 index 0000000..de2f909 Binary files /dev/null and b/lib/models/memory/flash/serial/S25fl032p/Model_Manual_Japanese.pdf differ diff --git a/lib/models/memory/flash/serial/S25fl032p/model/model_release_history.txt b/lib/models/memory/flash/serial/S25fl032p/model/model_release_history.txt new file mode 100644 index 0000000..ca61589 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/model/model_release_history.txt @@ -0,0 +1,227 @@ +########################################## +Date (DD/MM/YYYY) - 22.01.2008. + +Model name - S25FL032P + +Vendor - Spansion LLC + +Publication ID - SPANSION, S25FL064 032P DRS Rev.16 Issue Date: November 7, 2007 + +VITAL model author - Dragisa Stanojkovic + d-stanojkovic@hdl-dh.com +########################################## +########################################## +INITIAL RELEASE + +# Release Label => vital-amd-REL-s25fl032p-2008-01-22-1.tar.gz +# Release Date (DD/MM/YYYY) => 22/01/2008 +# Release Version => 1.0 +########################################## +RELEASE 1.1 + +# Release Label => vital-amd-REL-s25fl032p-2008-02-20-2.tar.gz +# Release Date (DD/MM/YYYY) => 20/02/2008 +# Release Version => 1.1 + +# Bugs fixed (from previous release) +- Quad functionality issue + +# Files modified (from previous release) +- s25fl032p.vhd +- s25fl032p.v +- testbench_s25fl032p_vhdl.vhd +- testbench_s25fl032p_verilog.vhd +- spansion_tc_pkg.vhd +- model_release_history.txt +########################################## +########################################## +Publication ID - SPANSION, S25FL064 032P DRS Rev.19, 2008 + +VITAL model author - Dragisa Stanojkovic + d-stanojkovic@hdl-dh.com +########################################## +########################################## +RELEASE 1.2 + +# Release Label => vital-amd-REL-s25fl032p-2008-03-05-1.tar.gz +# Release Date (DD/MM/YYYY) => 05/03/2008 +# Release Version => 1.2 + +# Bugs fixed (from previous release) +- MPM mode for Dual/Quad High Performance changed + +# Files modified (from previous release) +- s25fl032p.ftm +- s25fl032p.ftmv +- s25fl032p_vhdl.sdf +- s25fl032p_verilog.sdf +- s25fl032p.vhd +- s25fl032p.v +- testbench_s25fl032p_vhdl.vhd +- testbench_s25fl032p_verilog.vhd +- spansion_tc_pkg.vhd +- model_release_history.txt +########################################## +########################################## +RELEASE 1.3 + +# Release Label => vital-amd-REL-s25fl032p-2008-03-20-1.tar.gz +# Release Date (DD/MM/YYYY) => 20/03/2008 +# Release Version => 1.3 + +# Bugs fixed (from previous release) +- MPM mode removed + +# Files modified (from previous release) +- s25fl032p.vhd +- s25fl032p.v +- testbench_s25fl032p_vhdl.vhd +- testbench_s25fl032p_verilog.vhd +- spansion_tc_pkg.vhd +- model_release_history.txt +########################################## +########################################## + +VITAL model author - Jadranka Stoickov + j-stoickov@hdl-dh.com +########################################## +########################################## +RELEASE 1.4 + +# Release Label => vital-amd-REL-s25fl032p-2008-08-07-1.tar.gz +# Release Date (DD/MM/YYYY) => 07/08/2008 +# Release Version => 1.4 + +# Bugs fixed (from previous release) +- WEL bit fixed + +# Files modified (from previous release) +- s25fl032p.v +- model_release_history.txt +########################################## +########################################## +Publication ID - SPANSION, S25FL032P_00 Rev.01, 2008 + +VITAL model author - Jadranka Stoickov + j-stoickov@hdl-dh.com +########################################## +########################################## +RELEASE 1.5 + +# Release Label => vital-amd-REL-s25fl032p-2008-09-16-1.tar.gz +# Release Date (DD/MM/YYYY) => 16/09/2008 +# Release Version => 1.5 + +# Changes made (from previous release) +- alignment to new datasheet + +# Files modified (from previous release) +- s25fl032p.ftm +- s25fl032p.ftmv +- s25fl032p_vhdl.sdf +- s25fl032p_verilog.sdf +- s25fl032p.vhd +- s25fl032p.v +- testbench_s25fl032p_vhdl.vhd +- testbench_s25fl032p_verilog.vhd +- spansion_tc_pkg.vhd +- spansion_flash_testbench_struct.pdf +- spansion_flash_test_cases_list.pdf +- model_release_history.txt +########################################## +########################################## +Publication ID - SPANSION, S25FL129_064_032P_DRS Rev.23.2, Oct 13, 2008 + +VITAL model author - Jadranka Stoickov + j-stoickov@hdl-dh.com +########################################## +########################################## +RELEASE 1.6 + +# Release Label => vital-amd-REL-s25fl032p-2008-12-15-2.tar.gz +# Release Date (DD/MM/YYYY) => 15/12/2008 +# Release Version => 1.6 + +# Changes made (from previous release) +- alignment to new datasheet + +# Files modified (from previous release) +- s25fl032p.ftm +- s25fl032p.ftmv +- s25fl032p_vhdl.sdf +- s25fl032p_verilog.sdf +- s25fl032p.vhd +- s25fl032p.v +- testbench_s25fl032p_vhdl.vhd +- testbench_s25fl032p_verilog.vhd +- spansion_tc_pkg.vhd +- spansion_flash_testbench_struct.pdf +- spansion_flash_test_cases_list.pdf +- model_release_history.txt +########################################## +VITAL model author - Snezana Petrovic + s-petrovic@hdl-dh.com +########################################## +########################################## +RELEASE 1.7 + +# Release Label => vital-amd-REL-s25fl032p-2009-05-29-1.tar.gz +# Release Date (DD/MM/YYYY) => 29/05/2009 +# Release Version => 1.7 + +# Changes made (from previous release) +- Timing ranges in timing files corrected + +# Files modified (from previous release) +- s25fl032p.ftm +- s25fl032p.ftmv +- s25fl032p_vhdl.sdf +- s25fl032p_verilog.sdf +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +########################################## +RELEASE 1.8 + +# Release Label => vital-amd-REL-s25fl032p-2010-09-29-1.tar.gz +# Release Date (DD/MM/YYYY) => 29/09/2010 +# Release Version => 1.8 + +# Changes made (from previous release) +# 1. During the QUAD mode HOLD# input is not monitored for its normal function +# 2. Internal pull-up resistors for HOLD# and WP# inputs are implemented + +# Files modified (from previous release) +- s25fl032p.vhd +- s25fl032p.v +########################################## +########################################## +VITAL model author - Vesna Mancev + v-mancev@hdl-dh.com +########################################## +########################################## +RELEASE 1.9 + +# Release Label => vital-amd-REL-s25fl032p-2011-12-15-1.tar.gz +# Release Date (DD/MM/YYYY) => 15/12/2011 +# Release Version => 1.9 + +# Changes made (from previous release) +- alignment to new datasheet (S25FL032P_00_05, October 5, 2009) + +# Files modified (from previous release) +- s25fl032p.ftm +- s25fl032p.ftmv +- s25fl032p_vhdl.sdf +- s25fl032p_verilog.sdf +- s25fl032p.vhd +- s25fl032p.v +- testbench_s25fl032p_vhdl.vhd +- testbench_s25fl032p_verilog.vhd +- spansion_tc_pkg.vhd +- spansion_flash_testbench_struct.pdf +- spansion_flash_test_cases_list.pdf +- model_release_history.txt +########################################## \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p.v b/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p.v new file mode 100644 index 0000000..f7e8f01 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p.v @@ -0,0 +1,2598 @@ +////////////////////////////////////////////////////////////////////////////// +// File name : s25fl032p.v +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2011 Spansion, LLC. +// +// MODIFICATION HISTORY : +// +// version: | author: | mod date: | changes made: +// V1.0 D.Stanojkovic 08 Jan 22 Inital Release +// V1.1 D.Stanojkovic 08 Feb 20 BP bits setting corrected +// V1.2 D.Stanojkovic 08 Mar 05 MPM mode corrected +// V1.3 D.Stanojkovic 08 Mar 20 MPM mode removed +// V1.4 J.Stoickov 08 Aug 07 WEL bit corrected +// V1.5 J.Stoickov 08 Sep 16 Latest datasheet aligned +// V1.6 J.Stoickov 08 Dec 10 Latest datasheet aligned +// (S25FL129 064 032P) +// Program Error bit will not be +// set after programming in +// protect memory region +// V1.7 V.Mancev 10 Sep 29 Implementation of internal pull-up +// for HOLDNeg and WPNeg pins +// V1.8 V.Mancev 11 Dec 15 Latest datasheet aligned +// (S25FL032P_00_05) +////////////////////////////////////////////////////////////////////////////// +// PART DESCRIPTION: +// +// Library: FLASH +// Technology: FLASH MEMORY +// Part: S25FL032P +// +// Description: 32 Megabit Serial Flash Memory with 104 MHz SPI Bus Interface +// Comments : +// For correct simulation, simulator resolution should be set to 1 ps +// +////////////////////////////////////////////////////////////////////////////// +// Known Bugs: +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// MODULE DECLARATION // +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ps/1 ps + +module s25fl032p +( + SCK , + SI , + CSNeg , + HOLDNeg , + WPNeg , + SO +); +//////////////////////////////////////////////////////////////////////// +// Port / Part SOIn Declarations +//////////////////////////////////////////////////////////////////////// + input SCK ; + inout SI ; + + input CSNeg ; + inout HOLDNeg ; + inout WPNeg ; + inout SO ; + +// interconnect path delay signals + wire SCK_ipd ; + wire SI_ipd ; + + wire SI_in ; + assign SI_in = SI_ipd ; + + wire SI_out ; + assign SI_out = SI ; + + wire CSNeg_ipd ; + wire HOLDNeg_ipd ; + wire WPNeg_ipd ; + wire SO_ipd ; + + wire HOLDNeg_in ; + //Internal pull-up + assign HOLDNeg_in = (HOLDNeg_ipd === 1'bx) ? 1'b1 : HOLDNeg_ipd; + + wire HOLDNeg_out ; + assign HOLDNeg_out = HOLDNeg ; + + wire WPNeg_in ; + //Internal pull-up + assign WPNeg_in = (WPNeg_ipd === 1'bx) ? 1'b1 : WPNeg_ipd; + + wire WPNeg_out ; + assign WPNeg_out = WPNeg ; + + wire SOIn ; + assign SOIn = SO_ipd ; + + wire SOut ; + assign SOut = SO ; + +// internal delays + reg PP_in ; + reg PP_out ; + reg PU_in ; + reg PU_out ; + reg SE_in ; + reg SE_out ; + reg BE_in ; + reg BE_out ; + reg PE_in ; + reg PE_out ; + reg WR_in ; + reg WR_out ; + reg DP_in ; + reg DP_out ; + reg EP_in ; + reg EP_out ; + reg RES_in ; + reg RES_out ; + + reg SOut_zd = 1'bZ; + reg SOut_z = 1'bZ; + + wire SI_z ; + wire SO_z ; + + reg SIOut_zd = 1'bZ ; + reg SIOut_z = 1'bZ ; + + reg WPNegOut_zd = 1'bZ ; + reg HOLDNegOut_zd = 1'bZ ; + + assign SI_z = SIOut_z; + assign SO_z = SOut_z; + + parameter UserPreload = 1; + parameter mem_file_name = "none";//"s25fl032p.mem"; + parameter otp_file_name = "none";//"s25fl032p_secsi.mem"; + + parameter TimingModel = "DefaultTimingModel"; + + parameter PartID = "s25fl032p"; + parameter MaxData = 255; + parameter SecSize = 16'hFFFF; + parameter SecSize_4 = 4095; + parameter SecSize_8 = 8191; + parameter SecNum = 63; + parameter PageNum = 16'h3FFF; + parameter OTPSize = 511; + parameter OTPLoAddr = 9'h100; + parameter OTPHiAddr = 10'h2FF; + parameter HiAddrBit = 23; + parameter AddrRANGE = 24'h3FFFFF; + parameter BYTE = 8; + parameter Manuf_ID = 8'h01; + parameter ES = 8'h15; + parameter Jedec_ID = 8'h20; // first byte of Device ID + parameter DeviceID = 16'h0215; + parameter ExtendedBytes = 8'h4D; + parameter ReservedBytes = 8'h00; + + // If speed simulation is needed uncomment following line + +// `define SPEEDSIM; + + // powerup + reg PoweredUp; + + //FSM control signals + reg PDONE ; ////Prog. Done + reg PSTART ; ////Start Programming + + reg EDONE ; ////Era. Done + reg ESTART ; ////Start Erasing + + reg WDONE ; //// Writing Done + reg WSTART ; ////Start writing + + //Command Register + reg write; + reg cfg_write; + reg read_out; + + //Status reg. + reg[7:0] Status_reg = 8'b0; + reg[7:0] Status_reg_in = 8'b0; + reg[7:0] Sec_conf_reg = 8'b0; + reg[7:0] Sec_conf_reg_in = 8'b0; + + wire FREEZE; + wire QUAD; + wire TBPARM; + wire BPNV; + wire TBPROT; + assign FREEZE = Sec_conf_reg[0]; + assign QUAD = Sec_conf_reg[1]; + assign TBPARM = Sec_conf_reg[2]; + assign BPNV = Sec_conf_reg[3]; + assign TBPROT = Sec_conf_reg[5]; + + wire WIP; + wire WEL; + wire [2:0]BP; + wire E_ERR; + wire P_ERR; + wire SRWD; + assign WIP = Status_reg[0]; + assign WEL = Status_reg[1]; + assign BP = Status_reg[4:2]; + assign E_ERR = Status_reg[5]; + assign P_ERR = Status_reg[6]; + assign SRWD = Status_reg[7]; + + integer SA = 0; // 0 TO SecNum+1 + integer Byte_number = 0; + integer sect; + + //Address + integer Address = 0; // 0 - AddrRANGE + reg change_addr; + reg rd_fast; // = 1'b1; + reg rd_slow; + reg rd_jedec; + reg change_BP = 0; + reg rd_dual; + reg dual; + wire fast_rd; + wire rd; + wire rd_jid; + + wire RD_EQU_1; + assign RD_EQU_1 = rd_slow; + + wire RD_EQU_0; + assign RD_EQU_0 = ~rd_slow; + + reg hold_mode; + reg mpm_mode = 0; + wire hold; + + //Sector Protection Status + reg [SecNum:0] Sec_Prot = 64'b0; //= SecNum'b0; + + // timing check violation + reg Viol = 1'b0; + + integer Mem[0:AddrRANGE]; + integer OTPMem[OTPLoAddr: OTPHiAddr]; + + integer WByte[0:255]; + integer WOTPByte; + integer AddrLo; + integer AddrHi; + + reg[7:0] old_bit, new_bit; + integer old_int, new_int; + integer wr_cnt; + integer cnt; + + integer read_cnt = 0; + integer read_addr = 0; + reg[7:0] data_out; + reg[647:0] ident_out; + + reg oe = 1'b0; + event oe_event; + + integer CFI_array[8'h07:8'h50]; + reg [591:0] CFI_array_tmp; + reg [7:0] CFI_tmp; + + reg[15:0] PR_LOCK1; + reg[15:0] PR_LOCK2; + reg[15:0] PR_LOCK3; + +/////////////////////////////////////////////////////////////////////////////// +//Interconnect Path Delay Section +/////////////////////////////////////////////////////////////////////////////// + + buf (SCK_ipd, SCK); + buf (SI_ipd, SI); + + buf (CSNeg_ipd, CSNeg); + buf (HOLDNeg_ipd, HOLDNeg); + buf (WPNeg_ipd, WPNeg); + buf (SO_ipd, SO); + +/////////////////////////////////////////////////////////////////////////////// +// Propagation delay Section +/////////////////////////////////////////////////////////////////////////////// + nmos (SO, SO_z , 1); + + nmos (SI, SI_z , 1); + nmos (HOLDNeg, HOLDNegOut_zd , 1); + nmos (WPNeg, WPNegOut_zd , 1); + + wire deg_pin; + wire deg_sin; + wire deg_holdin; + //VHDL VITAL CheckEnable equivalents + wire dual_wr; + assign dual_wr = deg_holdin && QUAD; + wire dual_rd; + assign dual_rd = dual; + wire quad_wr; + assign quad_wr = SRWD && WEL ; + wire power; + assign power = PoweredUp; + + specify + // tipd delays: interconnect path delays , mapped to input port delays. + // In Verilog is not necessary to declare any tipd_ delay variables, + // they can be taken from SDF file + // With all the other delays real delays would be taken from SDF file + + // tpd delays + specparam tpd_SCK_SO =1; + specparam tpd_SCK_SI =1; + specparam tpd_CSNeg_SO =1; + specparam tpd_HOLDNeg_SO =1; + + specparam tsetup_SI_SCK =1; //tsuDAT / + specparam tsetup_CSNeg_SCK =1; // tCSS / + specparam tsetup_HOLDNeg_SCK =1; //tHD / + specparam tsetup_SCK_HOLDNeg =1; //tCH \ + specparam tsetup_WPNeg_CSNeg =1; //tWPS \ + + // thold values: hold times + specparam thold_SI_SCK =1; //thdDAT / + specparam thold_CSNeg_SCK =1; //tCSH / + specparam thold_HOLDNeg_SCK =1; //tCHHH / + specparam thold_SCK_HOLDNeg =1; //tHC \ + specparam thold_WPNeg_CSNeg =1; //tWPH \ + + // tpw values: pulse width + specparam tpw_SCK_fast_posedge =1; //tWH + specparam tpw_SCK_posedge =1; //tWH + specparam tpw_SCK_dual_posedge =1; //tWH + specparam tpw_SCK_rdid_posedge =1; //tWH + specparam tpw_SCK_fast_negedge =1; //tWL + specparam tpw_SCK_negedge =1; //tWL + specparam tpw_SCK_dual_negedge =1; //tWL + specparam tpw_SCK_rdid_negedge =1; //tWL + specparam tpw_CSNeg_read_posedge =1; //tCS + specparam tpw_CSNeg_pgm_posedge =1; //tCS + + // tperiod min (calculated as 1/max freq) + specparam tperiod_SCK_rd =1; // fSCK = 40MHz + specparam tperiod_SCK_fast_rd =1; // fSCK = 104MHz + specparam tperiod_SCK_dual_fast_rd =1; // fSCK = 80MHz + specparam tperiod_SCK_rdid =1; // fSCK = 50MHz + + // tdevice values: values for internal delays + `ifdef SPEEDSIM + // Page Program Operation + specparam tdevice_PP = 3e7; //30 us; + //Page Program Operation (ACC=9V)) + specparam tdevice_EP = 2.4e9; //2.4 ms; + //Sector Erase Operation + specparam tdevice_SE = 2e9; //2 ms; + //Bulk Erase Operation + specparam tdevice_BE = 64e9; //64 ms; + //Write Status Register Operation + specparam tdevice_WR = 5e8; // 0.5 ms; + //Software Protect Mode + specparam tdevice_DP = 10000000; // 10 us; + //Release from Software Protect Mode + specparam tdevice_RES = 30000000; // 30 us; + //Parameter block erase + specparam tdevice_PE = 800e6; //800 us; + //VCC (min) to CS# Low + specparam tdevice_PU = 300000000; //300 us; + `else + // Page Program Operation + specparam tdevice_PP = 3e9; //3 ms; + //Page Program Operation (ACC=9V)) + specparam tdevice_EP = 2.4e9; //2.4 ms; + //Sector Erase Operation + specparam tdevice_SE = 2e12; //2 s; + //Bulk Erase Operation + specparam tdevice_BE = 64e12; //64 sec; + //Write Status Register Operation + specparam tdevice_WR = 50e9; // 50 ms; + //Software Protect Mode + specparam tdevice_DP = 10000000; // 10 us; + //Release from Software Protect Mode + specparam tdevice_RES = 30000000; // 30 us; + //Parameter block erase + specparam tdevice_PE = 800e9; //800 ms; + //VCC (min) to CS# Low + specparam tdevice_PU = 300000000; //300 us; + `endif//SPEEDSIM + +/////////////////////////////////////////////////////////////////////////////// +// Input Port Delays don't require Verilog description +/////////////////////////////////////////////////////////////////////////////// +// Path delays // +/////////////////////////////////////////////////////////////////////////////// + if (~dual) (SCK => SO) = tpd_SCK_SO; + if (dual) (SCK => SO) = tpd_SCK_SI; + if (CSNeg)(CSNeg => SO) = tpd_CSNeg_SO; + if (~dual) (HOLDNeg => SO) = tpd_HOLDNeg_SO; + if (dual) (HOLDNeg => SO) = tpd_HOLDNeg_SO; + + if (dual)(SCK => SI) = tpd_SCK_SI; + if (dual && CSNeg)(CSNeg => SI) = tpd_CSNeg_SO; + if (dual)(HOLDNeg => SI) = tpd_HOLDNeg_SO; + + if (dual && QUAD)(SCK => HOLDNeg) = tpd_SCK_SI; + if (dual && CSNeg && QUAD)(CSNeg => HOLDNeg) = tpd_CSNeg_SO; + + if (dual && QUAD)(SCK => WPNeg) = tpd_SCK_SI; + if (dual && CSNeg && QUAD)(CSNeg => WPNeg) = tpd_CSNeg_SO; +//////////////////////////////////////////////////////////////////////////////// +// Timing Violation // +//////////////////////////////////////////////////////////////////////////////// + $setup ( SI , posedge SCK &&& deg_sin, + tsetup_SI_SCK, Viol); + $setup ( negedge HOLDNeg, posedge SCK &&& dual_wr, + tsetup_HOLDNeg_SCK, Viol); + $setup ( posedge SCK , posedge HOLDNeg &&& dual_wr, + tsetup_SCK_HOLDNeg, Viol); + $setup ( CSNeg , posedge SCK &&& power, + tsetup_CSNeg_SCK, Viol); + $setup ( WPNeg , negedge CSNeg &&& WPNeg, + tsetup_WPNeg_CSNeg, Viol); + + $hold ( posedge SCK , SI &&& deg_sin, + thold_SI_SCK, Viol); + $hold ( posedge HOLDNeg , posedge SCK &&& dual_wr, + thold_SCK_HOLDNeg, Viol); + $hold ( posedge SCK , CSNeg &&& power, + thold_CSNeg_SCK, Viol); + $hold ( posedge CSNeg , WPNeg &&& quad_wr, + thold_WPNeg_CSNeg, Viol); + $hold ( posedge SCK , negedge HOLDNeg &&& dual_wr, + thold_HOLDNeg_SCK, Viol); + + $width (posedge SCK &&& rd , tpw_SCK_posedge); + $width (posedge SCK &&& fast_rd , tpw_SCK_fast_posedge); + $width (posedge SCK &&& dual_rd , tpw_SCK_dual_posedge); + $width (posedge SCK &&& rd_jid , tpw_SCK_rdid_posedge); + $width (negedge SCK &&& rd , tpw_SCK_negedge); + $width (negedge SCK &&& fast_rd , tpw_SCK_fast_negedge); + $width (negedge SCK &&& dual_rd , tpw_SCK_dual_negedge); + $width (negedge SCK &&& rd_jid , tpw_SCK_rdid_negedge); + + $width (posedge CSNeg &&& RD_EQU_0, tpw_CSNeg_pgm_posedge); + $width (posedge CSNeg &&& RD_EQU_1, tpw_CSNeg_read_posedge); + + $period (posedge SCK &&& rd, tperiod_SCK_rd); + $period (posedge SCK &&& fast_rd, tperiod_SCK_fast_rd); + $period (posedge SCK &&& dual_rd, tperiod_SCK_dual_fast_rd); + $period (posedge SCK &&& rd_jid, tperiod_SCK_rdid); + + endspecify + +//////////////////////////////////////////////////////////////////////////////// +// Main Behavior Block // +//////////////////////////////////////////////////////////////////////////////// +// FSM states + parameter IDLE =4'd0; + parameter WRITE_SR =4'd1; + parameter DP_DOWN_WAIT =4'd2; + parameter DP_DOWN =4'd3; + parameter SECTOR_ER =4'd4; + parameter BULK_ER =4'd5; + parameter PAGE_PG =4'd6; + parameter OTP_PG =4'd7; + parameter P4_ER =4'd8; + parameter P8_ER =4'd9; + + reg [3:0] current_state; + reg [3:0] next_state; + +// Instructions + parameter NONE =5'd0; + parameter WREN =5'd1; + parameter WRDI =5'd2; + parameter WRR =5'd3; + parameter RDSR =5'd4; + parameter READ =5'd5; + parameter READ_ID =5'd6; + parameter RDID =5'd7; + parameter FAST_READ =5'd8; + parameter DUAL_READ =5'd9; + parameter QUAD_READ =5'd10; + parameter DH_READ =5'd11; + parameter QH_READ =5'd12; + parameter SE =5'd13; + parameter BE =5'd14; + parameter PP =5'd15; + parameter QPP =5'd16; + parameter DP =5'd17; + parameter RES_READ_ES =5'd18; + parameter CLSR =5'd19; + parameter RCR =5'd20; + parameter P4E =5'd21; + parameter P8E =5'd22; + parameter OTPP =5'd23; + parameter OTPR =5'd24; + reg [4:0] Instruct; + +//Bus cycle states + parameter STAND_BY =3'd0; + parameter CODE_BYTE =3'd1; + parameter ADDRESS_BYTES =3'd2; + parameter DUMMY_BYTES =3'd3; + parameter MODE_BYTE =3'd4; + parameter DATA_BYTES =3'd5; + + reg [2:0] bus_cycle_state; + + reg deq_pin; + always @(SOIn, SO_z) + begin + if (SOIn==SO_z) + deq_pin=1'b0; + else + deq_pin=1'b1; + end + // chech when data is generated from model to avoid setuphold check in + // those occasion + assign deg_pin=deq_pin; + + reg deq_sin; + always @(SI_in, SIOut_z) + begin + if (SI_in==SIOut_z) + deq_sin=1'b0; + else + deq_sin=1'b1; + end + // chech when data is generated from model to avoid setuphold check in + // those occasion + assign deg_sin=deq_sin; + + reg deq_holdin; + always @(HOLDNeg_ipd, HOLDNegOut_zd) + begin + if (HOLDNeg_ipd==HOLDNegOut_zd) + deq_holdin=1'b0; + else + deq_holdin=1'b1; + end + // check when data is generated from model to avoid setuphold check in + // those occasion + assign deg_holdin=deq_holdin; + + initial + begin : Init + + write = 1'b0; + cfg_write = 1'b0; + read_out = 1'b0; + Address = 0; + change_addr = 1'b0; + + PDONE = 1'b1; + PSTART = 1'b0; + + EDONE = 1'b1; + ESTART = 1'b0; + + WDONE = 1'b1; + WSTART = 1'b0; + + DP_in = 1'b0; + DP_out = 1'b0; + RES_in = 1'b0; + RES_out = 1'b0; + Instruct = NONE; + + bus_cycle_state = STAND_BY; + current_state = IDLE; + next_state = IDLE; + end + + //CFI + initial + begin: InitCFI + integer i; + integer j; + + CFI_array[8'h07] = 8'hFF; + CFI_array[8'h08] = 8'hFF; + CFI_array[8'h09] = 8'hFF; + CFI_array[8'h0A] = 8'hFF; + CFI_array[8'h0B] = 8'hFF; + CFI_array[8'h0C] = 8'hFF; + CFI_array[8'h0D] = 8'hFF; + CFI_array[8'h0E] = 8'hFF; + CFI_array[8'h0F] = 8'hFF; + CFI_array[8'h10] = 8'h51; + CFI_array[8'h11] = 8'h52; + CFI_array[8'h12] = 8'h59; + CFI_array[8'h13] = 8'h02; + CFI_array[8'h14] = 8'h00; + CFI_array[8'h15] = 8'h40; + CFI_array[8'h16] = 8'h00; + CFI_array[8'h17] = 8'h00; + CFI_array[8'h18] = 8'h00; + CFI_array[8'h19] = 8'h00; + CFI_array[8'h1A] = 8'h00; + //System interface string + CFI_array[8'h1B] = 8'h27; + CFI_array[8'h1C] = 8'h36; + CFI_array[8'h1D] = 8'h00; + CFI_array[8'h1E] = 8'h00; + CFI_array[8'h1F] = 8'h0B; + CFI_array[8'h20] = 8'h0B; + CFI_array[8'h21] = 8'h09; + CFI_array[8'h22] = 8'h0F; + CFI_array[8'h23] = 8'h01; + CFI_array[8'h24] = 8'h01; + CFI_array[8'h25] = 8'h02; + CFI_array[8'h26] = 8'h01; + //device geometry definition + CFI_array[8'h27] = 8'h16; + CFI_array[8'h28] = 8'h05; + CFI_array[8'h29] = 8'h05; + CFI_array[8'h2A] = 8'h08; + CFI_array[8'h2B] = 8'h00; + CFI_array[8'h2C] = 8'h02; + CFI_array[8'h2D] = 8'h1F; + CFI_array[8'h2E] = 8'h00; + CFI_array[8'h2F] = 8'h10; + CFI_array[8'h30] = 8'h00; + CFI_array[8'h31] = 8'h3D; + CFI_array[8'h32] = 8'h00; + CFI_array[8'h33] = 8'h00; + CFI_array[8'h34] = 8'h01; + CFI_array[8'h35] = 8'h00; + CFI_array[8'h36] = 8'h00; + CFI_array[8'h37] = 8'h00; + CFI_array[8'h38] = 8'h00; + CFI_array[8'h39] = 8'h00; + CFI_array[8'h3A] = 8'h00; + CFI_array[8'h3B] = 8'h00; + CFI_array[8'h3C] = 8'h00; + CFI_array[8'h3D] = 8'hFF; + CFI_array[8'h3E] = 8'hFF; + CFI_array[8'h3F] = 8'hFF; + //primary vendor-specific extended query + CFI_array[8'h40] = 8'h50; + CFI_array[8'h41] = 8'h52; + CFI_array[8'h42] = 8'h49; + CFI_array[8'h43] = 8'h31; + CFI_array[8'h44] = 8'h33; + CFI_array[8'h45] = 8'h15; + CFI_array[8'h46] = 8'h00; + CFI_array[8'h47] = 8'h01; + CFI_array[8'h48] = 8'h00; + CFI_array[8'h49] = 8'h05; + CFI_array[8'h4A] = 8'h00; + CFI_array[8'h4B] = 8'h01; + CFI_array[8'h4C] = 8'h03; + CFI_array[8'h4D] = 8'h85; + CFI_array[8'h4E] = 8'h95; + CFI_array[8'h4F] = 8'h07; + CFI_array[8'h50] = 8'h00; + + for(i=73;i>=0;i=i-1) + begin + CFI_tmp = CFI_array[8'h07-i+73]; + for(j=7;j>=0;j=j-1) + begin + CFI_array_tmp[8*i+j] = CFI_tmp[j]; + end + end + end + + // initialize memory + initial + begin: InitMemory + integer i; + + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + + if ((UserPreload) && !(mem_file_name == "none")) + begin + // Memory Preload + // s25fl032p.mem, memory preload file + // @aaaaaa - stands for address + // dd -
is byte to be written at Mem(aaaaaa++) + // (aaaaaa is incremented at every load) + $readmemh(mem_file_name,Mem); + end + + for (i=OTPLoAddr;i<=OTPHiAddr;i=i+1) + begin + OTPMem[i] = MaxData; + end + if (UserPreload && !(otp_file_name == "none")) + begin + //s25fl032p_secsi memory file + // / - comment + // @aaaaaa - stands for address within last defined + // sector + // dd -
is byte to be written at SecSi(aaaaaa++) + // (aa is incremented at every load) + // only first 1-5 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + $readmemh(otp_file_name,OTPMem); + end + PR_LOCK1[15:8] = 16'h0; + PR_LOCK1[7:0] = OTPMem[256]; + + PR_LOCK2[15:8] = OTPMem[275]; + PR_LOCK2[7:0] = OTPMem[274]; + + PR_LOCK3[15:8] = OTPMem[533]; + PR_LOCK3[7:0] = OTPMem[532]; + end + + //Power Up time; + initial + begin + PoweredUp = 1'b0; + #tdevice_PU PoweredUp = 1'b1; + end + + always @(posedge DP_in) + begin:TDPr + #tdevice_DP DP_out = DP_in; + end + always @(negedge DP_in) + begin:TDPf + #1 DP_out = DP_in; + end + + always @(posedge RES_in) + begin:TRESr + #tdevice_RES RES_out = RES_in; + end + always @(negedge RES_in) + begin:TRESf + #1 RES_out = RES_in; + end + + always @(next_state or PoweredUp) + begin: StateTransition + if (PoweredUp) + begin + current_state = next_state; + end + end + + always @(negedge CSNeg_ipd) + begin:CheckCSOnPowerUP + if (~PoweredUp) + $display ("Device is selected during Power Up"); + end + +// /////////////////////////////////////////////////////////////////////////// +// // Instruction cycle decode +// /////////////////////////////////////////////////////////////////////////// + integer data_cnt = 0; + integer addr_cnt = 0; + integer code_cnt = 0; + integer mode_cnt = 0; + integer dummy_cnt = 0; + integer bit_cnt = 0; + + reg[2047:0] Data_in = 2048'b0; + integer quad_data_in [0:511]; + reg[3:0] quad_nybble = 4'b0; + reg[3:0] Quad_slv = 4'b0; + reg[7:0] code = 8'b0; + reg[7:0] code_in = 8'b0; + reg[7:0] Byte_slv = 8'b0; + reg[HiAddrBit:0] addr_bytes; + reg[23:0] Address_in = 8'b0; + reg[7:0] mode_bytes; + reg[7:0] mode_in; + + reg rising_edge_CSNeg_ipd = 1'b0; + reg falling_edge_CSNeg_ipd = 1'b0; + reg rising_edge_SCK_ipd = 1'b0; + reg falling_edge_SCK_ipd = 1'b0; + + always @(falling_edge_CSNeg_ipd or rising_edge_CSNeg_ipd + or rising_edge_SCK_ipd or falling_edge_SCK_ipd) + begin: Buscycle1 + integer i; + integer j; + integer k; + if (falling_edge_CSNeg_ipd) + begin + if (bus_cycle_state==STAND_BY) + begin + bus_cycle_state = CODE_BYTE; + Instruct = NONE; + write = 1'b1; + code_cnt = 0; + addr_cnt = 0; + data_cnt = 0; + mode_cnt = 0; + dummy_cnt = 0; + end + end + + if (rising_edge_SCK_ipd) + begin + if (~CSNeg_ipd) + begin + case (bus_cycle_state) + CODE_BYTE : + begin + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + code_in[code_cnt] = SI_in; + code_cnt = code_cnt + 1; + if (code_cnt == BYTE) + begin + for (i=0;i<=7;i=i+1) + begin + code[i] = code_in[7-i]; + end + case(code) + 8'b00000110 : + begin + Instruct = WREN; + bus_cycle_state = DATA_BYTES; + end + 8'b00000100 : + begin + Instruct = WRDI; + bus_cycle_state = DATA_BYTES; + end + 8'b00000001 : + begin + Instruct = WRR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000101 : + begin + Instruct = RDSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00000011 : + begin + Instruct = READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00001011 : + begin + Instruct = FAST_READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10011111 : + begin + Instruct = RDID; + bus_cycle_state = DATA_BYTES; + end + 8'b10010000 : + begin + Instruct = READ_ID; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10101011 : + begin + Instruct = RES_READ_ES; + bus_cycle_state = DUMMY_BYTES; + end + 8'b11011000 : + begin + Instruct = SE; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11000111 , 8'b01100000: + begin + Instruct = BE; + bus_cycle_state = DATA_BYTES; + end + 8'b00000010 : + begin + Instruct = PP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00110010 : + begin + Instruct = QPP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10111001 : + begin + Instruct = DP; + bus_cycle_state = DATA_BYTES; + end + 8'b00110000 : + begin + Instruct = CLSR; + bus_cycle_state = DATA_BYTES; + end + 8'b00110101 : + begin + Instruct = RCR; + bus_cycle_state = DATA_BYTES; + end + 8'b00100000 : + begin + Instruct = P4E; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01000000 : + begin + Instruct = P8E; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01000010 : + begin + Instruct = OTPP; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01001011 : + begin + Instruct = OTPR; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b00111011 : + begin + Instruct = DUAL_READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b01101011 : + begin + Instruct = QUAD_READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b10111011 : + begin + Instruct = DH_READ; + bus_cycle_state = ADDRESS_BYTES; + end + 8'b11101011 : + begin + Instruct = QH_READ; + bus_cycle_state = ADDRESS_BYTES; + end + endcase + end + end + end + + ADDRESS_BYTES : + begin + if (((Instruct == FAST_READ || Instruct == OTPR || + Instruct == DUAL_READ) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct == QUAD_READ) && QUAD)) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for (i=23;i>=23-HiAddrBit;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DUMMY_BYTES; + end + end + else if (Instruct == DH_READ && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + if (SOIn !== 1'b0 && SOIn !== 1'b1) + begin + mpm_mode = 0; + bus_cycle_state = STAND_BY; + end + else + begin + Address_in[2*addr_cnt] = SOIn; + Address_in[2*addr_cnt+1] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 12) + begin + addr_cnt = 0; + for (i=23;i>=23-HiAddrBit;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + end + else if (Instruct == QH_READ) + begin + if(QUAD) + begin + if (SOIn !== 1'b0 && SOIn !== 1'b1) + begin + mpm_mode = 0; + bus_cycle_state = STAND_BY; + end + else + begin + Address_in[4*addr_cnt] = HOLDNeg_in; + Address_in[4*addr_cnt+1] = WPNeg_in; + Address_in[4*addr_cnt+2] = SOIn; + Address_in[4*addr_cnt+3] = SI_in; + read_cnt = 0; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 6) + begin + addr_cnt = 0; + for (i=23;i>=23-HiAddrBit;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = MODE_BYTE; + end + end + end + else + begin + bus_cycle_state = STAND_BY; + end + end + else if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + Address_in[addr_cnt] = SI_in; + addr_cnt = addr_cnt + 1; + if (addr_cnt == 3*BYTE) + begin + for (i=23;i>=23-HiAddrBit;i=i-1) + begin + addr_bytes[23-i] = Address_in[i]; + end + Address = addr_bytes; + change_addr = 1'b1; + #1 change_addr = 1'b0; + bus_cycle_state = DATA_BYTES; + end + end + end + + MODE_BYTE : + begin + if((Instruct == DH_READ) && + ((HOLDNeg_in && ~QUAD) || QUAD)) + begin + mode_in[2*mode_cnt] = SOIn; + mode_in[2*mode_cnt+1] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/2) + begin + mode_cnt = 0; + for (i=7;i>=7-BYTE;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DATA_BYTES; + end + end + else if((Instruct == QH_READ) && QUAD) + begin + mode_in[4*mode_cnt] = HOLDNeg_in; + mode_in[4*mode_cnt+1] = WPNeg_in; + mode_in[4*mode_cnt+2] = SOIn; + mode_in[4*mode_cnt+3] = SI_in; + mode_cnt = mode_cnt + 1; + if (mode_cnt == BYTE/4) + begin + mode_cnt = 0; + for (i=7;i>=7-BYTE;i=i-1) + begin + mode_bytes[i] = mode_in[7-i]; + end + bus_cycle_state = DUMMY_BYTES; + end + end + dummy_cnt = 0; + end + + DUMMY_BYTES : + begin + if(QUAD && (Instruct == QUAD_READ || + Instruct == QH_READ)) + begin + dummy_cnt = dummy_cnt + 1; + if ((dummy_cnt == BYTE) && Instruct == QUAD_READ) + bus_cycle_state = DATA_BYTES; + else if ((dummy_cnt == BYTE/2) && + Instruct == QH_READ) + bus_cycle_state = DATA_BYTES; + end + else if((HOLDNeg_in && ~QUAD) || QUAD) + begin + dummy_cnt = dummy_cnt + 1; + if (dummy_cnt == BYTE && (Instruct == FAST_READ || + Instruct == OTPR || Instruct == DUAL_READ)) + bus_cycle_state = DATA_BYTES; + else if (dummy_cnt == 3*BYTE) + bus_cycle_state = DATA_BYTES; + end + end + + DATA_BYTES : + begin + if(QUAD && Instruct == QPP) + begin + quad_nybble = {HOLDNeg_in, WPNeg_in, SOIn, SI_in}; + if (data_cnt > 511) + begin + //In case of quad mode and QPP, + //if more than 512 bytes are sent to the device + for (i=0;i<=510;i=i+1) + begin + quad_data_in[i] = quad_data_in[i+1]; + end + quad_data_in[511] = quad_nybble; + data_cnt = data_cnt + 1; + end + else + begin + if( quad_nybble !== 4'bZZZZ) + begin + quad_data_in[data_cnt] = quad_nybble; + end + data_cnt = data_cnt + 1; + end + end + else if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt > 2047) + //In case of serial mode and PP, if more than 256 + //bytes are sent to the device + begin + if (bit_cnt == 0) + begin + for (i=0;i<=(255*BYTE-1);i=i+1) + begin + Data_in[i] = Data_in[i+8]; + end + end + Data_in[2040 + bit_cnt] = SI_in; + bit_cnt = bit_cnt + 1; + if (bit_cnt == 8) + begin + bit_cnt = 0; + end + data_cnt = data_cnt + 1; + end + else + begin + Data_in[data_cnt] = SI_in; + data_cnt = data_cnt + 1; + bit_cnt = 0; + end + end + end + endcase + end + end + if (falling_edge_SCK_ipd) + begin + if ((bus_cycle_state == DATA_BYTES) && (~CSNeg_ipd)) + begin + if (((Instruct == READ || Instruct == FAST_READ || + Instruct == DUAL_READ || Instruct == DH_READ || + Instruct == RES_READ_ES || Instruct == RDID || + Instruct == RDSR || Instruct == READ_ID || + Instruct == RCR || Instruct == OTPR) && + ((HOLDNeg_in && ~QUAD) || QUAD)) || + ((Instruct == QUAD_READ || Instruct == QH_READ) && QUAD)) + begin + read_out = 1'b1; + #1 read_out = 1'b0; + end + end + end + if (rising_edge_CSNeg_ipd) + begin + if ((bus_cycle_state != DATA_BYTES) && + (bus_cycle_state != DUMMY_BYTES)) + begin + bus_cycle_state = STAND_BY; + end + else + begin + if (bus_cycle_state == DATA_BYTES) + begin + if (mpm_mode && (mode_bytes[7:4] == 4'b1010) && + (Instruct == DH_READ || Instruct == QH_READ)) + begin + bus_cycle_state = ADDRESS_BYTES; + end + else + begin + mpm_mode = 0; + bus_cycle_state = STAND_BY; + end + if (Instruct == QPP) + begin + if (data_cnt > 0) + begin + if ((data_cnt % 2) == 0) + begin + write = 0; + for(i=0;i<=255;i=i+1) + begin + for(j=1;j>=0;j=j-1) + begin + Quad_slv = quad_data_in[(i*2)+(1-j)]; + for(k=3;k>=0;k=k-1) + begin + Byte_slv[4*j+k] = Quad_slv[k]; + end + end + WByte[i] = Byte_slv; + end + if (data_cnt > 512) + Byte_number = 255; + else + Byte_number = data_cnt/2 -1; + end + end + end + if ((HOLDNeg_in && ~QUAD) || QUAD) + begin + case (Instruct) + WRDI, + WREN, + DP, + BE, + SE, + P4E, + P8E, + CLSR: + begin + if (data_cnt == 0) + write = 1'b0; + end + + RES_READ_ES: + begin + write = 1'b0; + end + + WRR : + begin + if((HOLDNeg_in && ~QUAD) || QUAD) + begin + if (data_cnt == 8) + begin + write = 0; + cfg_write = 1'b0; + for(i=0;i<=7;i=i+1) + begin + Status_reg_in[i]= + Data_in[7-i]; + end + end + else if (data_cnt == 16) + begin + write = 0; + cfg_write = 1'b1; + for(i=0;i<=7;i=i+1) + begin + Status_reg_in[i]= + Data_in[7-i]; + Sec_conf_reg_in[i]= + Data_in[15-i]; + end + end + end + end + + PP : + begin + if (data_cnt > 0) + begin + if ((data_cnt % 8) == 0) + begin + write = 1'b0; + for (i=0;i<=255;i=i+1) + begin + for (j=7;j>=0;j=j-1) + begin + Byte_slv[j] = + Data_in[(i*8) + (7-j)]; + end + WByte[i] = Byte_slv; + end + if (data_cnt > 256*BYTE) + Byte_number = 255; + else + Byte_number = ((data_cnt/8) - 1); + end + end + end + + OTPP : + begin + if (data_cnt == 8) + begin + write = 1'b0; + for (j=7;j>=0;j=j-1) + begin + Byte_slv[j] = Data_in[7-j]; + end + WOTPByte = Byte_slv; + end + end + endcase + end + end + else + if (bus_cycle_state == DUMMY_BYTES) + begin + bus_cycle_state = STAND_BY; + if (((HOLDNeg_in && ~QUAD) || QUAD) && + (Instruct == RES_READ_ES) && (dummy_cnt == 0)) + write = 1'b0; + end + end + end + end + +// ///////////////////////////////////////////////////////////////////////// +// // Timing control for the Program Operations +// // start +// ///////////////////////////////////////////////////////////////////////// + + event pdone_event; + + always @(PSTART) + begin + if (PSTART && PDONE) + if (Sec_Prot[SA] == 1'b0) + begin + PDONE = 1'b0; + ->pdone_event; + end + end + + always @(pdone_event) + begin:pdone_process + PDONE = 1'b0; + #tdevice_PP PDONE = 1'b1; + end + +// ///////////////////////////////////////////////////////////////////////// +// // Timing control for the Write Status Register Operation +// // start +// ///////////////////////////////////////////////////////////////////////// + + event wdone_event; + + always @(WSTART) + begin + if (WSTART && WDONE) + begin + WDONE = 1'b0; + ->wdone_event; + end + end + + always @(wdone_event) + begin:wdone_process + WDONE = 1'b0; + #tdevice_WR WDONE = 1'b1; + end + +// ///////////////////////////////////////////////////////////////////////// +// // Timing control for the Erase Operations +// ///////////////////////////////////////////////////////////////////////// + time duration_erase; + + event edone_event; + + always @(ESTART) + begin: erase + if (ESTART && EDONE) + begin + if (Instruct == BE) + begin + duration_erase = tdevice_BE; + end + else if (Instruct == P4E || Instruct == P8E) + begin + duration_erase = tdevice_PE; + end + else + begin + duration_erase = tdevice_SE; + end + + EDONE = 1'b0; + ->edone_event; + end + end + + always @(edone_event) + begin : edone_process + EDONE = 1'b0; + #duration_erase EDONE = 1'b1; + end +// ///////////////////////////////////////////////////////////////////////// +// // Main Behavior Process +// // combinational process for next state generation +// ///////////////////////////////////////////////////////////////////////// + + reg rising_edge_PDONE = 1'b0; + reg rising_edge_EDONE = 1'b0; + reg rising_edge_WDONE = 1'b0; + reg rising_edge_DP_out = 1'b0; + reg falling_edge_write = 1'b0; + integer i; + integer j; + + always @(falling_edge_write or rising_edge_PDONE or rising_edge_WDONE + or rising_edge_EDONE or rising_edge_DP_out) + begin: StateGen1 + if (falling_edge_write) + begin + case (current_state) + IDLE : + begin + if (~write) + begin + if ((Instruct == WRR) && WEL) + begin + if (~(Status_reg[7] && ~WPNeg_in && ~QUAD)) + //HPM is disabled when the Quad I/O Mode is enabled + //(Quad bit = 1 in the Configuration Register) + next_state = WRITE_SR; + end + + else if ((Instruct == PP || Instruct == QPP) && + WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0) + next_state = PAGE_PG; + end + + else if (Instruct == OTPP && WEL) + begin + if(Address == 256 || Address == 257 || + ((Address >= 258 && Address <= 273) && + PR_LOCK1[(Address-258)/8] == 1'b1) + || Address == 274 + || Address == 275 || ((Address >= 276 && + Address <= 531) && PR_LOCK2[(Address-276)/16] + ==1'b1) || Address == 532 || Address == 533 || + ((Address >= 534 && Address <= 767) + && PR_LOCK3[(Address-534)/16] == 1'b1)) + next_state = OTP_PG; + end + + else if (Instruct == SE && WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0) + next_state = SECTOR_ER; + end + + else if (Instruct == P4E && WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0 && (((sect == 0 || + sect == 1) && ~TBPARM) || ((sect == SecNum || + sect == SecNum-1) && TBPARM))) + next_state = P4_ER; + end + + else if (Instruct == P8E && WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0 && (((sect == 0 || + sect == 1) && ~TBPARM) || ((sect == SecNum || + sect == SecNum-1) && TBPARM))) + next_state = P8_ER; + end + + else if (Instruct == BE && WEL) + begin + if (Status_reg[2]==1'b0 && Status_reg[3]==1'b0 && + Status_reg[4]==1'b0) + next_state = BULK_ER; + end + else if (Instruct == DP) + next_state = DP_DOWN_WAIT; + else + next_state = IDLE; + end + end + + DP_DOWN : + begin + if (~write) + begin + if (Instruct == RES_READ_ES) + next_state = IDLE; + end + end + + endcase + end + + if (rising_edge_PDONE) + begin + if (current_state==PAGE_PG || current_state==OTP_PG) + begin + next_state = IDLE; + end + end + + if (rising_edge_WDONE) + begin + if (current_state==WRITE_SR) + begin + next_state = IDLE; + end + end + + if (rising_edge_EDONE) + begin + if (current_state==SECTOR_ER || current_state==BULK_ER + || current_state==P4_ER || current_state==P8_ER) + begin + next_state = IDLE; + end + end + + if (rising_edge_DP_out) + begin + if (current_state==DP_DOWN_WAIT) + next_state = DP_DOWN; + end + + end + + /////////////////////////////////////////////////////////////////////////// + //FSM Output generation and general functionality + /////////////////////////////////////////////////////////////////////////// + reg rising_edge_read_out = 1'b0; + reg rising_edge_RES_out = 1'b0; + reg Instruct_event = 1'b0; + reg change_addr_event = 1'b0; + reg rising_edge_powered = 1'b0; + reg current_state_event = 1'b0; + + integer sector; + integer WData [0:255]; + integer WOTPData; + integer Addr; + integer Addr_tmp; + + always @(oe_event) + begin + oe = 1'b1; + #1 oe = 1'b0; + end + + always @(rising_edge_read_out or Instruct_event or + change_addr_event or oe or current_state_event or + falling_edge_write or EDONE or WDONE or PDONE or + CSNeg_ipd or rising_edge_RES_out or rising_edge_powered or + rising_edge_DP_out) + begin: Functionality + integer i,j; + + if (rising_edge_read_out) + begin + if (PoweredUp == 1'b1) + ->oe_event; + end + + if (Instruct_event) + begin + read_cnt = 0; + rd_fast = 1'b1; + rd_slow = 1'b0; + rd_jedec = 1'b0; + dual = 1'b0; + if (current_state == DP_DOWN_WAIT) + begin + if (DP_in == 1'b1) + begin + $display ("Command results can be corrupted"); + end + end + if (Instruct == DH_READ || Instruct == QH_READ) + begin + mpm_mode = 1; + end + end + + if (rising_edge_powered) + begin + //The Configuration Register FREEZE bit is cleared. + Sec_conf_reg[0] = 1'b0; + + if (BPNV == 1 && FREEZE == 0) + begin + //When BPNV is set to ‘1’,the BP2-0 bits in the Status Register + //are volatile and will be reset to binary 111 after power on reset. + Status_reg[4] = 1'b1;// BP2 + Status_reg[3] = 1'b1;// BP1 + Status_reg[2] = 1'b1;// BP0 + change_BP = 1'b1; + #1 change_BP = 1'b0; + end + end + + if (change_addr_event) + begin + read_addr = Address; + end + + if (oe || current_state_event) + begin + case (current_state) + IDLE : + begin + if (oe && ~RES_in) + begin + if (Instruct == RDSR) + begin + //Read Status Register + SOut_zd = Status_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + if (Instruct == RCR) + begin + //Read Security Conf. Register + SOut_zd = Sec_conf_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + else if (Instruct == READ || Instruct == FAST_READ) + begin + //Read Memory array + if (Instruct == READ) + begin + rd_fast = 1'b0; + rd_jedec = 1'b0; + rd_slow = 1'b1; + end + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else if (Instruct == DUAL_READ || Instruct == DH_READ) + begin + //Read Memory array + rd_fast = 1'b0; + rd_slow = 1'b0; + rd_jedec = 1'b0; + dual = 1'b1; + data_out[7:0] = Mem[read_addr]; + SOut_zd = data_out[7-2*read_cnt]; + SIOut_zd = data_out[6-2*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 4) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else if (Instruct == QUAD_READ || Instruct == QH_READ) + begin + //Read Memory array + rd_fast = 1'b0; + rd_slow = 1'b0; + rd_jedec = 1'b0; + dual = 1'b1; + data_out[7:0] = Mem[read_addr]; + HOLDNegOut_zd = data_out[7-4*read_cnt]; + WPNegOut_zd = data_out[6-4*read_cnt]; + SOut_zd = data_out[5-4*read_cnt]; + SIOut_zd = data_out[4-4*read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 2) + begin + read_cnt = 0; + if (read_addr == AddrRANGE) + read_addr = 0; + else + read_addr = read_addr + 1; + end + end + else if (Instruct == OTPR) + begin + if(read_addr>=OTPLoAddr && read_addr<=OTPHiAddr) + begin + //Read OTP Memory array + rd_fast = 1'b1; + rd_slow = 1'b0; + rd_jedec = 1'b0; + dual = 1'b0; + data_out = OTPMem[read_addr]; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else + begin + //OTP Read operation will not wrap to the + //starting address after the OTP address is at + //its maximum; + //instead, the data will be indeterminate. + SOut_zd = 1'bX; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + else if (Instruct == RDID) + begin + // Read ID + rd_fast = 1'b0; + rd_slow = 1'b0; + rd_jedec = 1'b1; + dual = 1'b0; + ident_out = {Manuf_ID,DeviceID,ExtendedBytes, + ReservedBytes,ReservedBytes, + ReservedBytes,CFI_array_tmp}; + SOut_zd = ident_out[647-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 648) + read_cnt = 0; + end + else if (Instruct == READ_ID) + begin + // --Read Manufacturer and Device ID + if (read_addr % 2 == 0) + begin + data_out[7:0] = Manuf_ID; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = read_addr + 1; + end + end + else if (read_addr % 2 == 1) + begin + data_out[7:0] = ES; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + begin + read_cnt = 0; + read_addr = 0; + end + end + end + end + else if (oe && RES_in) + begin + $display ("Command results can be corrupted"); + SOut_zd = 1'bX; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + + WRITE_SR, + SECTOR_ER, + BULK_ER, + P4_ER, + P8_ER, + OTP_PG, + PAGE_PG : + begin + if (oe && Instruct == RDSR) + begin + //Read Status Register + SOut_zd = Status_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + if (oe && Instruct == RCR) + begin + //Read Security Conf. Register + SOut_zd = Sec_conf_reg[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + DP_DOWN : + begin + if (oe && Instruct == RES_READ_ES) + begin + // Read ID + data_out[7:0] = ES; + SOut_zd = data_out[7-read_cnt]; + read_cnt = read_cnt + 1; + if (read_cnt == 8) + read_cnt = 0; + end + end + + endcase + end + + if (falling_edge_write) + begin + case (current_state) + IDLE : + begin + if (~write) + begin + if (RES_in == 1'b1 && Instruct != DP) + begin + $display ("Command results can be corrupted"); + end + if (Instruct == WREN) + Status_reg[1] = 1'b1; + else if (Instruct == WRDI) + Status_reg[1] = 1'b0; + else if (Instruct == WRR && WEL) + begin + if (~(Status_reg[7] && ~WPNeg_in && ~QUAD)) + begin + WSTART = 1'b1; + WSTART <= #1 1'b0; + Status_reg[0] = 1'b1; + end + else + begin + Status_reg[1] = 0; + end + end + else if ((Instruct == PP || Instruct == QPP) && + WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0) + begin + PSTART = 1'b1; + PSTART <= #1 1'b0; + Status_reg[0] = 1'b1; //WIP + Addr = Address; + Addr_tmp = Address; + SA = sect; + wr_cnt = Byte_number; + for (i=0;i<=wr_cnt;i=i+1) + begin + if (Viol != 1'b0) + WData[i] = -1; + else + WData[i] = WByte[i]; + end + end + else + begin + Status_reg[1] = 1'b0; + end + end + else if (Instruct == OTPP && WEL) + begin + if(Address == 256 || Address == 257 || + ((Address >= 258 && Address <= 273) && + PR_LOCK1[(Address-258)/8] == 1'b1) + || Address == 274 + || Address == 275 || ((Address >= 276 && + Address <= 531) && PR_LOCK2[(Address-276)/16] + ==1'b1) || Address == 532 || Address == 533 || + ((Address >= 534 && Address <= 767) + && PR_LOCK3[(Address-534)/16] == 1'b1)) + begin + PSTART = 1'b1; + PSTART <= #1 1'b0; + Status_reg[0] = 1'b1; //WIP + Addr = Address; + if (Viol != 1'b0 ) + WOTPData = -1; + else + WOTPData = WOTPByte; + end + else if (Address < 100 || Address > 767 ) + begin + Status_reg[6] = 1'b1; + Status_reg[1] = 1'b0; + end + else + begin + Status_reg[1] = 1'b0; + end + end + else if (Instruct == SE && WEL) + begin + sect = Address / 24'h10000; + if (Sec_Prot[sect] == 1'b0) + begin + ESTART = 1'b1; + ESTART <= #1 1'b0; + Status_reg[0] = 1'b1; + Addr = Address; + end + else + begin + Status_reg[1] = 1'b0; + end + end + else if (Instruct == BE && WEL) + begin + if(Status_reg[2]==1'b0 && Status_reg[3]==1'b0 && + Status_reg[4]==1'b0) + begin + ESTART = 1'b1; + ESTART <= #1 1'b0; + Status_reg[0] = 1'b1; + end + else + begin + Status_reg[1] = 1'b0; + end + end + else if (Instruct == P4E && WEL) + begin + sect = Address / 24'h10000; + if (((sect == 0 || + sect == 1) && ~TBPARM) || ((sect == SecNum || + sect == SecNum-1) && TBPARM)) + begin + if (Sec_Prot[sect] == 1'b0) + begin + ESTART = 1'b1; + ESTART <= #1 1'b0; + Status_reg[0] = 1'b1; + Addr = Address; + end + else + begin + Status_reg[1] = 1'b0; + end + end + else + begin + Status_reg[5] = 1'b1; + Status_reg[1] = 1'b0; + end + end + else if (Instruct == P8E && WEL) + begin + sect = Address / 24'h10000; + if (((sect == 0 || + sect == 1) && ~TBPARM) || ((sect == SecNum || + sect == SecNum-1) && TBPARM)) + begin + if (Sec_Prot[sect] == 1'b0) + begin + ESTART = 1'b1; + ESTART <= #1 1'b0; + Status_reg[0] = 1'b1; + Addr = Address; + end + else + begin + Status_reg[1] = 1'b0; + end + end + else + begin + Status_reg[5] = 1'b1; + Status_reg[1] = 1'b0; + end + end + else if (Instruct == CLSR) + begin + Status_reg[5] = 1'b0; + Status_reg[6] = 1'b0; + end + else if (Instruct == DP) + begin + RES_in <= 1'b0; + DP_in = 1'b1; + end + else if (Instruct == RES_READ_ES) + begin + RES_in <= 1'b1; + end + end + + end + + DP_DOWN : + begin + if (~write) + begin + if (Instruct == RES_READ_ES) + RES_in = 1'b1; + end + end + + endcase + end + + if(current_state_event || EDONE) + begin + case (current_state) + + SECTOR_ER : + begin + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = -1; + end + if (EDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + BULK_ER : + begin + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = -1; + end + + if (EDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + for (i=0;i<=AddrRANGE;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + P4_ER : + begin + ADDRHILO_PB4(AddrLo, AddrHi, Addr); + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = -1; + end + if (EDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + P8_ER : + begin + ADDRHILO_PB8(AddrLo, AddrHi, Addr); + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = -1; + end + if (EDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + for (i=AddrLo;i<=AddrHi;i=i+1) + begin + Mem[i] = MaxData; + end + end + end + endcase + end + + if(current_state_event || WDONE) + begin + if (current_state == WRITE_SR) + begin + if (WDONE) + begin + Status_reg[0] = 1'b0;//WIP + Status_reg[1] = 1'b0;//WEL + //SRWD bit + Status_reg[7] = Status_reg_in[7];//MSB first + + if (FREEZE == 0) + //The Freeze Bit, when set to 1, locks the current + //state of the BP2-0 bits in Status Register, + //the TBPROT and TBPARM bits in the Config Register + //As long as the FREEZE bit remains cleared to logic + //'0', the other bits of the Configuration register + //including FREEZE are writeable. + begin + Status_reg[4] = Status_reg_in[4];// BP2 + Status_reg[3] = Status_reg_in[3];// BP1 + Status_reg[2] = Status_reg_in[2];// BP0 + + if (cfg_write) + begin + Sec_conf_reg[0] = Sec_conf_reg_in[0];// FREEZE + + if (TBPARM == 1'b0) + begin + Sec_conf_reg[2] = Sec_conf_reg_in[2];//TBPARM + end + + if (TBPROT == 1'b0) + begin + Sec_conf_reg[5] = Sec_conf_reg_in[5];//TBPROT + end + + Sec_conf_reg[1] = Sec_conf_reg_in[1];// QUAD + + if (BPNV == 1'b0) + begin + Sec_conf_reg[3] = Sec_conf_reg_in[3];//BPNV + end + end + + change_BP = 1'b1; + #1 change_BP = 1'b0; + end + + end + end + end + + if(current_state_event || PDONE) + begin + if (current_state == PAGE_PG) + begin + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt = 0; + + for (i=0;i<=wr_cnt;i=i+1) + begin + new_int = WData[i]; + old_int = Mem[Addr + i - cnt]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + if (~old_bit[j]) + new_bit[j]=1'b0; + new_int=new_bit; + end + + WData[i]= new_int; + end + else + begin + WData[i] = -1; + end + + Mem[Addr + i -cnt] = - 1; + + if ((Addr + i) == AddrHi) + begin + Addr = AddrLo; + cnt = i + 1; + end + end + + cnt = 0; + + if (PDONE) + begin + Status_reg[0] = 1'b0;//wip + Status_reg[1] = 1'b0; + for (i=0;i<=wr_cnt;i=i+1) + begin + Mem[Addr_tmp + i - cnt] = WData[i]; + if ((Addr_tmp + i) == AddrHi) + begin + Addr_tmp = AddrLo; + cnt = i + 1; + end + end + end + end + end + + if(current_state_event || PDONE) + begin + if (current_state == OTP_PG) + begin + new_int = WOTPData; + old_int = OTPMem[Addr]; + if (new_int > -1) + begin + new_bit = new_int; + if (old_int > -1) + begin + old_bit = old_int; + for(j=0;j<=7;j=j+1) + begin + if (~old_bit[j]) + new_bit[j] = 1'b0; + end + new_int = new_bit; + end + WOTPData = new_int; + end + else + begin + WOTPData = -1; + end + OTPMem[Addr] = -1; + if (PDONE) + begin + Status_reg[0] = 1'b0; + Status_reg[1] = 1'b0; + OTPMem[Addr] = WOTPData; + PR_LOCK1 = {OTPMem[257],OTPMem[256]}; + + PR_LOCK1[15:8] = OTPMem[257]; + PR_LOCK1[7:0] = OTPMem[256]; + PR_LOCK2[15:8] = OTPMem[275]; + PR_LOCK2[7:0] = OTPMem[274]; + PR_LOCK3[15:8] = OTPMem[533]; + PR_LOCK3[7:0] = OTPMem[532]; + end + end + end + + //Output Disable Control + if (CSNeg_ipd ) + begin + SIOut_zd = 1'bZ; + HOLDNegOut_zd = 1'bZ; + WPNegOut_zd = 1'bZ; + SOut_zd = 1'bZ; + end + + if (rising_edge_RES_out) + begin + if(RES_out) + begin + RES_in = 1'b0; + end + end + + if (rising_edge_DP_out) + begin + if (current_state == DP_DOWN_WAIT) + begin + DP_in = 1'b0; + end + end + + end + + always @(change_BP) + begin + if (change_BP) + begin + case (Status_reg[4:2]) + 3'b000 : + begin + Sec_Prot = 256'h0; + end + + 3'b001 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)*63/64] = 1'b1; + Sec_Prot[(SecNum+1)*63/64 - 1 : 0] = 126'h0; + end + else + begin + Sec_Prot[(SecNum+1)/64 - 1 : 0] = 2'b11; + Sec_Prot[SecNum : (SecNum+1)/64] = 126'h0; + end + end + + 3'b010 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)*31/32] = 4'hF; + Sec_Prot[(SecNum+1)*31/32 - 1 : 0] = 124'h0; + end + else + begin + Sec_Prot[(SecNum+1)/32 - 1 : 0] = 4'hF; + Sec_Prot[SecNum : (SecNum+1)/32] = 124'h0; + end + end + + 3'b011 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)*15/16] = 8'hFF; + Sec_Prot[(SecNum+1)*15/16 - 1 : 0] = 120'h0; + end + else + begin + Sec_Prot[(SecNum+1)/16 - 1 : 0] = 8'hFF; + Sec_Prot[SecNum : (SecNum+1)/16] = 120'h0; + end + end + + 3'b100 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)*7/8] = 16'hFFFF; + Sec_Prot[(SecNum+1)*7/8 - 1 : 0] = 112'h0; + end + else + begin + Sec_Prot[(SecNum+1)/8 - 1 : 0] = 16'hFFFF; + Sec_Prot[SecNum : (SecNum+1)/8] = 112'h0; + end + end + + 3'b101 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)*3/4] + = 32'hFFFFFFFF; + Sec_Prot[(SecNum+1)*3/4 - 1 : 0] = 96'h0; + end + else + begin + Sec_Prot[(SecNum+1)/4 - 1 : 0] + = 32'hFFFFFFFF; + Sec_Prot[SecNum : (SecNum+1)/4] = 96'h0; + end + end + + 3'b110 : + begin + if (~Sec_conf_reg[5]) + begin + Sec_Prot[SecNum : (SecNum+1)/2] + = 64'hFFFFFFFFFFFFFFFF; + Sec_Prot[(SecNum+1)/2 - 1 : 0] = 64'h0; + end + else + begin + Sec_Prot[(SecNum+1)/2 - 1 : 0] + = 64'hFFFFFFFFFFFFFFFF; + Sec_Prot[SecNum : (SecNum+1)/2] = 64'h0; + end + end + + 3'b111 : + begin + Sec_Prot = 128'hFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + end + + endcase + end + end + + assign fast_rd = rd_fast; + assign rd = rd_slow; + assign rd_jid = rd_jedec; + + always @(SOut_zd or HOLDNeg_in or SIOut_zd) + begin + if (~HOLDNeg_in && ~QUAD) + begin + hold_mode = 1'b1; + SIOut_z = 1'bZ; + SOut_z = 1'bZ; + end + else + begin + if (hold_mode) + begin + SIOut_z <= #(tpd_HOLDNeg_SO) SIOut_zd; + SOut_z <= #(tpd_HOLDNeg_SO) SOut_zd; + hold_mode = 1'b0; + end + else + begin + SIOut_z = SIOut_zd; + SOut_z = SOut_zd; + hold_mode = 1'b0; + end + end + end + +// Procedure ADDRHILO_SEC + task ADDRHILO_SEC; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 20'h10000; + AddrLOW = sector * 20'h10000; + AddrHIGH = sector * 20'h10000 + 16'hFFFF; + end + endtask + +// Procedure ADDRHILO_PG + task ADDRHILO_PG; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer page; + begin + + page = Addr / 16'h100; + AddrLOW = page * 16'h100; + AddrHIGH = page * 16'h100 + 8'hFF; + + end + endtask + +// Procedure ADDRHILO_PB4 + task ADDRHILO_PB4; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 20'h10000; + if (sector == 0 || sector == 1 || + sector == SecNum || sector == SecNum-1) + begin + AddrLOW = (Address/(SecSize_4+1))*(SecSize_4+1); + AddrHIGH = (Address/(SecSize_4+1))*(SecSize_4+1) + SecSize_4; + end + end + endtask + +// Procedure ADDRHILO_PB8 + task ADDRHILO_PB8; + inout AddrLOW; + inout AddrHIGH; + input Addr; + integer AddrLOW; + integer AddrHIGH; + integer Addr; + integer sector; + begin + sector = Addr / 20'h10000; + if (sector == 0 || sector == SecNum-1) + begin + AddrLOW = (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH = (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + end + if (sector == 1) + begin + AddrLOW = (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH = (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + if (AddrHIGH > 20'h1FFFF) + AddrHIGH = 20'h1FFFF; + end + if (sector == SecNum) + begin + AddrLOW = (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH = (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + if (AddrHIGH > 24'h3FFFFF) + AddrHIGH = 24'h3FFFFF; + end + end + endtask + + always @(negedge CSNeg_ipd) + begin + falling_edge_CSNeg_ipd = 1'b1; + #1 falling_edge_CSNeg_ipd = 1'b0; + end + + always @(posedge SCK_ipd) + begin + rising_edge_SCK_ipd = 1'b1; + #1 rising_edge_SCK_ipd = 1'b0; + end + + always @(negedge SCK_ipd) + begin + falling_edge_SCK_ipd = 1'b1; + #1 falling_edge_SCK_ipd = 1'b0; + end + + always @(posedge CSNeg_ipd) + begin + rising_edge_CSNeg_ipd = 1'b1; + #1 rising_edge_CSNeg_ipd = 1'b0; + end + + always @(negedge write) + begin + falling_edge_write = 1'b1; + #1 falling_edge_write = 1'b0; + end + + always @(posedge PDONE) + begin + rising_edge_PDONE = 1'b1; + #1 rising_edge_PDONE = 1'b0; + end + + always @(posedge WDONE) + begin + rising_edge_WDONE = 1'b1; + #1 rising_edge_WDONE = 1'b0; + end + + always @(posedge EDONE) + begin + rising_edge_EDONE = 1'b1; + #1 rising_edge_EDONE = 1'b0; + end + + always @(posedge DP_out) + begin + rising_edge_DP_out = 1'b1; + #1 rising_edge_DP_out = 1'b0; + end + + always @(posedge RES_out) + begin + rising_edge_RES_out = 1'b1; + #1 rising_edge_RES_out = 1'b0; + end + + always @(posedge read_out) + begin + rising_edge_read_out = 1'b1; + #1 rising_edge_read_out = 1'b0; + end + + always @(posedge PoweredUp) + begin + rising_edge_powered = 1'b1; + #1 rising_edge_powered = 1'b0; + end + + always @(Instruct) + begin + Instruct_event = 1'b1; + #1 Instruct_event = 1'b0; + end + + always @(change_addr) + begin + change_addr_event = 1'b1; + #1 change_addr_event = 1'b0; + end + + always @(current_state) + begin + current_state_event = 1'b1; + #1 current_state_event = 1'b0; + end + +endmodule \ No newline at end of file diff --git a/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p.vhd b/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p.vhd new file mode 100644 index 0000000..4eba2b4 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p.vhd @@ -0,0 +1,2532 @@ +------------------------------------------------------------------------------- +-- File Name: s25fl032p.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2011 Spansion, LLC. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 D.Stanojkovic 08 Jan 22 Inital Release +-- V1.1 D.Stanojkovic 08 Feb 20 BP bits setting corrected +-- V1.2 D.Stanojkovic 08 Mar 05 MPM mode corrected +-- V1.3 D.Stanojkovic 08 Mar 20 MPM mode removed +-- V1.4 J.Stoickov 08 Sep 16 Latest datasheet aligned +-- V1.5 J.Stoickov 08 Dec 10 Latest datasheet aligned +-- (S25FL129 064 032P) +-- Program Error bit will not be +-- set after programming in +-- protect memory region +-- V1.6 V.Mancev 10 Sep 29 Implementation of internal pull-up +-- for HOLDNeg and WPNeg pins +-- V1.7 V.Mancev 11 Dec 15 Latest datasheet aligned +-- (S25FL032P_00_05) +---------------------------------------------------------------------------- +--- +-- PART DESCRIPTION: +-- +-- Library: FLASH +-- Technology: FLASH MEMORY +-- Part: S25FL032P +-- +-- Description: 32 Megabit Serial Flash Memory with 104 MHz SPI Bus Interface +-- +------------------------------------------------------------------------------- +-- Known Bugs: +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + USE STD.textio.ALL; + USE IEEE.VITAL_timing.ALL; + USE IEEE.VITAL_primitives.ALL; + +LIBRARY FMF; USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY s25fl032p IS + GENERIC ( + -- tipd delays: interconnect path delays + tipd_SCK : VitalDelayType01 := VitalZeroDelay01; + tipd_SI : VitalDelayType01 := VitalZeroDelay01; + tipd_SO : VitalDelayType01 := VitalZeroDelay01; + + tipd_CSNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_HOLDNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays + tpd_SCK_SO : VitalDelayType01Z := UnitDelay01Z; -- tV + tpd_SCK_SI : VitalDelayType01Z := UnitDelay01Z; -- tV + tpd_CSNeg_SO : VitalDelayType01Z := UnitDelay01Z; -- tDIS + tpd_HOLDNeg_SO : VitalDelayType01Z := UnitDelay01Z; -- tLZ,tHZ + + --tsetup values + tsetup_CSNeg_SCK : VitalDelayType := UnitDelay; -- tCSS / + tsetup_HOLDNeg_SCK : VitalDelayType := UnitDelay; -- tHC / + tsetup_SI_SCK : VitalDelayType := UnitDelay; -- tsuDAT / + tsetup_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPS \ + + --thold values + thold_CSNeg_SCK : VitalDelayType := UnitDelay; -- tCSH / + thold_HOLDNeg_SCK : VitalDelayType := UnitDelay; -- tCHHH / + thold_SI_SCK : VitalDelayType := UnitDelay; -- thdDAT / + thold_WPNeg_CSNeg : VitalDelayType := UnitDelay; -- tWPH \ + + --tpw values: pulse width + tpw_SCK_serial_fast_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_serial_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_dual_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_rd_jid_posedge : VitalDelayType := UnitDelay; -- tWH + tpw_SCK_serial_fast_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_serial_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_dual_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_SCK_rd_jid_negedge : VitalDelayType := UnitDelay; -- tWL + tpw_CSNeg_read_posedge : VitalDelayType := UnitDelay; -- tCS + tpw_CSNeg_pgm_posedge : VitalDelayType := UnitDelay; -- tCS + + -- tperiod min (calculated as 1/max freq) + tperiod_SCK_serial_rd : VitalDelayType := UnitDelay;--fSCK=40MHz + tperiod_SCK_serial_fast_rd : VitalDelayType := UnitDelay;--fSCK=104MHz + tperiod_SCK_dual_fast_rd : VitalDelayType := UnitDelay;--fSCK=80MHz + tperiod_SCK_serial_rd_jid : VitalDelayType := UnitDelay;--fSCK=50MHz + + -- tdevice values: values for internal delays + -- Page Program Operation + tdevice_PP : VitalDelayType := 3 ms; + -- Page Program Operation (ACC=9V)) + tdevice_EP : VitalDelayType := 2.4 ms; --tPP + -- Sector Erase Operation + tdevice_SE : VitalDelayType := 2 sec; --tSE + -- Bulk Erase Operation + tdevice_BE : VitalDelayType := 64 sec; --tBE + -- Write Status Register Operation + tdevice_WR : VitalDelayType := 50 ms; --tW + -- Deep Power Down + tdevice_DP : VitalDelayType := 10 us; --tDP + -- Release from Software Protect Mode + tdevice_RES : VitalDelayType := 30 us; --tRES + -- Parameter block erase + tdevice_PE : VitalDelayType := 800 ms; --tPE + -- VCC (min) to CS# Low + tdevice_PU : VitalDelayType := 300 us; --tPU + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING := "s25fl032p.mem"; + otp_file_name : STRING := "s25fl032pOTP.mem"; + + UserPreload : BOOLEAN := FALSE; --TRUE; + LongTimming : BOOLEAN := TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING := DefaultTimingModel + ); + PORT ( + SCK : IN std_ulogic := 'U'; -- serial clock input + SI : INOUT std_ulogic := 'U'; -- serial data input + CSNeg : IN std_ulogic := 'U'; -- chip select input + HOLDNeg : INOUT std_ulogic := 'U'; -- hold input + WPNeg : INOUT std_ulogic := 'U'; -- write protect input + SO : INOUT std_ulogic := 'U' -- SO + ); + ATTRIBUTE VITAL_LEVEL0 of s25fl032p : ENTITY IS TRUE; +END s25fl032p; + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of s25fl032p IS + ATTRIBUTE VITAL_LEVEL0 OF vhdl_behavioral : ARCHITECTURE IS TRUE; + + CONSTANT PartID : STRING := "s25fl032p"; + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 + CONSTANT SecSize_4 : NATURAL := 16#FFF#; --4095 + CONSTANT SecSize_8 : NATURAL := 16#1FFF#; --8191 + CONSTANT OTPSize : NATURAL := 511; + CONSTANT OTPLoAddr : NATURAL := 16#100#; + CONSTANT OTPHiAddr : NATURAL := 16#2FF#; + CONSTANT SecNum : NATURAL := 63; + CONSTANT PageNum : NATURAL := 16#3FFF#; + CONSTANT HiAddrBit : NATURAL := 23; + CONSTANT AddrRANGE : NATURAL := 16#3FFFFF#; + CONSTANT BYTE : NATURAL := 8; + --Manufacturer Identification + CONSTANT Manuf_ID : NATURAL := 16#01#; + --Electronic Signature + CONSTANT ES : NATURAL := 16#15#; + --Device ID + --Manufacturer Identification && Memory Type && Memory Capacity + CONSTANT Jedec_ID : NATURAL := 16#20#; -- first byte of Device ID + CONSTANT DeviceID : NATURAL := 16#0215#; + CONSTANT ExtendedBytes : NATURAL := 16#4D#; + CONSTANT ReservedBytes : NATURAL := 16#00#; + +-- interconnect path delay signals + SIGNAL SCK_ipd : std_ulogic := 'U'; + SIGNAL SI_ipd : std_ulogic := 'U'; + SIGNAL SO_ipd : std_ulogic := 'U'; + SIGNAL CSNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_ipd : std_ulogic := 'U'; + SIGNAL WPNeg_ipd : std_ulogic := 'U'; + SIGNAL HOLDNeg_pullup : std_ulogic := 'U'; + SIGNAL WPNeg_pullup : std_ulogic := 'U'; + + --- internal delays + SIGNAL PP_in : std_ulogic := '0'; + SIGNAL PP_out : std_ulogic := '0'; + SIGNAL PU_in : std_ulogic := '0'; + SIGNAL PU_out : std_ulogic := '0'; + SIGNAL SE_in : std_ulogic := '0'; + SIGNAL SE_out : std_ulogic := '0'; + SIGNAL BE_in : std_ulogic := '0'; + SIGNAL BE_out : std_ulogic := '0'; + SIGNAL EP_in : std_ulogic := '0'; + SIGNAL EP_out : std_ulogic := '0'; + SIGNAL WR_in : std_ulogic := '0'; + SIGNAL WR_out : std_ulogic := '0'; + SIGNAL DP_in : std_ulogic := '0'; + SIGNAL DP_out : std_ulogic := '0'; + SIGNAL PE_in : std_ulogic := '0'; + SIGNAL PE_out : std_ulogic := '0'; + SIGNAL RES_in : std_ulogic := '0'; + SIGNAL RES_out : std_ulogic := '0'; + +BEGIN + --------------------------------------------------------------------------- + -- Internal Delays + --------------------------------------------------------------------------- + -- Artificial VITAL primitives to incorporate internal delays + PP :VitalBuf(PP_out, PP_in, (tdevice_PP ,UnitDelay)); + PU :VitalBuf(PU_out, PU_in, (tdevice_PU ,UnitDelay)); + SE :VitalBuf(SE_out, SE_in, (tdevice_SE ,UnitDelay)); + BE :VitalBuf(BE_out, BE_in, (tdevice_BE ,UnitDelay)); + EP :VitalBuf(EP_out, EP_in, (tdevice_EP ,UnitDelay)); + WR :VitalBuf(WR_out, WR_in, (tdevice_WR ,UnitDelay)); + DP :VitalBuf(DP_out, DP_in, (tdevice_DP ,UnitDelay)); + PE :VitalBuf(PE_out, PE_in, (tdevice_PE ,UnitDelay)); + RES :VitalBuf(RES_out, RES_in, (tdevice_RES ,UnitDelay)); + + --------------------------------------------------------------------------- + -- Wire Delays + --------------------------------------------------------------------------- + WireDelay : BLOCK + BEGIN + + w_1 : VitalWireDelay (SCK_ipd, SCK, tipd_SCK); + w_2 : VitalWireDelay (SI_ipd, SI, tipd_SI); + w_3 : VitalWireDelay (SO_ipd, SO, tipd_SO); + + w_4: VitalWireDelay (CSNeg_ipd, CSNeg, tipd_CSNeg); + w_5: VitalWireDelay (HOLDNeg_ipd, HOLDNeg, tipd_HOLDNeg); + w_6: VitalWireDelay (WPNeg_ipd, WPNeg, tipd_WPNeg); + + END BLOCK; + + --------------------------------------------------------------------------- + -- Main Behavior Block + --------------------------------------------------------------------------- + Behavior: BLOCK + + PORT ( + SCK : IN std_ulogic := 'U'; + SIIn : IN std_ulogic := 'U'; + SIOut : OUT std_ulogic := 'U'; + SOIn : IN std_logic := 'U'; + SOut : OUT std_logic := 'U'; + CSNeg : IN std_ulogic := 'U'; + HOLDNegIn : IN std_ulogic := 'U'; + HOLDNegOut : OUT std_ulogic := 'U'; + WPNegIn : IN std_ulogic := 'U'; + WPNegOut : OUT std_ulogic := 'U' + ); + PORT MAP ( + SCK => SCK_ipd, + SIIn => SI_ipd, + + SOIn => SO_ipd, + + SOut => SO, + + CSNeg => CSNeg_ipd, + + HOLDNegIn => HOLDNeg_ipd, + WPNegIn => WPNeg_ipd, + + SIOut => SI, + WPNegOut => WPNeg, + HOLDNegOut => HOLDNeg + ); + + -- State Machine : State_Type + TYPE state_type IS (IDLE, + WRITE_SR, + PAGE_PG, + OTP_PG, + SECTOR_ER, + BULK_ER, + P4_ER, + P8_ER, + DP_DOWN_WAIT, + DP_DOWN + ); + + -- Instruction Type + TYPE instruction_type IS (NONE, + WREN, + WRDI, + WRR, + RDSR, + READ, + READ_ID, + RDID, + FAST_READ, + DUAL_READ, + QUAD_READ, + DH_READ, + QH_READ, + SE, + BE, + PP, + QPP, + DP, + RES_READ_ES, + ENTER_PRL, + EXIT_PRL, + CLSR, + RCR, + P4E, + P8E, + OTPR, + OTPP + ); + + TYPE WByteType IS ARRAY (0 TO 255) OF INTEGER RANGE -1 TO MaxData; + --Flash Memory Array + TYPE MemArray IS ARRAY (0 TO AddrRANGE) OF INTEGER + RANGE -1 TO MaxData; + --OTP Memory Array + TYPE OTPArr IS ARRAY (OTPLoAddr TO OTPHiAddr) OF INTEGER + RANGE -1 TO MaxData; + + --------------------------------------------------------------------------- + -- memory declaration + --------------------------------------------------------------------------- + SHARED VARIABLE Mem : MemArray := (OTHERS => MaxData); + -- OTP Sector + SHARED VARIABLE OTPMem : OTPArr := (OTHERS => MaxData); + + SIGNAL WByte : WByteType := (OTHERS => 0); + SIGNAL WOTPByte : INTEGER RANGE -1 TO MaxData; + -- states + SIGNAL current_state : state_type; + SIGNAL next_state : state_type; + + SIGNAL Instruct : instruction_type; + --zero delay signal + SIGNAL SOut_zd : std_logic := 'Z'; + SIGNAL SIOut_zd : std_logic := 'Z'; + SIGNAL HOLDNegOut_zd : std_logic := 'Z'; + SIGNAL WPNegOut_zd : std_logic := 'Z'; + --HOLD delay on output data + SIGNAL SOut_z : std_logic := 'Z'; + SIGNAL SIOut_z : std_logic := 'Z'; + -- powerup + SIGNAL PoweredUp : std_logic := '0'; + + SHARED VARIABLE Status_reg : std_logic_vector(7 downto 0) + := (others => '0'); + + SIGNAL Status_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Status register Write In Progress Bit + ALIAS WIP :std_logic IS Status_reg(0); + -- Status register Write Enable Latch Bit + ALIAS WEL :std_logic IS Status_reg(1); + -- Status register block protect Bits + ALIAS BP0 :std_logic IS Status_reg(2); + ALIAS BP1 :std_logic IS Status_reg(3); + ALIAS BP2 :std_logic IS Status_reg(4); + -- status register Erase Error bit + ALIAS E_ERR :std_logic IS Status_reg(5); + -- status register Program Error bit + ALIAS P_ERR :std_logic IS Status_reg(6); + -- status register write disable + ALIAS SRWD :std_logic IS Status_reg(7); + + SHARED VARIABLE Sec_conf_reg : std_logic_vector(7 downto 0) + := (others => '0'); + + SIGNAL Sec_conf_reg_in : std_logic_vector(7 downto 0) + := (others => '0'); + + -- Configuration Register FREEZE bit + ALIAS FREEZE :std_logic IS Sec_conf_reg(0); + -- Configuration Register QUAD bit + ALIAS QUAD :std_logic IS Sec_conf_reg(1); + -- Configuration Register TBPARM bit + ALIAS TBPARM :std_logic IS Sec_conf_reg(2); + -- Configuration Register BPNV bit + ALIAS BPNV :std_logic IS Sec_conf_reg(3); + -- Security Configuration Register the TBPROT bit + ALIAS TBPROT :std_logic IS Sec_conf_reg(5); + + -- The Lock Protection Registers for OTP Memory space + SHARED VARIABLE PR_LOCK1 :std_logic_vector(15 downto 0); + SHARED VARIABLE PR_LOCK2 :std_logic_vector(15 downto 0); + SHARED VARIABLE PR_LOCK3 :std_logic_vector(15 downto 0); + + --Command Register + SIGNAL write : std_logic := '0'; + SIGNAL cfg_write : std_logic := '0'; + SIGNAL read_out : std_logic := '0'; + + SIGNAL fast_rd : boolean := true; + SIGNAL rd : boolean := false; + SIGNAL dual : boolean := false; + SIGNAL rd_jid : boolean := false; + + SHARED VARIABLE hold_mode : boolean := false; + SHARED VARIABLE mpm_mode : boolean := false; + + SHARED VARIABLE read_cnt : NATURAL := 0; + + SIGNAL change_addr : std_logic := '0'; + + SIGNAL change_BP : std_logic := '0'; + + --FSM control signals + SIGNAL PDONE : std_logic := '1'; -- Page Prog. Done + SIGNAL PSTART : std_logic := '0'; --Start Page Programming + + SIGNAL WDONE : std_logic := '1'; -- Write. Done + SIGNAL WSTART : std_logic := '0'; --Start Write + + SIGNAL ESTART : std_logic := '0'; --Start Erase + SIGNAL EDONE : std_logic := '1'; --Erase Done + + -- Sector and subsector addresses + SIGNAL SA : NATURAL RANGE 0 TO SecNum := 0; + SHARED VARIABLE sect : NATURAL RANGE 0 TO SecNum; + + SIGNAL Byte_number : NATURAL RANGE 0 TO 255 := 0; + + -- Sector is protect if '1' + SHARED VARIABLE Sec_Prot : std_logic_vector(SecNum downto 0) := + (OTHERS => '0'); + + SHARED VARIABLE BP : std_logic_vector(2 downto 0) := "000"; + + SIGNAL Address : NATURAL RANGE 0 TO AddrRANGE := 0; + + -- timing check violation + SIGNAL Viol : X01 := '0'; + + PROCEDURE ADDRHILO_SEC( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE sector : NATURAL RANGE 0 TO SecNum; + BEGIN + sector := Addr/16#10000#; + AddrLOW := sector*16#10000#; + AddrHIGH := sector*16#10000# + 16#0FFFF#; + END ADDRHILO_SEC; + + PROCEDURE ADDRHILO_PG( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE page : NATURAL RANGE 0 TO PageNum; + BEGIN + page := Addr/16#100#; + AddrLOW := Page*16#100#; + AddrHIGH := Page*16#100# + 16#FF#; + END AddrHILO_PG; + + PROCEDURE ADDRHILO_PB4( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE Sec : NATURAL RANGE 0 TO SecNum; + BEGIN + Sec := Addr/16#10000#; + IF Sec = 0 OR Sec = 1 OR Sec = SecNum OR Sec = SecNum - 1 THEN + AddrLOW := (Address/(SecSize_4+1))*(SecSize_4+1); + AddrHIGH := (Address/(SecSize_4+1))*(SecSize_4+1) + SecSize_4; + END IF; + END ADDRHILO_PB4; + + PROCEDURE ADDRHILO_PB8( + VARIABLE AddrLOW : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE AddrHIGH : INOUT NATURAL RANGE 0 to ADDRRange; + VARIABLE Addr : NATURAL) IS + VARIABLE Sec : NATURAL RANGE 0 TO SecNum; + BEGIN + Sec := Addr/16#10000#; + IF Sec = 0 OR Sec = SecNum - 1 THEN + AddrLOW := (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH := (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + ELSIF Sec = 1 THEN + AddrLOW := (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH := (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + IF AddrHIGH > 16#1FFFF# THEN + AddrHIGH := 16#1FFFF#; + END IF; + ELSIF Sec = SecNum THEN + AddrLOW := (Address/(SecSize_8+1))*(SecSize_8+1); + AddrHIGH := (Address/(SecSize_8+1))*(SecSize_8+1) + SecSize_8; + IF AddrHIGH > 16#3FFFFF# THEN + AddrHIGH := 16#3FFFFF#; + END IF; + END IF; + END ADDRHILO_PB8; + + BEGIN + + ---------------------------------------------------------------------------- + --Power Up time; + --------------------------------------------------------------------------- + PoweredUp <= '1' AFTER tdevice_PU; + + --------------------------------------------------------------------------- + -- VITAL Timing Checks Procedures + --------------------------------------------------------------------------- + VITALTimingCheck: PROCESS(SIIn, SOIn, SCK_ipd, CSNeg_ipd, HOLDNegIn, + WPNegIn) + -- Timing Check Variables + VARIABLE Tviol_SI_SCK : X01 := '0'; + VARIABLE TD_SI_SCK : VitalTimingDataType; + + VARIABLE Tviol_HOLD_SCK : X01 := '0'; + VARIABLE TD_HOLD_SCK : VitalTimingDataType; + + VARIABLE Tviol_CS_SCK : X01 := '0'; + VARIABLE TD_CS_SCK : VitalTimingDataType; + + VARIABLE Tviol_WS_CS : X01 := '0'; + VARIABLE TD_WS_CS : VitalTimingDataType; + + VARIABLE Tviol_WH_CS : X01 := '0'; + VARIABLE TD_WH_CS : VitalTimingDataType; + + VARIABLE Pviol_CS_read : X01 := '0'; + VARIABLE PD_CS_read : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_CS_pgm : X01 := '0'; + VARIABLE PD_CS_pgm : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_fast : X01 := '0'; + VARIABLE PD_SCK_serial_fast : VitalPeriodDataType := + VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual : X01 := '0'; + VARIABLE PD_SCK_dual : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_rdid : X01 := '0'; + VARIABLE PD_SCK_rdid : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial : X01 := '0'; + VARIABLE PD_SCK_serial : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_fast_rd: X01 := '0'; + VARIABLE PD_SCK_serial_fast_rd : VitalPeriodDataType := + VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_rd : X01 := '0'; + VARIABLE PD_SCK_serial_rd : VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_serial_rdid : X01 := '0'; + VARIABLE PD_SCK_serial_rdid: VitalPeriodDataType := VitalPeriodDataInit; + + VARIABLE Pviol_SCK_dual_fast_rd: X01 := '0'; + VARIABLE PD_SCK_dual_fast_rd : VitalPeriodDataType := + VitalPeriodDataInit; + + VARIABLE Violation : X01 := '0'; + + BEGIN + --------------------------------------------------------------------------- + -- Timing Check Section + --------------------------------------------------------------------------- + IF (TimingChecksOn) THEN + + -- Setup/Hold Check between SI and SCK, serial mode + VitalSetupHoldCheck ( + TestSignal => SIIn, + TestSignalName => "SI", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_SI_SCK, + SetupLow => tsetup_SI_SCK, + HoldHigh => thold_SI_SCK, + HoldLow => thold_SI_SCK, + CheckEnabled => SIOut_z /= SIIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_SI_SCK, + Violation => Tviol_SI_SCK + ); + + -- Setup/Hold Check between HOLD# and SCK / + VitalSetupHoldCheck ( + TestSignal => HOLDNegIn, + TestSignalName => "HOLD#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupLow => tsetup_HOLDNeg_SCK, + SetupHigh => tsetup_HOLDNeg_SCK, + HoldLow => thold_HOLDNeg_SCK, + HoldHigh => thold_HOLDNeg_SCK, + CheckEnabled => QUAD = '1' + AND HOLDNegOut_zd /= HOLDNegIn, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_HOLD_SCK, + Violation => Tviol_HOLD_SCK + ); + + -- Setup/Hold Check between CS# and SCK + VitalSetupHoldCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + RefSignal => SCK_ipd, + RefSignalName => "SCK", + SetupHigh => tsetup_CSNeg_SCK, + SetupLow => tsetup_CSNeg_SCK, + HoldHigh => thold_CSNeg_SCK, + HoldLow => thold_CSNeg_SCK, + CheckEnabled => true, + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_CS_SCK, + Violation => Tviol_CS_SCK + ); + + -- Setup Check between W# and CS# \ + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "W#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + SetupHigh => tsetup_WPNeg_CSNeg, + CheckEnabled => true, + RefTransition => '\', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WS_CS, + Violation => Tviol_WS_CS + ); + + -- Hold Check between W# and CS# / + VitalSetupHoldCheck ( + TestSignal => WPNegIn, + TestSignalName => "W#", + RefSignal => CSNeg_ipd, + RefSignalName => "CS#", + HoldHigh => thold_WPNeg_CSNeg, + CheckEnabled => SRWD = '1' AND WEL = '1' AND QUAD = '0', + RefTransition => '/', + HeaderMsg => InstancePath & PartID, + TimingData => TD_WH_CS, + Violation => Tviol_WH_CS + ); + + -- Period Check CS# for Program/Erase, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_pgm_posedge, + PeriodData => PD_CS_pgm, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CS_pgm, + HeaderMsg => InstancePath & PartID, + CheckEnabled => TRUE ); + + -- Period Check CS# for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => CSNeg_ipd, + TestSignalName => "CS#", + PulseWidthHigh => tpw_CSNeg_read_posedge, + PeriodData => PD_CS_read, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_CS_read, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd ); + + -- Period Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_serial_negedge, + PulseWidthHigh => tpw_SCK_serial_posedge, + PeriodData => PD_SCK_serial, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd); + + -- Period Check SCK for RDID, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_rd_jid_negedge, + PulseWidthHigh => tpw_SCK_rd_jid_posedge, + PeriodData => PD_SCK_rdid, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_rdid, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd_jid); + + -- Period Check SCK for FAST_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_serial_fast_negedge, + PulseWidthHigh => tpw_SCK_serial_fast_posedge, + PeriodData => PD_SCK_serial_fast, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_fast, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Period Check SCK for DUAL_READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + PulseWidthLow => tpw_SCK_dual_negedge, + PulseWidthHigh => tpw_SCK_dual_posedge, + PeriodData => PD_SCK_dual, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual); + + -- Period Check SCK for READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_serial_rd, + PeriodData => PD_SCK_serial_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd ); + + -- Period Check SCK for RDID, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_serial_rd_jid, + PeriodData => PD_SCK_serial_rdid, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_rdid, + HeaderMsg => InstancePath & PartID, + CheckEnabled => rd_jid ); + + -- Period Check SCK for other than READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_serial_fast_rd, + PeriodData => PD_SCK_serial_fast_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_serial_fast_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => fast_rd ); + + -- Period Check SCK for other than READ, serial mode + VitalPeriodPulseCheck ( + TestSignal => SCK_ipd, + TestSignalName => "SCK", + Period => tperiod_SCK_dual_fast_rd, + PeriodData => PD_SCK_dual_fast_rd, + XOn => XOn, + MsgOn => MsgOn, + Violation => Pviol_SCK_dual_fast_rd, + HeaderMsg => InstancePath & PartID, + CheckEnabled => dual ); + + Violation := Tviol_SI_SCK OR + Tviol_HOLD_SCK OR + Tviol_CS_SCK OR + Tviol_WS_CS OR + Tviol_WH_CS OR + Pviol_CS_read OR + Pviol_CS_pgm OR + Pviol_SCK_serial_fast OR + Pviol_SCK_dual OR + Pviol_SCK_rdid OR + Pviol_SCK_serial OR + Pviol_SCK_serial_rd OR + Pviol_SCK_serial_rdid OR + Pviol_SCK_serial_fast_rd OR + Pviol_SCK_dual_fast_rd; + + Viol <= Violation; + + ASSERT Violation = '0' + REPORT InstancePath & partID & ": simulation may be" & + " inaccurate due to timing violations" + SEVERITY WARNING; + + END IF; + END PROCESS VITALTimingCheck; + +---------------------------------------------------------------------------- +-- sequential process for FSM state transition +---------------------------------------------------------------------------- + StateTransition : PROCESS(next_state, PoweredUp) + + BEGIN + IF PoweredUp = '1' THEN + current_state <= next_state; + END IF; + END PROCESS StateTransition; + + --------------------------------------------------------------------------- + -- Write cycle decode + --------------------------------------------------------------------------- + BusCycleDecode : PROCESS(SCK_ipd, CSNeg_ipd, HOLDNeg_pullup, SIIn, RES_in) + + TYPE bus_cycle_type IS (STAND_BY, + CODE_BYTE, + ADDRESS_BYTES, + DUMMY_BYTES, + MODE_BYTE, + DATA_BYTES + ); + TYPE quad_data_type IS ARRAY (0 TO 511) OF INTEGER RANGE 0 TO 15; + + VARIABLE bus_cycle_state : bus_cycle_type; + + VARIABLE data_cnt : NATURAL := 0; + VARIABLE addr_cnt : NATURAL := 0; + VARIABLE code_cnt : NATURAL := 0; + VARIABLE mode_cnt : NATURAL := 0; + VARIABLE dummy_cnt : NATURAL := 0; + VARIABLE bit_cnt : NATURAL := 0; + VARIABLE Data_in : std_logic_vector(2047 downto 0) + := (others => '0'); + VARIABLE quad_data_in : quad_data_type; + VARIABLE quad_nybble : std_logic_vector(3 downto 0); + VARIABLE Quad_slv : std_logic_vector(3 downto 0); + VARIABLE code : std_logic_vector(7 downto 0); + VARIABLE code_in : std_logic_vector(7 downto 0); + VARIABLE Byte_slv : std_logic_vector(7 downto 0); + VARIABLE addr_bytes : std_logic_vector(HiAddrBit downto 0); + VARIABLE Address_in : std_logic_vector(23 downto 0); + VARIABLE mode_bytes : std_logic_vector(7 downto 0); + VARIABLE mode_in : std_logic_vector(7 downto 0); + BEGIN + + IF rising_edge(CSNeg_ipd) AND NOT(bus_cycle_state = DATA_BYTES) + AND NOT(bus_cycle_state = DUMMY_BYTES) THEN + bus_cycle_state := STAND_BY; + ELSE + CASE bus_cycle_state IS + WHEN STAND_BY => + IF falling_edge(CSNeg_ipd) THEN + Instruct <= NONE; + write <= '1'; + code_cnt := 0; + addr_cnt := 0; + data_cnt := 0; + mode_cnt := 0; + dummy_cnt := 0; + bus_cycle_state := CODE_BYTE; + END IF; + + WHEN CODE_BYTE => + IF rising_edge(SCK_ipd) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1') THEN + Code_in(code_cnt) := SIIn; + code_cnt := code_cnt + 1; + IF code_cnt = BYTE THEN + --MSB first + FOR I IN 7 DOWNTO 0 LOOP + code(i) := code_in(7-i); + END LOOP; + + CASE code IS + WHEN "00000110" => --06h + Instruct <= WREN; + bus_cycle_state := DATA_BYTES; + WHEN "00000100" => --04h + Instruct <= WRDI; + bus_cycle_state := DATA_BYTES; + WHEN "00000001" => --01h + Instruct <= WRR; + bus_cycle_state := DATA_BYTES; + WHEN "00000101" => --05h + Instruct <= RDSR; + bus_cycle_state := DATA_BYTES; + WHEN "00000011" => --03h + Instruct <= READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00001011" => --0Bh + Instruct <= FAST_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10011111" => --9Fh + Instruct <= RDID; + bus_cycle_state := DATA_BYTES; + WHEN "10010000" => + Instruct <= READ_ID; --90h + bus_cycle_state := ADDRESS_BYTES; + WHEN "10101011" => + Instruct <= RES_READ_ES; --ABh + bus_cycle_state := DUMMY_BYTES; + WHEN "11011000" => --D8h + Instruct <= SE; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11000111" | "01100000" => --C7h or 60h + Instruct <= BE; + bus_cycle_state := DATA_BYTES; + WHEN "00000010" => --02h + Instruct <= PP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00110010" => --32h + Instruct <= QPP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10111001" => --B9h + Instruct <= DP; + bus_cycle_state := DATA_BYTES; + WHEN "00110000" => --30h + Instruct <= CLSR; + bus_cycle_state := DATA_BYTES; + WHEN "00110101" => --35h + Instruct <= RCR; + bus_cycle_state := DATA_BYTES; + WHEN "00100000" => --20h + Instruct <= P4E; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01000000" =>--40h + Instruct <= P8E; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01000010" => --42h + Instruct <= OTPP; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01001011" => --4Bh + Instruct <= OTPR; + bus_cycle_state := ADDRESS_BYTES; + WHEN "00111011" => --3Bh + Instruct <= DUAL_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "01101011" => --6Bh + Instruct <= QUAD_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "10111011" => --BBh + Instruct <= DH_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN "11101011" => --EBh + Instruct <= QH_READ; + bus_cycle_state := ADDRESS_BYTES; + WHEN others => + null; + END CASE; + END IF; + END IF; + + WHEN ADDRESS_BYTES => + IF rising_edge(SCK_ipd) THEN + IF ((Instruct=FAST_READ OR Instruct=OTPR + OR Instruct=DUAL_READ) AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1')) + OR (Instruct=QUAD_READ AND QUAD = '1') THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 23-HiAddrBit LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DUMMY_BYTES; + END IF; + ELSIF Instruct = DH_READ AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1') THEN + IF SOIn /= 'Z' THEN + Address_in(2*addr_cnt) := SOIn; + Address_in(2*addr_cnt+1) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 12 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 23-HiAddrBit LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSE + mpm_mode := FALSE; + bus_cycle_state := STAND_BY; + END IF; + ELSIF Instruct = QH_READ THEN + IF QUAD = '1' THEN + IF SOIn /= 'Z' THEN + Address_in(4*addr_cnt) := HOLDNegIn; + Address_in(4*addr_cnt+1) := WPNegIn; + Address_in(4*addr_cnt+2) := SOIn; + Address_in(4*addr_cnt+3) := SIIn; + read_cnt := 0; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 6 THEN + addr_cnt := 0; + FOR I IN 23 DOWNTO 23-HiAddrBit LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := MODE_BYTE; + END IF; + ELSE + mpm_mode := FALSE; + bus_cycle_state := STAND_BY; + END IF; + ELSE + bus_cycle_state := STAND_BY; + END IF; + ELSIF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + Address_in(addr_cnt) := SIIn; + addr_cnt := addr_cnt + 1; + IF addr_cnt = 3*BYTE THEN + FOR I IN 23 DOWNTO 23-HiAddrBit LOOP + addr_bytes(23-i) := Address_in(i); + END LOOP; + Address <= to_nat(addr_bytes); + change_addr <= '1','0' AFTER 1 ns; + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + END IF; + + WHEN MODE_BYTE => + IF rising_edge(SCK_ipd) THEN + IF Instruct=DH_READ AND + ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1') THEN + mode_in(2*mode_cnt) := SOIn; + mode_in(2*mode_cnt+1) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/2 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF Instruct=QH_READ AND QUAD = '1' THEN + mode_in(4*mode_cnt) := HOLDNegIn; + mode_in(4*mode_cnt+1) := WPNegIn; + mode_in(4*mode_cnt+2) := SOIn; + mode_in(4*mode_cnt+3) := SIIn; + mode_cnt := mode_cnt + 1; + IF mode_cnt = BYTE/4 THEN + mode_cnt := 0; + FOR I IN 7 DOWNTO 0 LOOP + mode_bytes(i) := mode_in(7-i); + END LOOP; + bus_cycle_state := DUMMY_BYTES; + END IF; + END IF; + dummy_cnt := 0; + END IF; + + WHEN DUMMY_BYTES => + IF rising_edge(SCK_ipd) THEN + IF QUAD = '1' AND (Instruct=QUAD_READ + OR Instruct=QH_READ) THEN + dummy_cnt := dummy_cnt + 1; + IF dummy_cnt = BYTE AND Instruct=QUAD_READ THEN + bus_cycle_state := DATA_BYTES; + ELSIF dummy_cnt = BYTE/2 AND Instruct=QH_READ THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + dummy_cnt := dummy_cnt + 1; + IF dummy_cnt = BYTE THEN + IF Instruct=FAST_READ OR Instruct=OTPR OR + Instruct=DUAL_READ THEN + bus_cycle_state := DATA_BYTES; + END IF; + ELSIF dummy_cnt = 3*BYTE THEN + bus_cycle_state := DATA_BYTES; + END IF; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + IF (((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1') + AND dummy_cnt = 0 AND Instruct = RES_READ_ES) THEN + write <= '0'; + END IF; + bus_cycle_state := STAND_BY; + END IF; + + WHEN DATA_BYTES => + IF falling_edge(SCK_ipd) AND CSNeg_ipd = '0' THEN + IF ((Instruct = READ OR Instruct = FAST_READ + OR Instruct = DUAL_READ OR Instruct = DH_READ + OR Instruct = RES_READ_ES OR Instruct = RDID + OR Instruct = READ_ID OR Instruct = RDSR + OR Instruct = RCR OR Instruct = OTPR) + AND ((HOLDNeg_pullup='1' AND QUAD='0') OR QUAD ='1')) + OR ((Instruct=QUAD_READ OR Instruct=QH_READ) + AND QUAD = '1') THEN + read_out <= '1', '0' AFTER 1 ns; + END IF; + END IF; + IF rising_edge(SCK_ipd) THEN + IF QUAD = '1' AND Instruct=QPP THEN + quad_nybble := HOLDNegIn & WPNegIn & SOIn & SIIn; + IF data_cnt > 511 THEN + --In case of quad mode and QPP, + --if more than 512 bytes are sent to the device + FOR I IN 0 TO 510 LOOP + quad_data_in(i) := quad_data_in(i+1); + END LOOP; + quad_data_in(511) := to_nat(quad_nybble); + data_cnt := data_cnt +1; + ELSE + IF quad_nybble /= "ZZZZ" THEN + quad_data_in(data_cnt) := + to_nat(quad_nybble); + END IF; + data_cnt := data_cnt +1; + END IF; + ELSIF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + IF data_cnt > 2047 THEN + --In case of serial mode and PP, + --if more than 256 bytes are sent to the device + IF bit_cnt = 0 THEN + FOR I IN 0 TO (255*BYTE - 1) LOOP + Data_in(i) := Data_in(i+8); + END LOOP; + END IF; + Data_in(2040 + bit_cnt) := SIIn; + bit_cnt := bit_cnt + 1; + IF bit_cnt = 8 THEN + bit_cnt := 0; + END IF; + data_cnt := data_cnt + 1; + ELSE + Data_in(data_cnt) := SIIn; + data_cnt := data_cnt + 1; + bit_cnt := 0; + END IF; + END IF; + END IF; + + IF rising_edge(CSNeg_ipd) THEN + IF mpm_mode AND mode_bytes(7 downto 4) = "1010" + AND (Instruct = DH_READ OR Instruct = QH_READ) THEN + bus_cycle_state := ADDRESS_BYTES; + ELSE + mpm_mode := FALSE; + bus_cycle_state := STAND_BY; + END IF; + CASE Instruct IS + WHEN WREN | WRDI | DP | BE | SE | P4E | P8E + | CLSR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + IF data_cnt = 0 THEN + write <= '0'; + END IF; + END IF; + WHEN RES_READ_ES => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + write <= '0'; + END IF; + WHEN WRR => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + IF ((data_cnt mod 8) = 0 AND + data_cnt > 0) THEN + IF data_cnt = 8 THEN + write <= '0'; + cfg_write <= '0'; + FOR i IN 0 TO 7 LOOP + Status_reg_in(i) <= + Data_in(7-i); + END LOOP; + ELSIF data_cnt = 16 THEN + --After the 16th cycle both the + --Status and Configuration Registers + --are written to. + write <= '0'; + cfg_write <= '1'; + FOR i IN 0 TO 7 LOOP + Status_reg_in(i) <= + Data_in(7-i); + Sec_conf_reg_in(i) <= + Data_in(15-i); + END LOOP; + END IF; + END IF; + END IF; + + WHEN PP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + IF data_cnt > 0 THEN + IF data_cnt mod 8 = 0 THEN + write <= '0'; + FOR I IN 0 TO 255 LOOP + FOR J IN 7 DOWNTO 0 LOOP + Byte_slv(j) := + Data_in((i*8) + (7-j)); + END LOOP; + WByte(i) <= + to_nat(Byte_slv); + END LOOP; + IF data_cnt > 256*BYTE THEN + Byte_number <= 255; + ELSE + Byte_number <= data_cnt/8-1; + END IF; + END IF; + END IF; + END IF; + + WHEN QPP => + IF data_cnt > 0 THEN + IF data_cnt mod 2 = 0 THEN + write <= '0'; + FOR I IN 0 TO 255 LOOP + FOR J IN 1 DOWNTO 0 LOOP + Quad_slv := + to_slv(quad_data_in((i*2) + + (1-j)),4); + + Byte_slv(4*j+3 DOWNTO 4*j) := + Quad_slv; + END LOOP; + WByte(i) <= + to_nat(Byte_slv); + END LOOP; + IF data_cnt > 512 THEN + Byte_number <= 255; + ELSE + Byte_number <= data_cnt/2-1; + END IF; + END IF; + END IF; + + WHEN OTPP => + IF ((HOLDNeg_pullup='1' AND QUAD='0') OR + QUAD ='1') THEN + IF data_cnt = 8 THEN + write <= '0'; + FOR J IN 7 DOWNTO 0 LOOP + Byte_slv(j) := Data_in(7-j); + END LOOP; + WOTPByte <= to_nat(Byte_slv); + END IF; + END IF; + + WHEN others => + null; + END CASE; + END IF; + + END CASE; + END IF; + + END PROCESS BusCycleDecode; + + --------------------------------------------------------------------------- + -- Timing control for the Page Program + --------------------------------------------------------------------------- + ProgTime : PROCESS(PSTART) + VARIABLE pob : time; + BEGIN + IF LongTimming THEN + pob := tdevice_PP; + ELSE + pob := tdevice_PP / 100; + END IF; + IF rising_edge(PSTART) AND PDONE = '1' THEN + IF Sec_Prot(SA) = '0' THEN + PDONE <= '0', '1' AFTER pob; + END IF; + END IF; + END PROCESS ProgTime; + + --------------------------------------------------------------------------- + -- Timing control for the Write Status Register + --------------------------------------------------------------------------- + WriteTime : PROCESS(WSTART) + VARIABLE wob : time; + BEGIN + IF LongTimming THEN + wob := tdevice_WR; + ELSE + wob := tdevice_WR / 100; + END IF; + IF rising_edge(WSTART) AND WDONE = '1' THEN + WDONE <= '0', '1' AFTER wob; + END IF; + END PROCESS WriteTime; + + --------------------------------------------------------------------------- + -- Timing control for the Bulk Erase + --------------------------------------------------------------------------- + ErsTime : PROCESS(ESTART) + VARIABLE seo : time; + VARIABLE beo : time; + VARIABLE peo : time; + VARIABLE duration : time; + BEGIN + IF LongTimming THEN + seo := tdevice_SE; + beo := tdevice_BE; + peo := tdevice_PE; + ELSE + seo := tdevice_SE / 1000; + beo := tdevice_BE / 1000; + peo := tdevice_PE / 1000; + END IF; + IF rising_edge(ESTART) AND EDONE = '1' THEN + IF Instruct = BE THEN + duration := beo; + ELSIF Instruct = P4E OR Instruct = P8E THEN + duration := peo; + ELSE --Instruct = SE + duration := seo; + END IF; + EDONE <= '0', '1' AFTER duration; + END IF; + END PROCESS ErsTime; + + CheckCEOnPowerUP :PROCESS + BEGIN + IF CSNeg /= '1' THEN + REPORT InstancePath & partID & + ": Device is selected during Power Up" + SEVERITY WARNING; + END IF; + WAIT; + END PROCESS; + + --------------------------------------------------------------------------- + -- Main Behavior Process + -- combinational process for next state generation + --------------------------------------------------------------------------- + StateGen :PROCESS(write, CSNeg, WDONE, PDONE, EDONE, DP_out) + + BEGIN + ----------------------------------------------------------------------- + -- Functionality Section + ----------------------------------------------------------------------- + + CASE current_state IS + WHEN IDLE => + IF falling_edge(write) THEN + IF Instruct = WRR AND WEL = '1' + AND not(SRWD='1' AND WPNeg_pullup='0' AND QUAD='0') THEN + -- can not execute if HPM is entered + -- or if WEL bit is zero + next_state <= WRITE_SR; + ELSIF (Instruct = PP OR Instruct = QPP) AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + next_state <= PAGE_PG; + END IF; + ELSIF Instruct = OTPP AND WEL = '1' THEN + IF Address = 256 OR Address = 257 OR + ((Address >= 258 AND Address <= 273) AND + PR_LOCK1((Address-258)/8) = '1') OR Address = 274 OR + Address = 275 OR((Address >= 276 AND Address <= 531) + AND PR_LOCK2((Address-276)/16) = '1') OR Address = 532 + OR Address = 533 OR((Address >= 534 AND Address <= 767) + AND PR_LOCK3((Address-534)/16) = '1') THEN + next_state <= OTP_PG; + END IF; + ELSIF Instruct = SE AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + next_state <= SECTOR_ER; + END IF; + ELSIF Instruct = P4E AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' AND (((sect=0 OR sect=1) + AND TBPARM='0') OR ((sect=SecNum OR sect=SecNum-1) + AND TBPARM='1')) THEN + next_state <= P4_ER; + END IF; + ELSIF Instruct = P8E AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' AND (((sect=0 OR sect=1) + AND TBPARM='0') OR ((sect=SecNum OR sect=SecNum-1) + AND TBPARM='1')) THEN + next_state <= P8_ER; + END IF; + ELSIF Instruct = BE AND WEL = '1' AND + (BP0='0' AND BP1='0' AND BP2='0') THEN + next_state <= BULK_ER; + ELSIF Instruct = DP THEN + next_state <= DP_DOWN_WAIT; + ELSE + next_state <= IDLE; + END IF; + END IF; + + WHEN WRITE_SR => + IF rising_edge(WDONE) THEN + next_state <= IDLE; + END IF; + + WHEN PAGE_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN OTP_PG => + IF rising_edge(PDONE) THEN + next_state <= IDLE; + END IF; + + WHEN BULK_ER | SECTOR_ER | P4_ER | P8_ER => + IF rising_edge(EDONE) THEN + next_state <= IDLE; + END IF; + + WHEN DP_DOWN_WAIT => + IF rising_edge(DP_out) THEN + next_state <= DP_DOWN; + END IF; + + WHEN DP_DOWN => + IF falling_edge(write) AND Instruct = RES_READ_ES THEN + next_state <= IDLE; + END IF; + + END CASE; + + END PROCESS StateGen; + + --------------------------------------------------------------------------- + --FSM Output generation and general funcionality + --------------------------------------------------------------------------- + Functional : PROCESS(write,read_out, WDONE, PDONE, EDONE, current_state, + CSNeg_ipd, HOLDNeg_pullup, Instruct, Address, WByte, + DP_out, RES_out, change_addr, PoweredUp, WPNeg_pullup) + --Common Flash Interface Query codes + TYPE CFItype IS ARRAY (16#07# TO 16#50#) OF + INTEGER RANGE -1 TO 16#FF#; + TYPE WDataType IS ARRAY (0 TO 255) OF INTEGER RANGE -1 TO MaxData; + + VARIABLE CFI_array : CFItype := (OTHERS => -1); + VARIABLE WData : WDataType := (OTHERS => 0); + VARIABLE WOTPData : INTEGER RANGE -1 to MaxData; + VARIABLE oe : boolean := FALSE; + + VARIABLE AddrLo : NATURAL; + VARIABLE AddrHi : NATURAL; + VARIABLE Addr : NATURAL; + VARIABLE Addr_tmp : NATURAL; + + VARIABLE read_addr : NATURAL RANGE 0 TO AddrRANGE; + VARIABLE data_out : std_logic_vector(7 downto 0); + VARIABLE ident_out : std_logic_vector(647 downto 0); + VARIABLE CFI_array_tmp : std_logic_vector(591 downto 0); + + VARIABLE old_bit : std_logic_vector(7 downto 0); + VARIABLE new_bit : std_logic_vector(7 downto 0); + VARIABLE old_int : INTEGER RANGE -1 to MaxData; + VARIABLE new_int : INTEGER RANGE -1 to MaxData; + VARIABLE wr_cnt : NATURAL RANGE 0 TO 255; + + VARIABLE sect : NATURAL RANGE 0 TO SecNum; + VARIABLE cnt : NATURAL RANGE 0 TO 256 := 0; + + BEGIN + ----------------------------------------------------------------------- + -- Functionality Section + ----------------------------------------------------------------------- + + oe := rising_edge(read_out) AND PoweredUp = '1'; + + IF Instruct'EVENT THEN + read_cnt := 0; + fast_rd <= true; + rd_jid <= false; + dual <= false; + rd <= false; + IF Instruct = DH_READ OR Instruct = QH_READ THEN + mpm_mode := TRUE; + END IF; + END IF; + + IF rising_edge(PoweredUp) THEN + + FREEZE := '0'; + --When BPNV is set to '1'. the BP2-0 bits in Status Register are + --volatile and will be reset binary 111 after power-on reset + IF BPNV = '1' AND FREEZE = '0' THEN + BP0 := '1'; + BP1 := '1'; + BP2 := '1'; + BP := BP2 & BP1 & BP0; + change_BP <= '1', '0' AFTER 1 ns; + END IF; + END IF; + + IF rising_edge(change_addr) THEN + read_addr := Address; + END IF; + + IF RES_out'EVENT AND RES_out = '1' THEN + RES_in <= '0'; + END IF; + + CASE current_state IS + WHEN IDLE => + IF falling_edge(write) THEN + read_cnt := 0; + IF RES_in = '1' AND Instruct /= DP THEN + ASSERT false + REPORT InstancePath & partID & "Command results" & + " can be corrupted, a delay of tRES" & + " currently in progress." + SEVERITY WARNING; + END IF; + IF Instruct = WREN THEN + WEL := '1'; + ELSIF Instruct = WRDI THEN + WEL := '0'; + ELSIF Instruct = WRR AND WEL = '1' THEN + IF not(SRWD='1' AND WPNeg_pullup='0' AND QUAD='0') THEN + -- can not execute if HPM is entered + -- or if WEL bit is zero + WSTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + ELSE + WEL := '0'; + END IF; + ELSIF (Instruct = PP OR Instruct = QPP) AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + PSTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + SA <= sect; + Addr := Address; + Addr_tmp := Address; + wr_cnt := Byte_number; + FOR I IN wr_cnt DOWNTO 0 LOOP + IF Viol /= '0' THEN + WData(i) := -1; + ELSE + WData(i) := WByte(i); + END IF; + END LOOP; + ELSE + WEL := '0'; + END IF; + ELSIF Instruct = OTPP AND WEL = '1' THEN + IF Address = 256 OR Address = 257 OR + ((Address >= 258 AND Address <= 273) AND + PR_LOCK1((Address-258)/8)='1') OR Address=274 OR + Address=275 OR ((Address>=276 AND Address<=531) + AND PR_LOCK2((Address-276)/16)='1') OR Address=532 + OR Address=533 OR ((Address>=534 AND Address<=767) + AND PR_LOCK3((Address-534)/16) = '1') THEN + PSTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + Addr := Address; + IF Viol /= '0' THEN + WOTPData := -1; + ELSE + WOTPData := WOTPByte; + END IF; + ELSIF (Address < 100 OR Address > 767 ) THEN + P_ERR := '1'; + WEL := '0'; + ELSE + WEL := '0'; + END IF; + ELSIF Instruct = SE AND WEL = '1' THEN + sect := Address / 16#10000#; + IF Sec_Prot(sect) = '0' THEN + ESTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + Addr := Address; + ELSE + WEL := '0'; + END IF; + ELSIF Instruct = BE AND WEL = '1' THEN + IF (BP0='0' AND BP1='0' AND BP2='0') THEN + ESTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + ELSE + WEL := '0'; + END IF; + ELSIF Instruct = P4E AND WEL = '1' THEN + sect := Address / 16#10000#; + IF ((sect=0 OR sect=1) AND TBPARM='0') + OR ((sect=SecNum OR sect=SecNum-1) + AND TBPARM='1') THEN + IF Sec_Prot(sect) = '0' THEN + ESTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + Addr := Address; + ELSE + WEL := '0'; + END IF; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + ELSIF Instruct = P8E AND WEL = '1' THEN + sect := Address / 16#10000#; + IF ((sect=0 OR sect=1) AND TBPARM='0') + OR ((sect=SecNum OR sect=SecNum-1) + AND TBPARM='1') THEN + IF Sec_Prot(sect) = '0' THEN + ESTART <= '1', '0' AFTER 1 ns; + WIP := '1'; + Addr := Address; + ELSE + WEL := '0'; + END IF; + ELSE + E_ERR := '1'; + WEL := '0'; + END IF; + ELSIF Instruct = CLSR THEN + E_ERR := '0'; + P_ERR := '0'; + ELSIF Instruct = DP THEN + RES_in <= '0'; + DP_in <= '1'; + ELSIF Instruct = RES_READ_ES THEN + RES_in <= '1'; + END IF; + + ELSIF oe AND RES_in = '0' THEN + IF Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = RCR THEN + --Read Security Conf. Register + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = READ OR Instruct = FAST_READ THEN + --Read Memory array + IF Instruct = READ THEN + fast_rd <= false; + rd_jid <= false; + rd <= true; + END IF; + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF Instruct = DUAL_READ OR Instruct = DH_READ THEN + --Read Memory array + fast_rd <= false; + rd <= false; + rd_jid <= false; + dual <= true; + data_out := to_slv(Mem(read_addr),8); + SOut_zd <= data_out(7-2*read_cnt); + SIOut_zd <= data_out(6-2*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 4 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF (Instruct = QUAD_READ OR Instruct = QH_READ) + AND QUAD = '1' THEN + --Read Memory array + fast_rd <= false; + rd <= false; + rd_jid <= false; + dual <= true; + data_out := to_slv(Mem(read_addr),8); + HOLDNegOut_zd <= data_out(7-4*read_cnt); + WPNegOut_zd <= data_out(6-4*read_cnt); + SOut_zd <= data_out(5-4*read_cnt); + SIOut_zd <= data_out(4-4*read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 2 THEN + read_cnt := 0; + IF read_addr = AddrRANGE THEN + read_addr := 0; + ELSE + read_addr := read_addr + 1; + END IF; + END IF; + ELSIF Instruct = OTPR THEN + IF (read_addr>=OTPLoAddr) AND (read_addr<=OTPHiAddr) + THEN + --Read OTP Memory array + fast_rd <= true; + rd_jid <= false; + rd <= false; + data_out := to_slv(OTPMem(read_addr),8); + SOut_zd <= data_out(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSIF (read_addr > OTPHiAddr) THEN + --OTP Read operation will not wrap to the + --starting address after the OTP address is at + --its maximum or Read Password Protection Mode + --is selected; instead, the data beyond the + --maximum OTP address will be undefined. + SOut_zd <= 'U'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ELSIF Instruct = RDID THEN + --Read Device ID + --can be terminated by driving CSNeg high + --at any time + fast_rd <= false; + rd_jid <= true; + rd <= false; + ident_out := to_slv(Manuf_ID,8) & to_slv(DeviceID,16) & + to_slv(ExtendedBytes,8) & to_slv(ReservedBytes,8) & + to_slv(ReservedBytes,8) & to_slv(ReservedBytes,8) & + CFI_array_tmp; + SOut_zd <= ident_out(647-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 648 THEN + read_cnt := 0; + END IF; + ELSIF Instruct = READ_ID THEN + --Read Manufacturer and Device ID + IF read_addr MOD 2 = 0 THEN + data_out := to_slv(Manuf_ID,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := read_addr + 1; + END IF; + ELSE + data_out := to_slv(ES,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + read_addr := 0; + END IF; + END IF; + END IF; + ELSIF oe AND RES_in = '1' THEN + SOut_zd <= 'X'; + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + ASSERT false + REPORT InstancePath & partID & "Command results" & + " can be corrupted, a delay of tRES" & + " currently in progress." + SEVERITY WARNING; + END IF; + + WHEN WRITE_SR => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + IF WDONE = '1' THEN + WIP := '0'; + WEL := '0'; + SRWD := Status_reg_in(7);--MSB first + + IF FREEZE='0' THEN + --The Freeze Bit, when set to 1, locks the current + --state of the BP2-0 bits in Status Register, + --the TBPROT and TBPARM bits in the Config Register + --As long as the FREEZE bit remains cleared to logic + --'0', the other bits of the Configuration register + --including FREEZE are writeable. + + BP2 := Status_reg_in(4); + BP1 := Status_reg_in(3); + BP0 := Status_reg_in(2); + + BP := BP2 & BP1 & BP0; + + IF cfg_write = '1' THEN + + FREEZE := Sec_conf_reg_in(0);--MSB first + + IF TBPARM = '0' THEN + TBPARM := Sec_conf_reg_in(2); + END IF; + + IF TBPROT = '0' THEN + TBPROT := Sec_conf_reg_in(5); + END IF; + + QUAD := Sec_conf_reg_in(1); + + IF BPNV = '0' THEN + BPNV := Sec_conf_reg_in(3); + END IF; + + END IF; + + change_BP <= '1', '0' AFTER 1 ns; + END IF; + + END IF; + + WHEN PAGE_PG => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + ADDRHILO_PG(AddrLo, AddrHi, Addr); + cnt := 0; + + FOR i IN 0 TO wr_cnt LOOP + new_int := WData(i); + old_int := Mem(Addr + i - cnt); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WData(i) := new_int; + ELSE + WData(i) := -1; + END IF; + + Mem(Addr + i - cnt) := -1; + + IF (Addr + i) = AddrHi THEN + Addr := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + cnt :=0; + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO wr_cnt LOOP + Mem(Addr_tmp + i - cnt) := WData(i); + IF (Addr_tmp + i) = AddrHi THEN + Addr_tmp := AddrLo; + cnt := i + 1; + END IF; + END LOOP; + END IF; + + WHEN OTP_PG => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + new_int := WOTPData; + old_int := OTPMem(Addr); + IF new_int > -1 THEN + new_bit := to_slv(new_int,8); + IF old_int > -1 THEN + old_bit := to_slv(old_int,8); + FOR j IN 0 TO 7 LOOP + IF old_bit(j) = '0' THEN + new_bit(j) := '0'; + END IF; + END LOOP; + new_int := to_nat(new_bit); + END IF; + WOTPData := new_int; + ELSE + WOTPData := -1; + END IF; + OTPMem(Addr) := -1; + IF PDONE = '1' THEN + WIP := '0'; + WEL := '0'; + OTPMem(Addr) := WOTPData; + PR_LOCK1 := to_slv(OTPMem(257),8) & to_slv(OTPMem(256),8); + PR_LOCK2 := to_slv(OTPMem(275),8) & to_slv(OTPMem(274),8); + PR_LOCK3 := to_slv(OTPMem(533),8) & to_slv(OTPMem(532),8); + END IF; + + WHEN SECTOR_ER => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + ADDRHILO_SEC(AddrLo, AddrHi, Addr); + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + + WHEN BULK_ER => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + FOR i IN 0 TO AddrRANGE LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN 0 TO AddrRANGE LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + + WHEN P4_ER => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ADDRHILO_PB4(AddrLo, AddrHi, Addr); + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + + WHEN P8_ER => + IF oe AND Instruct = RDSR THEN + --Read Status Register + SOut_zd <= Status_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + IF oe AND Instruct = RCR THEN + SOut_zd <= Sec_conf_reg(7-read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + ADDRHILO_PB8(AddrLo, AddrHi, Addr); + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := -1; + END LOOP; + IF EDONE = '1' THEN + WIP := '0'; + WEL := '0'; + FOR i IN AddrLo TO AddrHi LOOP + Mem(i) := MaxData; + END LOOP; + END IF; + + WHEN DP_DOWN_WAIT => + IF rising_edge(DP_out) THEN + DP_in <= '0'; + ELSIF DP_in = '1' AND Instruct'EVENT THEN + ASSERT false + REPORT InstancePath & partID & "Command results" & + " can be corrupted, a delay of tPD" & + " currently in progress." + SEVERITY WARNING; + END IF; + + WHEN DP_DOWN => + IF falling_edge(write) THEN + IF Instruct = RES_READ_ES THEN + RES_in <= '1'; + END IF; + ELSIF oe AND Instruct = RES_READ_ES THEN + --Read Electronic Signature + data_out := to_slv(ES,8); + SOut_zd <= data_out(7 - read_cnt); + read_cnt := read_cnt + 1; + IF read_cnt = 8 THEN + read_cnt := 0; + END IF; + END IF; + + END CASE; + + --Output Disable Control + IF (CSNeg_ipd = '1') THEN + SIOut_zd <= 'Z'; + HOLDNegOut_zd <= 'Z'; + WPNegOut_zd <= 'Z'; + SOut_zd <= 'Z'; + END IF; + + IF NOW = 0 ns THEN + CFI_array(16#07#) := 16#FF#; + CFI_array(16#08#) := 16#FF#; + CFI_array(16#09#) := 16#FF#; + CFI_array(16#0A#) := 16#FF#; + CFI_array(16#0B#) := 16#FF#; + CFI_array(16#0C#) := 16#FF#; + CFI_array(16#0D#) := 16#FF#; + CFI_array(16#0E#) := 16#FF#; + CFI_array(16#0F#) := 16#FF#; + --Product Group CFI Query Identification String + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#00#; + CFI_array(16#18#) := 16#00#; + CFI_array(16#19#) := 16#00#; + CFI_array(16#1A#) := 16#00#; + --Product Group CFI system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#0B#; + CFI_array(16#20#) := 16#0B#; + CFI_array(16#21#) := 16#09#; + CFI_array(16#22#) := 16#0F#; + CFI_array(16#23#) := 16#01#; + CFI_array(16#24#) := 16#01#; + CFI_array(16#25#) := 16#02#; + CFI_array(16#26#) := 16#01#; + --Product Group CFI Device Geometry Definition + CFI_array(16#27#) := 16#16#; + CFI_array(16#28#) := 16#05#; + CFI_array(16#29#) := 16#05#; + CFI_array(16#2A#) := 16#08#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#02#; + CFI_array(16#2D#) := 16#1F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#10#; + CFI_array(16#30#) := 16#00#; + CFI_array(16#31#) := 16#3D#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#01#; + CFI_array(16#35#) := 16#00#; + CFI_array(16#36#) := 16#00#; + CFI_array(16#37#) := 16#00#; + CFI_array(16#38#) := 16#00#; + CFI_array(16#39#) := 16#00#; + CFI_array(16#3A#) := 16#00#; + CFI_array(16#3B#) := 16#00#; + CFI_array(16#3C#) := 16#00#; + CFI_array(16#3D#) := 16#FF#; + CFI_array(16#3E#) := 16#FF#; + CFI_array(16#3F#) := 16#FF#; + --Product Group CFI Primary Vendor-Specific Extended Query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#15#; + CFI_array(16#46#) := 16#00#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#00#; + CFI_array(16#49#) := 16#05#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#01#; + CFI_array(16#4C#) := 16#03#; + CFI_array(16#4D#) := 16#85#; + CFI_array(16#4E#) := 16#95#; + CFI_array(16#4F#) := 16#07#; + CFI_array(16#50#) := 16#00#; + END IF; + + CFI_array_tmp :=to_slv(CFI_array(16#07#), 8) & + to_slv(CFI_array(16#08#), 8) & + to_slv(CFI_array(16#09#), 8) & + to_slv(CFI_array(16#0A#), 8) & + to_slv(CFI_array(16#0B#), 8) & + to_slv(CFI_array(16#0C#), 8) & + to_slv(CFI_array(16#0D#), 8) & + to_slv(CFI_array(16#0E#), 8) & + to_slv(CFI_array(16#0F#), 8) & + to_slv(CFI_array(16#10#), 8) & + to_slv(CFI_array(16#11#), 8) & + to_slv(CFI_array(16#12#), 8) & + to_slv(CFI_array(16#13#), 8) & + to_slv(CFI_array(16#14#), 8) & + to_slv(CFI_array(16#15#), 8) & + to_slv(CFI_array(16#16#), 8) & + to_slv(CFI_array(16#17#), 8) & + to_slv(CFI_array(16#18#), 8) & + to_slv(CFI_array(16#19#), 8) & + to_slv(CFI_array(16#1A#), 8) & + to_slv(CFI_array(16#1B#), 8) & + to_slv(CFI_array(16#1C#), 8) & + to_slv(CFI_array(16#1D#), 8) & + to_slv(CFI_array(16#1E#), 8) & + to_slv(CFI_array(16#1F#), 8) & + to_slv(CFI_array(16#20#), 8) & + to_slv(CFI_array(16#21#), 8) & + to_slv(CFI_array(16#22#), 8) & + to_slv(CFI_array(16#23#), 8) & + to_slv(CFI_array(16#24#), 8) & + to_slv(CFI_array(16#25#), 8) & + to_slv(CFI_array(16#26#), 8) & + to_slv(CFI_array(16#27#), 8) & + to_slv(CFI_array(16#28#), 8) & + to_slv(CFI_array(16#29#), 8) & + to_slv(CFI_array(16#2A#), 8) & + to_slv(CFI_array(16#2B#), 8) & + to_slv(CFI_array(16#2C#), 8) & + to_slv(CFI_array(16#2D#), 8) & + to_slv(CFI_array(16#2E#), 8) & + to_slv(CFI_array(16#2F#), 8) & + to_slv(CFI_array(16#30#), 8) & + to_slv(CFI_array(16#31#), 8) & + to_slv(CFI_array(16#32#), 8) & + to_slv(CFI_array(16#33#), 8) & + to_slv(CFI_array(16#34#), 8) & + to_slv(CFI_array(16#35#), 8) & + to_slv(CFI_array(16#36#), 8) & + to_slv(CFI_array(16#37#), 8) & + to_slv(CFI_array(16#38#), 8) & + to_slv(CFI_array(16#39#), 8) & + to_slv(CFI_array(16#3A#), 8) & + to_slv(CFI_array(16#3B#), 8) & + to_slv(CFI_array(16#3C#), 8) & + to_slv(CFI_array(16#3D#), 8) & + to_slv(CFI_array(16#3E#), 8) & + to_slv(CFI_array(16#3F#), 8) & + to_slv(CFI_array(16#40#), 8) & + to_slv(CFI_array(16#41#), 8) & + to_slv(CFI_array(16#42#), 8) & + to_slv(CFI_array(16#43#), 8) & + to_slv(CFI_array(16#44#), 8) & + to_slv(CFI_array(16#45#), 8) & + to_slv(CFI_array(16#46#), 8) & + to_slv(CFI_array(16#47#), 8) & + to_slv(CFI_array(16#48#), 8) & + to_slv(CFI_array(16#49#), 8) & + to_slv(CFI_array(16#4A#), 8) & + to_slv(CFI_array(16#4B#), 8) & + to_slv(CFI_array(16#4C#), 8) & + to_slv(CFI_array(16#4D#), 8) & + to_slv(CFI_array(16#4E#), 8) & + to_slv(CFI_array(16#4F#), 8) & + to_slv(CFI_array(16#50#), 8); + + END PROCESS Functional; + + Protect : PROCESS(change_BP) + BEGIN + IF rising_edge(change_BP) THEN + + CASE BP IS + WHEN "000" => + Sec_Prot := (others => '0'); + WHEN "001" => + IF TBPROT = '0' THEN + Sec_Prot(63 downto 63) := (others => '1'); + Sec_Prot(62 downto 0) := (others => '0'); + ELSE + Sec_Prot(0 downto 0) := (others => '1'); + Sec_Prot(63 downto 1) := (others => '0'); + END IF; + WHEN "010" => + IF TBPROT = '0' THEN + Sec_Prot(63 downto 62) := (others => '1'); + Sec_Prot(61 downto 0) := (others => '0'); + ELSE + Sec_Prot(1 downto 0) := (others => '1'); + Sec_Prot(63 downto 2) := (others => '0'); + END IF; + WHEN "011" => + IF TBPROT = '0' THEN + Sec_Prot(63 downto 60) := (others => '1'); + Sec_Prot(59 downto 0) := (others => '0'); + ELSE + Sec_Prot(3 downto 0) := (others => '1'); + Sec_Prot(63 downto 4) := (others => '0'); + END IF; + WHEN "100" => + IF TBPROT = '0' THEN + Sec_Prot(63 downto 56) := (others => '1'); + Sec_Prot(55 downto 0) := (others => '0'); + ELSE + Sec_Prot(7 downto 0) := (others => '1'); + Sec_Prot(63 downto 8) := (others => '0'); + END IF; + WHEN "101" => + IF TBPROT = '0' THEN + Sec_Prot(63 downto 48) := (others => '1'); + Sec_Prot(47 downto 0) := (others => '0'); + ELSE + Sec_Prot(15 downto 0) := (others => '1'); + Sec_Prot(63 downto 16) := (others => '0'); + END IF; + WHEN "110" => + IF TBPROT = '0' THEN + Sec_Prot(63 downto 32) := (others => '1'); + Sec_Prot(31 downto 0) := (others => '0'); + ELSE + Sec_Prot(31 downto 0) := (others => '1'); + Sec_Prot(63 downto 32) := (others => '0'); + END IF; + WHEN OTHERS => + Sec_Prot := (others => '1'); + END CASE; + END IF; + END PROCESS Protect; + + HOLD_FRAME_ON_PO_ZD : PROCESS(SOut_zd, SIOut_zd, HOLDNeg_pullup) + BEGIN + IF (HOLDNeg_pullup = '0' AND QUAD /= '1') THEN + hold_mode := TRUE; + SIOut_z <= 'Z'; + SOut_z <= 'Z'; + ELSE + IF hold_mode THEN + SIOut_z <= SIOut_zd AFTER tpd_HOLDNeg_SO(trz0); + SOut_z <= SOut_zd AFTER tpd_HOLDNeg_SO(trz0); + hold_mode := FALSE; + ELSE + SIOut_z <= SIOut_zd; + SOut_z <= SOut_zd; + hold_mode := FALSE; + END IF; + END IF; + END PROCESS HOLD_FRAME_ON_PO_ZD; + + HOLD_PULL_UP : PROCESS(HOLDNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (HOLDNegIn = 'Z') THEN + HOLDNeg_pullup <= '1'; + ELSE + HOLDNeg_pullup <= HOLDNegIn; + END IF; + END IF; + END PROCESS HOLD_PULL_UP; + + WP_PULL_UP : PROCESS(WPNegIn) + BEGIN + IF (QUAD = '0') THEN + IF (WPNegIn = 'Z') THEN + WPNeg_pullup <= '1'; + ELSE + WPNeg_pullup <= WPNegIn; + END IF; + END IF; + END PROCESS WP_PULL_UP; + + --------------------------------------------------------------------------- + ---- File Read Section - Preload Control + --------------------------------------------------------------------------- + MemPreload : PROCESS + + -- text file input variables + FILE mem_file : text is mem_file_name; + FILE otp_file : text is otp_file_name; + VARIABLE ind : NATURAL RANGE 0 TO AddrRANGE := 0; + VARIABLE secsi_ind : NATURAL RANGE 16#100# TO 16#2FF# := 16#100#; + VARIABLE buf : line; + + BEGIN + --------------------------------------------------------------------------- + --s25fl032p memory preload file format +----------------------------------- + --------------------------------------------------------------------------- + -- / - comment + -- @aaaaaa - stands for address + -- dd -
is byte to be written at Mem(aaaaaa++) + -- (aaaaaa is incremented at every load) + -- only first 1-7 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (mem_file_name /= "none" AND UserPreload) THEN + ind := 0; + Mem := (OTHERS => MaxData); + WHILE (not ENDFILE (mem_file)) LOOP + READLINE (mem_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + IF ind > AddrRANGE THEN + ASSERT false + REPORT "Given preload address is out of" & + "memory address range" + SEVERITY warning; + ELSE + ind := h(buf(2 to 7)); --address + END IF; + ELSE + Mem(ind) := h(buf(1 to 2)); + ind := ind + 1; + END IF; + END LOOP; + END IF; + + --------------------------------------------------------------------------- + --s25fl032p_otp memory preload file format +----------------------------------- + --------------------------------------------------------------------------- + -- / - comment + -- @aaa - stands for address + -- dd -
is byte to be written at OTPMem(aaa++) + -- (aaa is incremented at every load) + -- only first 1-4 columns are loaded. NO empty lines !!!!!!!!!!!!!!!! + --------------------------------------------------------------------------- + + -- memory preload + IF (otp_file_name /= "none" AND UserPreload) THEN + secsi_ind := 16#100#; + OTPMem := (OTHERS => MaxData); + WHILE (not ENDFILE (otp_file)) LOOP + READLINE (otp_file, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + IF secsi_ind > 16#2FF# OR secsi_ind < 16#100# THEN + ASSERT false + REPORT "Given preload address is out of" & + "OTP address range" + SEVERITY warning; + ELSE + secsi_ind := h(buf(2 to 4)); --address + END IF; + ELSE + OTPMem(secsi_ind) := h(buf(1 to 2)); + PR_LOCK1 := to_slv(OTPMem(257),8) & to_slv(OTPMem(256),8); + PR_LOCK2 := to_slv(OTPMem(275),8) & to_slv(OTPMem(274),8); + PR_LOCK3 := to_slv(OTPMem(533),8) & to_slv(OTPMem(532),8); + secsi_ind := secsi_ind + 1; + END IF; + END LOOP; + END IF; + + WAIT; + END PROCESS MemPreload; + + ---------------------------------------------------------------------------- + -- Path Delay Section + ---------------------------------------------------------------------------- + + S_Out_PathDelay_Gen : PROCESS(SOut_z) + + VARIABLE SO_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SOut, + OutSignalName => "PO", + OutTemp => SOut_z, + GlitchData => SO_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SO), + PathCondition => SOut_z /= 'Z' + AND (NOT dual)), + 1 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SI), + PathCondition => SOut_z /= 'Z' + AND dual), + 2 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1'), + 3 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => TRUE) + ) + ); + END PROCESS; + + SI_Out_PathDelay : PROCESS(SIOut_z) + + VARIABLE SI_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => SIOut, + OutSignalName => "SI", + OutTemp => SIOut_z, + GlitchData => SI_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SI), + PathCondition => SIOut_z /= 'Z' AND dual), + 1 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND dual), + 2 => (InputChangeTime => HOLDNegIn'LAST_EVENT, + PathDelay => tpd_HOLDNeg_SO, + PathCondition => dual) + ) + ); + END PROCESS; + + HOLD_Out_PathDelay : PROCESS(HOLDNegOut_zd) + + VARIABLE HOLD_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => HOLDNegOut, + OutSignalName => "HOLDNeg", + OutTemp => HOLDNegOut_zd, + GlitchData => HOLD_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SI), + PathCondition => HOLDNegOut_zd /= 'Z' AND dual + AND QUAD = '1'), + 1 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND dual + AND QUAD = '1') + ) + ); + END PROCESS; + + W_Out_PathDelay : PROCESS(WPNegOut_zd) + + VARIABLE W_GlitchData : VitalGlitchDataType; + BEGIN + VitalPathDelay01Z ( + OutSignal => WPNegOut, + OutSignalName => "WPNeg", + OutTemp => WPNegOut_zd, + GlitchData => W_GlitchData, + Paths => ( + 0 => (InputChangeTime => SCK_ipd'LAST_EVENT, + PathDelay => VitalExtendtofillDelay(tpd_SCK_SI), + PathCondition => HOLDNegOut_zd /= 'Z'AND dual + AND QUAD = '1'), + 1 => (InputChangeTime => CSNeg_ipd'LAST_EVENT, + PathDelay => tpd_CSNeg_SO, + PathCondition => CSNeg_ipd = '1' AND dual + AND QUAD = '1') + ) + ); + END PROCESS; + END BLOCK behavior; +END vhdl_behavioral; diff --git a/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p_ver.ftm b/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p_ver.ftm new file mode 100644 index 0000000..182ab94 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p_ver.ftm @@ -0,0 +1,267 @@ + +FMF Timing for s25fl032p Parts + + +version: | author: | mod date: | changes made: + V1.0 D.Stanojkovic 08 Jan 22 Initial release + V1.1 D.Stanojkovic 08 Mar 05 New timmings added and changed + timming model labeling + V1.2 J.Stoickov 08 Sep 16 Latest datasheet update + V1.3 J.Stoickov 08 Dec 10 Changed timming model labeling + V1.4 S.Petrovic 09 May 29 Timing ranges corrected + V1.5 V.Mancev 11 Dec 13 Latest datasheet update + +1ns +s25fl032p + +S25FL032P0XMFI000_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI001_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI003_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI010_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI011_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI013_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI000_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI001_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI003_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI010_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI011_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI013_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV000_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV001_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV003_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV010_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV011_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV013_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV000_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV001_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV003_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV010_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV011_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV013_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI020_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI023_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI030_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI033_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV020_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV023_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV030_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV033_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +The values listed are for VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + + (DELAY (ABSOLUTE + (COND ~dual (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8))) + (COND dual (IOPATH SCK SO (6.5:8:9.5) (6.5:8:9.5) () (6.5:8:9.5) () (6.5:8:9.5))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (COND dual (IOPATH SCK SI (6.5:8:9.5) (6.5:8:9.5) () (6.5:8:9.5) () (6.5:8:9.5))) + (COND dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual && CSNeg (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK HOLDNeg (6.5:8:9.5) (6.5:8:9.5) () (6.5:8:9.5) () (6.5:8:9.5))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK WPNeg (6.5:8:9.5) (6.5:8:9.5) () (6.5:8:9.5) () (6.5:8:9.5))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) +)) +(TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND fast_rd (negedge SCK)) (4.5)) + (WIDTH (COND fast_rd (posedge SCK)) (4.5)) + (WIDTH (COND dual_rd (negedge SCK)) (4.5)) + (WIDTH (COND dual_rd (posedge SCK)) (4.5)) + (WIDTH (COND rd (negedge SCK)) (4.5)) + (WIDTH (COND rd (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (PERIOD (COND fast_rd SCK) (9.6)) + (PERIOD (COND rd SCK) (25.0)) + (PERIOD (COND rd_jid SCK) (20.0)) + (PERIOD (COND dual_rd SCK) (12.5)) +) + + + + +S25FL032P0XMFI000_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI001_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI003_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI010_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI011_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI013_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI000_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI001_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI003_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI010_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI011_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI013_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV000_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV001_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV003_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV010_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV011_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV013_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV000_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV001_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV003_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV010_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV011_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV013_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI020_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI023_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI030_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI033_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV020_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV023_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV030_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV033_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + + (DELAY (ABSOLUTE + (COND ~dual (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) () (4.5:5.5:6.5) () (4.5:5.5:6.5))) + (COND dual (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (COND dual (IOPATH SCK SI (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8))) + (COND dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual && CSNeg (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK HOLDNeg (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK WPNeg (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) +)) +(TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND fast_rd (negedge SCK)) (4.5)) + (WIDTH (COND fast_rd (posedge SCK)) (4.5)) + (WIDTH (COND dual_rd (negedge SCK)) (4.5)) + (WIDTH (COND dual_rd (posedge SCK)) (4.5)) + (WIDTH (COND rd (negedge SCK)) (4.5)) + (WIDTH (COND rd (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (PERIOD (COND fast_rd SCK) (9.6)) + (PERIOD (COND rd SCK) (25.0)) + (PERIOD (COND rd_jid SCK) (20.0)) + (PERIOD (COND dual_rd SCK) (12.5)) +) + + + + +S25FL032P0XMFI000_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI001_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI003_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI010_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI011_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI013_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI000_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI001_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI003_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI010_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI011_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI013_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV000_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV001_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV003_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV010_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV011_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV013_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV000_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV001_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV003_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV010_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV011_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV013_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI020_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI023_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI030_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI033_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV020_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV023_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV030_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV033_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + + (DELAY (ABSOLUTE + (COND ~dual (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) () (4.5:5.5:6.5) () (4.5:5.5:6.5))) + (COND dual (IOPATH SCK SO (4.7:5.8:7) (4.7:5.8:7) () (4.7:5.8:7) () (4.7:5.8:7))) + + (COND CSNeg (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND ~dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + + (COND dual (IOPATH SCK SI (4.7:5.8:7) (4.7:5.8:7) () (4.7:5.8:7) () (4.7:5.8:7))) + (COND dual (IOPATH HOLDNeg SI () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8))) + (COND dual && CSNeg (IOPATH CSNeg SI () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK HOLDNeg (4.7:5.8:7) (4.7:5.8:7) () (4.7:5.8:7) () (4.7:5.8:7))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg HOLDNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) + + (COND dual && QUAD (IOPATH SCK WPNeg (4.7:5.8:7) (4.7:5.8:7) () (4.7:5.8:7) () (4.7:5.8:7))) + (COND dual && CSNeg && QUAD (IOPATH CSNeg WPNeg () () (5.4:6.7:8) () (5.4:6.7:8) ())) +)) +(TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND fast_rd (negedge SCK)) (4.5)) + (WIDTH (COND fast_rd (posedge SCK)) (4.5)) + (WIDTH (COND dual_rd (negedge SCK)) (4.5)) + (WIDTH (COND dual_rd (posedge SCK)) (4.5)) + (WIDTH (COND rd (negedge SCK)) (4.5)) + (WIDTH (COND rd (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND RD_EQU_1 (posedge CSNeg)) (10)) + (WIDTH (COND RD_EQU_0 (posedge CSNeg)) (50)) + (PERIOD (COND fast_rd SCK) (9.6)) + (PERIOD (COND rd SCK) (25.0)) + (PERIOD (COND rd_jid SCK) (20.0)) + (PERIOD (COND dual_rd SCK) (12.5)) +) + + + diff --git a/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p_vhd.ftm b/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p_vhd.ftm new file mode 100644 index 0000000..1e1dd63 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/model/s25fl032p_vhd.ftm @@ -0,0 +1,279 @@ + +FMF Timing for s25fl032p Parts + + +version: | author: | mod date: | changes made: + V1.0 D.Stanojkovic 08 Jan 22 Initial release + V1.1 D.Stanojkovic 08 Mar 05 New timmings added and changed + timming model labeling + V1.2 J.Stoickov 08 Sep 16 Latest datasheet update + V1.3 J.Stoickov 08 Dec 10 Changed timming model labeling + V1.4 S.Petrovic 09 May 29 Timing ranges corrected + V1.5 V.Mancev 11 Dec 13 Latest datasheet update + +1ns +s25fl032p + +S25FL032P0XMFI000_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI001_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI003_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI010_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI011_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI013_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI000_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI001_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI003_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI010_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI011_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI013_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV000_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV001_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV003_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV010_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV011_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV013_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV000_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV001_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV003_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV010_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV011_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV013_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI020_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI023_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI030_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI033_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV020_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV023_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV030_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV033_F_30pF Spansion, S25FL032P_00_05, October 5, 2009 +The values listed are for full Vcc range VCC=2.7V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (IOPATH SCK SO (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8)) + (IOPATH SCK SI (6.5:8:9.5) (6.5:8:9.5) () (6.5:8:9.5) () (6.5:8:9.5)) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + )) + (TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND serial_fast (negedge SCK)) (4.5)) + (WIDTH (COND serial_fast (posedge SCK)) (4.5)) + (WIDTH (COND dual (negedge SCK)) (4.5)) + (WIDTH (COND dual (posedge SCK)) (4.5)) + (WIDTH (COND serial (negedge SCK)) (4.5)) + (WIDTH (COND serial (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgm (posedge CSNeg)) (50)) + (PERIOD (COND serial_fast_rd SCK) (9.6)) + (PERIOD (COND serial_rd SCK) (25.0)) + (PERIOD (COND serial_rd_jid SCK) (20.0)) + (PERIOD (COND dual_fast_rd SCK) (12.5)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(1200000:1500000:3000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/EP) (DELAY (ABSOLUTE (DEVICE(1000000:1200000:2400000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(40e7:50e7:2e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(25e9:32e9:64e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WR) (DELAY (ABSOLUTE(DEVICE(50000000:50000000:50000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300000:300000:300000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/DP) (DELAY (ABSOLUTE (DEVICE(10000:10000:10000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PE) (DELAY (ABSOLUTE (DEVICE(20e7:20e7:80e7) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/RES) (DELAY (ABSOLUTE (DEVICE(30000:30000:30000) ) ) ) + + + +S25FL032P0XMFI000_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI001_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI003_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI010_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI011_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI013_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI000_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI001_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI003_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI010_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI011_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI013_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV000_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV001_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV003_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV010_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV011_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV013_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV000_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV001_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV003_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV010_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV011_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV013_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI020_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI023_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI030_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI033_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV020_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV023_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV030_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV033_R_30pF Spansion, S25FL032P_00_05, October 5, 2009 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=30pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) () (4.5:5.5:6.5) () (4.5:5.5:6.5)) + (IOPATH SCK SI (5.4:6.7:8) (5.4:6.7:8) () (5.4:6.7:8) () (5.4:6.7:8)) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + )) + (TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND serial_fast (negedge SCK)) (4.5)) + (WIDTH (COND serial_fast (posedge SCK)) (4.5)) + (WIDTH (COND dual (negedge SCK)) (4.5)) + (WIDTH (COND dual (posedge SCK)) (4.5)) + (WIDTH (COND serial (negedge SCK)) (4.5)) + (WIDTH (COND serial (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgm (posedge CSNeg)) (50)) + (PERIOD (COND serial_fast_rd SCK) (9.6)) + (PERIOD (COND serial_rd SCK) (25.0)) + (PERIOD (COND serial_rd_jid SCK) (20.0)) + (PERIOD (COND dual_fast_rd SCK) (12.5)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(1200000:1500000:3000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/EP) (DELAY (ABSOLUTE (DEVICE(1000000:1200000:2400000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(40e7:50e7:2e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(25e9:32e9:64e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WR) (DELAY (ABSOLUTE(DEVICE(50000000:50000000:50000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300000:300000:300000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/DP) (DELAY (ABSOLUTE (DEVICE(10000:10000:10000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PE) (DELAY (ABSOLUTE (DEVICE(20e7:20e7:80e7) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/RES) (DELAY (ABSOLUTE (DEVICE(30000:30000:30000) ) ) ) + + + +S25FL032P0XMFI000_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI001_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI003_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI010_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI011_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFI013_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI000_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI001_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI003_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI010_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI011_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFI013_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV000_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV001_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV003_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV010_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV011_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XMFV013_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV000_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV001_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV003_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV010_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV011_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XNFV013_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI020_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI023_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI030_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHI033_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV020_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV023_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV030_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +S25FL032P0XBHV033_R_15pF Spansion, S25FL032P_00_05, October 5, 2009 +The values listed are for regulated Vcc range VCC=3.0V to 3.6V, CL=15pF, +Industrial Ta=-40 to +85 Celsius + +(DELAY (ABSOLUTE + (IOPATH SCK SO (4.5:5.5:6.5) (4.5:5.5:6.5) () (4.5:5.5:6.5) () (4.5:5.5:6.5)) + (IOPATH SCK SI (4.7:5.8:7) (4.7:5.8:7) () (4.7:5.8:7) () (4.7:5.8:7)) + (IOPATH HOLDNeg SO () () (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8) (5.4:6.7:8)) + (IOPATH CSNeg SO () () (5.4:6.7:8) () (5.4:6.7:8) ()) + )) + (TIMINGCHECK + (SETUP CSNeg SCK (3)) + (SETUP HOLDNeg SCK (3)) + (SETUP SI SCK (3)) + (SETUP WPNeg CSNeg (20)) + + (HOLD CSNeg SCK (3)) + (HOLD HOLDNeg SCK (3)) + (HOLD SI SCK (2)) + (HOLD WPNeg CSNeg (100)) + + (WIDTH (COND serial_fast (negedge SCK)) (4.5)) + (WIDTH (COND serial_fast (posedge SCK)) (4.5)) + (WIDTH (COND dual (negedge SCK)) (4.5)) + (WIDTH (COND dual (posedge SCK)) (4.5)) + (WIDTH (COND serial (negedge SCK)) (4.5)) + (WIDTH (COND serial (posedge SCK)) (4.5)) + (WIDTH (COND rd_jid (negedge SCK)) (4.5)) + (WIDTH (COND rd_jid (posedge SCK)) (4.5)) + (WIDTH (COND read (posedge CSNeg)) (10)) + (WIDTH (COND pgm (posedge CSNeg)) (50)) + (PERIOD (COND serial_fast_rd SCK) (9.6)) + (PERIOD (COND serial_rd SCK) (25.0)) + (PERIOD (COND serial_rd_jid SCK) (20.0)) + (PERIOD (COND dual_fast_rd SCK) (12.5)) +)) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PP) (DELAY (ABSOLUTE (DEVICE(1200000:1500000:3000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/EP) (DELAY (ABSOLUTE (DEVICE(1000000:1200000:2400000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/SE) (DELAY (ABSOLUTE (DEVICE(40e7:50e7:2e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/BE) (DELAY (ABSOLUTE (DEVICE(25e9:32e9:64e9) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/WR) (DELAY (ABSOLUTE(DEVICE(50000000:50000000:50000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PU) (DELAY (ABSOLUTE (DEVICE(300000:300000:300000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/DP) (DELAY (ABSOLUTE (DEVICE(10000:10000:10000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/PE) (DELAY (ABSOLUTE (DEVICE(20e7:20e7:80e7) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE %LABEL%/RES) (DELAY (ABSOLUTE (DEVICE(30000:30000:30000) ) ) ) + + diff --git a/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/mk_sdf.cmd b/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/mk_sdf.cmd new file mode 100644 index 0000000..f6d6cc7 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/mk_sdf.cmd @@ -0,0 +1,10 @@ +SET sdffile_suffix .sdf +SET use_global_timing_dir false +SET timingfile_dir /user/USERNAME/CreateSDF +SET timingfile_suffix .ftm +SET time_scale 1ns +SET local_path . +SET vendor MODELSIM_HOME +SET diagnostics on +SET vhdl_file testbench.vhd +SET lwb false diff --git a/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/mk_sdf_204.pl b/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/mk_sdf_204.pl new file mode 100644 index 0000000..5f2f2b8 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/mk_sdf_204.pl @@ -0,0 +1,462 @@ +#!/usr/local/bin/perl +# +# mk_sdf : Perl replacement for C mk_sdf +# +# Copyright (C) 2000, 1999 Free Model Foundry; http:/vhdl.org/fmf/ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# Author : R. Munden +# Date : 20001115 +# Version : 2.0.4 +# +# Revision history: +# 2.0: 19990702 +# o Intial release of perl version +# 2.0.1: 19990722 +# o fixed problem with . in path for TimingModels +# 2.0.2: 20000616 +# o changed instance search to work with Mentor +# 2.0.3: 20001115 +# o changed to parse ":" without leading space +# o fixed problem with . in path for TimingModels again +# 2.0.4: 20030405 +# o chaged SDF version to 3.0 +# +################################################################# +# +# command line arguments: + +# ARGV[0] - name of VHDL netlist + +# global variables: + +# %component_list - list of instance names by component name +# %instance_isin - list architectures by instances contained therein +# %instance_comp - list of component names by instance name +# %comp_lib - library each component (by name) is configured to +# @instance_list - array of all instance names in design in order found + +$version = "2.0.4"; +$design_name = ''; +$timing_dir = ''; +$diags = "off"; + +%keywords = (architecture => 1, + component => 1, + timingmodel => 1); + +# INPUT files +$CMD = "mk_sdf.cmd"; +$VHD = ''; # name of VHDL netlist + +# OUTPUT files +$RFV = "/tmp/short.vhd"; # reformatted VHDL +$sdf_file = ''; # name of SDF file + +&read_cmd_file; +&get_names; +&reformat; + +open INPUT, $RFV; +@lines = ; +close INPUT; + +$current_architecture = ""; + +foreach $line (@lines) +{ + @words = split / /, $line; + foreach $word (@words) + { + $keywords{$word} == "1" and do { &$word(@words);}; + if ($component_list{$word}) + { + $line =~ /(.+) : $word/ and do { + if ($1 !~ /for/) { # instantiation found + $component_list{$word} = $component_list{$word} . $1; + push (@instance_list, $1); + $instance_name = $1; + } + }; + $instance_comp{$1} = $word; + $instance_isin{$1} = $current_architecture; + if ( $diags ne off ) { + print "reading instance $instance_name: $word in $current_architecture\n"; + } + $line =~ /for all : $word use entity (.+)/ and do + { + @config = split(/\./, $1); + $comp_lib{$word} = $config[0];}; + } + } +} +if ( $diags ne off ) { + print "finished with netlist\n\n"; +} + +&begin_sdf; +&build_paths; +&close_sdf; +`rm $RFV`; + +print "$time\n"; + +sub architecture +{ + $current_architecture = $_[3]; + push (@architectures, $current_architecture); +} + +sub component +{ + if ($_[0] ne "end") + { + $name = $_[1]; + $arch_list{$current_architecture} = + $arch_list{$current_architecture} . " " . $name; + unless ($component_list{$name}) { $component_list{$name} = " ";} + } +} + +sub timingmodel +{ + $line =~ /timingmodel => \"(.+)\"/ and do { + $model = $1; + $model_name{$instance_name} = $model; + }; +} + +sub begin_sdf +{ + if ( $diags ne off ) { + print "writing SDF boilerplate\n"; + } + $time = localtime; + if (open(SDF, ">$sdf_file") !=1) { die "can't open $sdf_file\n";} + print "Opening $sdf_file\n"; + print SDF "(DELAYFILE\n"; + print SDF " (SDFVERSION \"3.0\")\n"; + print SDF " (DESIGN \"$design_name\")\n"; + print SDF " (DATE \"$time\")\n"; + print SDF " (VENDOR \"Free Model Foundry\")\n"; + print SDF " (PROGRAM \"SDF timing utility(tm)\")\n"; + print SDF " (VERSION \"$version\")\n"; + print SDF " (DIVIDER /)\n"; + print SDF " (VOLTAGE)\n"; + print SDF " (PROCESS)\n"; + print SDF " (TEMPERATURE)\n"; + print SDF " (TIMESCALE 1ns)\n"; +} + +sub build_paths +{ + foreach $instance_list (@instance_list) + { + @instance = $instance_list; + foreach $instance (@instance) + { + if ( $diags ne off ) { + print "working on $instance\n"; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + $timing_file =~ s/\s//; + if ( $diags ne off ) { + print "$instance should be in $timing_file\n"; + } + if (-e $timing_file) { + if ($model_name{$instance} ne "") { + print SDF " (CELL\n"; + print SDF " (CELLTYPE \"$instance_comp{$instance}\")\n"; + $inst = $instance; + $full_inst = $instance; + while ($component_list{$instance_isin{$inst}}) { + $full_inst = "$component_list{$instance_isin{$inst}}/$full_inst"; + $full_inst =~ s/\s+//; + $inst = $component_list{$instance_isin{$inst}}; + $inst =~ s/\s+//; +# print SDF " (INSTANCE $component_list{$instance_isin{$instance}}/$instance)\n"; + } + print SDF " (INSTANCE $full_inst)\n"; + &add_timing; + } + } else { + if ( $diags ne off ) { + print "$timing_file not found!\n"; + } + } + } + } +} + +sub add_timing +{ + $timing_found = "false"; + $part_found = "false"; +# unless ($lib_path{$comp_lib{$instance_comp{$instance}}}) + unless ($timing_file) + { + print "path to $timing_file not found\n"; + exit; + } + if ($gtd =~ /true/i) { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; +# $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}./$timing_dir"; + } else { + $path = "$lib_path{$comp_lib{$instance_comp{$instance}}}/$timing_dir"; + } + $timing_file = "$path/$instance_comp{$instance}_vhd.ftm"; + if (open(TF, "<$timing_file") !=1) { warn "can't open $timing_file\n"; } + if ( $diags ne off ) { + print "reading $timing_file\n"; + } + $section_found = "false"; + while () + { + next unless (/$model_name{$instance}/i || ($part_found eq "true")); + $part_found = "true"; + if ( $diags ne off ) { + print "found entry for $model_name{$instance}\n"; + } + next unless (//i || ($timing_found eq "true")); + $timing_found = "true"; + next if (//i); + if (/<\/timing>/i) + { + print SDF " )\n"; + $timing_found = "false"; + $part_found = "false"; + $section_found = "true"; + last; + } else { + if (/%LABEL%/) + { + if ($component_list{$instance_isin{$instance}}) + { + $_ =~ s/%LABEL%/$component_list{$instance_isin{$instance}}\/$instance/; + } else { + $_ =~ s/%LABEL%/$instance/; + } + } + print SDF $_; + } + } + unless ($section_found eq "true") { + print "$model_name not found\n"; + } +} + +sub close_sdf +{ + print SDF ")\n"; + print "closing $sdf_file\n"; + close(SDF); +} + +# read mk_sdf.cmd + +sub read_cmd_file { + + if (open(CMD, $CMD) !=1) { die "can't open $CMD\n"; } + while () { + chop; + @fields = ''; + @fields = split; + unless ($fields[0] =~ /#/) { + if ($fields[0] =~ /SET/) { + if ($fields[1] =~ /vhdl_file/) {$VHD = $fields[2]} + if ($fields[1] =~ /sdffile_suffix/) {$suffix = $fields[2]} + if ($fields[1] =~ /use_global_timing_dir/) {$gtd = $fields[2]} + if ($fields[1] =~ /timingfile_dir/) {$timing_dir = $fields[2]} + if ($fields[1] =~ /vendor/) {$vendor = $fields[2]} + if ($fields[1] =~ /diagnostics/) {$diags = $fields[2]} + } + } + } + if ( $diags ne off ) { + print "\nmk_sdf diagnostics on\n\n"; + print "vhdl_file $VHD\n"; + print "sdffile_suffix $suffix\n"; + print "use_global_timing_dir $gtd\n"; + print "timingfile_dir $timing_dir\n"; + print "vendor $vendor\n\n"; + } +} +# + +# get name of netlist + +sub get_names +{ + + if ($ARGV[0] ne "") { $VHD = "$ARGV[0]"; } + + if ($ARGV[1] eq "") + { + @name = split(/\./,$VHD); + $design_name = $name[0]; + } else { + $design_name = "$ARGV[1]"; + } + $sdf_file = $design_name . $suffix; + if ($gtd =~ /false/i) + { + if ($vendor =~ /modeltech/i) { &read_mti; } + if ($vendor =~ /cadence/i) { &read_cds; } + } + if ( $diags ne off ) { + print "design name is $design_name\n\n"; + } +} +# +################################################################ +# + +# reformat netlist + +sub reformat +{ + $entfound = false; + + if (open(VHD, $VHD) !=1) { die "can't open $VHD\n"; } + if (open(OUT, ">$RFV") !=1) { die "can't open $OUT\n"; } + + while () { + if (/^--|library|package/i) { next } + if (/--/) { # strip embeded comments + @line = split("--"); + $_ = $line[0]; + } + s/:/ : /g; + s/;/ ;/g; + s/\s+/ /g; # reduces spaces and tabs + s/^\s//g; # no leading spaces + if (/entity/i) { + $entfound = "true"; + } + chomp; + if ( $entfound eq true ) { + print OUT lc($_); + if (/;|is|begin/i) { print OUT "\n"; } + } + } + + close OUT; + if ( $diags ne off ) { + print "reformatted netlist written to $RFV\n\n"; + } + +} + +# read ModelTech's modelsim.ini file + +sub read_mti +{ + $lib_found = "false"; + if ($ENV{MODELPATH}) + { + $ini_file = "$ENV{MODELPATH}/../modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "\$MODELPATH environment variable not found\n"; + } + $lib_found = "false"; + if (-e "modelsim.ini") + { + $ini_file = "modelsim.ini"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + if ($lib_found eq "true") + { + chomp; + if (/\[.+\]/) { last; } + s/\s+//; + @lib_line = split(/=/); + $lib_line[1] =~ s/\/work//; + $lib_path{$lib_line[0]} = $lib_line[1]; + } elsif (/\[Library\]/i) + { + $lib_found = "true"; + next; + } + } + } else { + print "local modelsim.ini file not found, may not be needed\n"; + } +} + +# read Cadence's cds.lib file + +sub read_cds +{ + if ($ENV{CDS_VHDL}) + { + $ini_file = "$ENV{CDS_VHDL}/files/cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "\$CDS_VHDL environment variable not found\n"; + } + if (-e "cds.lib") + { + $ini_file = "cds.lib"; + if (open(INI, "$ini_file") !=1) { die "can't open $ini_file\n";} + if ( $diags ne off ) { + print "reading $ini_file\n\n"; + } + while () + { + chomp; + s/\s+/ /; + if (/define/i) + { + @lib_line = split; + $lib_path{$lib_line[1]} = $lib_line[2]; + } + } + } else { + print "local cds.lib file not found, may not be needed\n"; + } +} diff --git a/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/my_mem_vhd.ftm b/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/my_mem_vhd.ftm new file mode 100644 index 0000000..2fc35c2 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/my_mem_vhd.ftm @@ -0,0 +1,205 @@ + +FMF Timing for testbench Parts + + +version: | author: | mod date: | changes made: + V1.0 VHD2FTM 03 July 11 Initial release + +1ns +am29lv640m + +MY_MEM +AM29LV640MH90R +AM29LV640ML90R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH101 +AM29LV640ML101 +AM29LV640MH101R +AM29LV640ML101R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (100:100:100) (100:100:100)) + (IOPATH A0 DQ1 (30:30:30) (30:30:30)) + (IOPATH CENeg DQ0 (95:95:95) (95:95:95) (11:11:11) (95:95:95) (11:11:11) (95:95:95)) + (IOPATH OENeg DQ0 (25:25:25) (25:25:25) (11:11:11) (25:25:25) (11:11:11) (25:25:25)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (100)) + (IOPATH WENeg RY (0) (100)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (100:100:100)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH112 +AM29LV640ML112 +AM29LV640MH112R +AM29LV640ML112R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (110:110:110) (110:110:110)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (105:105:105) (105:105:105) (11:11:11) (105:105:105) (11:11:11) (105:105:105)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (110)) + (IOPATH WENeg RY (0) (110)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (110:110:110)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + +AM29LV640MH120 +AM29LV640ML120 +AM29LV640MH120R +AM29LV640ML120R + + + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (120:120:120) (120:120:120)) + (IOPATH A0 DQ1 (40:40:40) (40:40:40)) + (IOPATH CENeg DQ0 (115:115:115) (115:115:115) (11:11:11) (115:115:115) (11:11:11) (115:115:115)) + (IOPATH OENeg DQ0 (35:35:35) (35:35:35) (11:11:11) (35:35:35) (11:11:11) (35:35:35)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (120)) + (IOPATH WENeg RY (0) (120)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (120:120:120)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + + diff --git a/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/testbench.sdf b/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/testbench.sdf new file mode 100644 index 0000000..02495dd --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/testbench.sdf @@ -0,0 +1,58 @@ +(DELAYFILE + (SDFVERSION "3.0") + (DESIGN "testbench") + (DATE "Wed Jan 28 15:15:41 2004") + (VENDOR "Free Model Foundry") + (PROGRAM "SDF timing utility(tm)") + (VERSION "2.0.4") + (DIVIDER /) + (VOLTAGE) + (PROCESS) + (TEMPERATURE) + (TIMESCALE 1ns) + (CELL + (CELLTYPE "my_mem") + (INSTANCE dut) + (DELAY (ABSOLUTE + (IOPATH A0 DQ0 (90:90:90) (90:90:90)) + (IOPATH A0 DQ1 (25:25:25) (25:25:25)) + (IOPATH CENeg DQ0 (85:85:85) (85:85:85) (11:11:11) (85:85:85) (11:11:11) (85:85:85)) + (IOPATH OENeg DQ0 (20:20:20) (20:20:20) (11:11:11) (20:20:20) (11:11:11) (20:20:20)) + (IOPATH RESETNeg DQ0 () () (0:0:0) () (0:0:0) ()) + (IOPATH CENeg RY (0) (90)) + (IOPATH WENeg RY (0) (90)) + )) + (TIMINGCHECK + (SETUP A0 CENeg (0:0:0)) + (SETUP A0 OENeg (15:15:15)) + (SETUP DQ0 CENeg (45:45:45)) + (HOLD CENeg RESETNeg (50:50:50)) + (HOLD OENeg WENeg (0:0:0)) + (HOLD A0 CENeg (45:45:45)) + (HOLD A0 OENeg (0:0:0)) + (HOLD DQ0 CENeg (0:0:0)) + (HOLD WENeg OENeg (0:0:0)) + (WIDTH (negedge RESETNeg) (500:500:500)) + (WIDTH (posedge OENeg) (20:20:20)) + (WIDTH (negedge WENeg) (35:35:35)) + (WIDTH (posedge WENeg) (30:30:30)) + (WIDTH (negedge CENeg) (45:45:45)) + (WIDTH (posedge CENeg) (30:30:30)) + (WIDTH (negedge A0) (90:90:90)) + )) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/WBPB) (DELAY (ABSOLUTE (DEVICE(11000:11000:11000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/POB) (DELAY (ABSOLUTE (DEVICE(100000:100000:100000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/SEO) (DELAY (ABSOLUTE (DEVICE(500000000:500000000:500000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/HANG) (DELAY (ABSOLUTE (DEVICE(400000000:400000000:400000000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/START_T1) (DELAY (ABSOLUTE (DEVICE(5000:5000:20000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/CTMOUT) (DELAY (ABSOLUTE (DEVICE(50000:50000:50000) ) ) ) ) + (CELL (CELLTYPE "VITALbuf") + (INSTANCE dut/READY) (DELAY (ABSOLUTE (DEVICE(20000:20000:20000) ) ) ) + ) +) diff --git a/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/testbench.vhd b/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/testbench.vhd new file mode 100644 index 0000000..c7d852a --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/utilities/CreateSDF/testbench.vhd @@ -0,0 +1,1606 @@ +------------------------------------------------------------------------------ +-- File name : testbench_640.vhd +------------------------------------------------------------------------------- +-- Copyright (C) 2003 AMD. +-- +-- MODIFICATION HISTORY : +-- +-- version: | author: | mod date: | changes made: +-- V0.1 M.Marinkovic 11 July 03 Initial +-- v0.2 M.Marinkovic 28 Aug 03 Changed protected sector selection +-- +------------------------------------------------------------------------------- +-- PART DESCRIPTION: +-- +-- Description: +-- Generic test enviroment for verification of AMD flash memory +-- VITAL models.my_mem +-- +------------------------------------------------------------------------------- +-- Note: VHDL code formating not done +-- For High/Low sector protection selection change: +-- TimingModel constant and TimingModel generic value +-- +------------------------------------------------------------------------------- +LIBRARY IEEE; + USE IEEE.std_logic_1164.ALL; +--USE IEEE.VITAL_timing.ALL; +--USE IEEE.VITAL_primitives.ALL; + USE STD.textio.ALL; + +LIBRARY VITAL2000; + USE VITAL2000.vital_timing.ALL; + USE VITAL2000.vital_primitives.ALL; + +LIBRARY FMF; + USE FMF.gen_utils.ALL; + USE FMF.conversions.ALL; + + +LIBRARY work; + USE work.amd_tc_pkg.ALL; + +------------------------------------------------------------------------------- +-- ENTITY DECLARATION +------------------------------------------------------------------------------- +ENTITY testbench_640 IS +END testbench_640; + + +------------------------------------------------------------------------------- +-- ARCHITECTURE DECLARATION +------------------------------------------------------------------------------- +ARCHITECTURE vhdl_behavioral of testbench_640 IS + COMPONENT my_mem + GENERIC ( + -- tipd delays: interconnect path delays + tipd_A0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A6 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A7 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A9 : VitalDelayType01 := VitalZeroDelay01; --address + tipd_A10 : VitalDelayType01 := VitalZeroDelay01; --lines + tipd_A11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A14 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A15 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A16 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A17 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A18 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A19 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A20 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_A21 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ0 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ1 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ2 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ3 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ4 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ5 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ6 : VitalDelayType01 := VitalZeroDelay01; -- data + tipd_DQ7 : VitalDelayType01 := VitalZeroDelay01; -- lines + tipd_DQ8 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ9 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ10 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ11 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ12 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ13 : VitalDelayType01 := VitalZeroDelay01; -- + tipd_DQ14 : VitalDelayType01 := VitalZeroDelay01; -- + + tipd_DQ15 : VitalDelayType01 := VitalZeroDelay01; -- DQ15/A-1 + + tipd_CENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_OENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WENeg : VitalDelayType01 := VitalZeroDelay01; + tipd_RESETNeg : VitalDelayType01 := VitalZeroDelay01; + tipd_WPNeg : VitalDelayType01 := VitalZeroDelay01; --WP#/ACC + tipd_BYTENeg : VitalDelayType01 := VitalZeroDelay01; + + -- tpd delays + tpd_A0_DQ0 : VitalDelayType01 := UnitDelay01;--tACC + tpd_A0_DQ1 : VitalDelayType01 := UnitDelay01;--tPACC + tpd_CENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tCE,tCE,tDF,-,tDF,-) + tpd_OENeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(tOE,tOE,tDF,-,tDF,-) + tpd_RESETNeg_DQ0 : VitalDelayType01Z := UnitDelay01Z; + --(-,-,0,-,0,-) + tpd_CENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + tpd_WENeg_RY : VitalDelayType01 := UnitDelay01; --tBUSY + + --tsetup values + tsetup_A0_CENeg : VitalDelayType := UnitDelay; --tAS edge \ + tsetup_A0_OENeg : VitalDelayType := UnitDelay; --tASO edge \ + tsetup_DQ0_CENeg : VitalDelayType := UnitDelay; --tDS edge / + + --thold values + thold_CENeg_RESETNeg: VitalDelayType := UnitDelay; --tRH edge / + thold_OENeg_WENeg : VitalDelayType := UnitDelay; --tOEH edge / + thold_A0_CENeg : VitalDelayType := UnitDelay; --tAH edge \ + thold_A0_OENeg : VitalDelayType := UnitDelay; --tAHT edge \ + thold_DQ0_CENeg : VitalDelayType := UnitDelay; --tDH edge / + thold_WENeg_OENeg : VitalDelayType := UnitDelay; --tGHWL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge: VitalDelayType := UnitDelay; --tRP + tpw_OENeg_posedge : VitalDelayType := UnitDelay; --tOEPH + tpw_WENeg_negedge : VitalDelayType := UnitDelay; --tWP + tpw_WENeg_posedge : VitalDelayType := UnitDelay; --tWPH + tpw_CENeg_negedge : VitalDelayType := UnitDelay; --tCP + tpw_CENeg_posedge : VitalDelayType := UnitDelay; --tCEPH + tpw_A0_negedge : VitalDelayType := UnitDelay; --tWC tRC + + + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB : VitalDelayType := 11 us; + --Program Operation + tdevice_POB : VitalDelayType := 100 us; + --Sector Erase Operation tWHWH2 + tdevice_SEO : VitalDelayType := 500 ms; + --Timing Limit Exceeded + tdevice_HANG : VitalDelayType := 400 ms; --? + --program/erase suspend timeout + tdevice_START_T1 : VitalDelayType := 5 us; + --sector erase command sequence timeout + tdevice_CTMOUT : VitalDelayType := 50 us; + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY : VitalDelayType := 20 us; --tReady + + -- generic control parameters + InstancePath : STRING := DefaultInstancePath; + TimingChecksOn : BOOLEAN := DefaultTimingChecks; + MsgOn : BOOLEAN := DefaultMsgOn; + XOn : BOOLEAN := DefaultXon; + -- memory file to be loaded + mem_file_name : STRING ;--:= "am29lv640m.mem"; + prot_file_name : STRING ;--:= "am29lv640m_prot.mem"; + secsi_file_name : STRING ;--:= "am29lv_secsi.mem"; + + UserPreload : BOOLEAN ;--:= TRUE; + LongTimming : BOOLEAN ;--:= TRUE; + + -- For FMF SDF technology file usage + TimingModel : STRING --:= "AM29LV640MH90R" + ); + PORT ( + A21 : IN std_logic := 'U'; -- + A20 : IN std_logic := 'U'; -- + A19 : IN std_logic := 'U'; -- + A18 : IN std_logic := 'U'; -- + A17 : IN std_logic := 'U'; -- + A16 : IN std_logic := 'U'; -- + A15 : IN std_logic := 'U'; -- + A14 : IN std_logic := 'U'; -- + A13 : IN std_logic := 'U'; --address + A12 : IN std_logic := 'U'; --lines + A11 : IN std_logic := 'U'; -- + A10 : IN std_logic := 'U'; -- + A9 : IN std_logic := 'U'; -- + A8 : IN std_logic := 'U'; -- + A7 : IN std_logic := 'U'; -- + A6 : IN std_logic := 'U'; -- + A5 : IN std_logic := 'U'; -- + A4 : IN std_logic := 'U'; -- + A3 : IN std_logic := 'U'; -- + A2 : IN std_logic := 'U'; -- + A1 : IN std_logic := 'U'; -- + A0 : IN std_logic := 'U'; -- + + DQ15 : INOUT std_logic := 'U'; -- DQ15/A-1 + DQ14 : INOUT std_logic := 'U'; -- + DQ13 : INOUT std_logic := 'U'; -- + DQ12 : INOUT std_logic := 'U'; -- + DQ11 : INOUT std_logic := 'U'; -- + DQ10 : INOUT std_logic := 'U'; -- + DQ9 : INOUT std_logic := 'U'; -- data + DQ8 : INOUT std_logic := 'U'; -- lines + DQ7 : INOUT std_logic := 'U'; -- + DQ6 : INOUT std_logic := 'U'; -- + DQ5 : INOUT std_logic := 'U'; -- + DQ4 : INOUT std_logic := 'U'; -- + DQ3 : INOUT std_logic := 'U'; -- + DQ2 : INOUT std_logic := 'U'; -- + DQ1 : INOUT std_logic := 'U'; -- + DQ0 : INOUT std_logic := 'U'; -- + + CENeg : IN std_logic := 'U'; + OENeg : IN std_logic := 'U'; + WENeg : IN std_logic := 'U'; + RESETNeg : IN std_logic := 'U'; + WPNeg : IN std_logic := 'U'; --WP#/ACC + BYTENeg : IN std_logic := 'U'; + RY : OUT std_logic := 'U' --RY/BY# + ); + END COMPONENT; + + FOR ALL: my_mem USE ENTITY WORK.my_mem(VHDL_BEHAVIORAL); + + --------------------------------------------------------------------------- + --memory configuration + --------------------------------------------------------------------------- + CONSTANT MaxData : NATURAL := 16#FF#; --255; + CONSTANT SecSize : NATURAL := 16#FFFF#; --65535 + CONSTANT SecSiSize : NATURAL := 255; + CONSTANT SecNum : NATURAL := 127; + CONSTANT HiAddrBit : NATURAL := 21; + --Address of the Protected Sector +-- CONSTANT ProtSecNum : NATURAL := SecNum; + + --------------------------------------------------------------------------- + --model configuration + --------------------------------------------------------------------------- + CONSTANT mem_file : STRING := "am29lv640m.mem"; + CONSTANT prot_file : STRING := "am29lv640m_prot.mem"; + CONSTANT secsi_file : STRING := "am29lv_secsi.mem"; + + CONSTANT UserPreload : boolean := TRUE; + CONSTANT DebugInfo : boolean := FALSE; + CONSTANT LongTimming : boolean := TRUE; + CONSTANT TimingModel : STRING := "MY_MEM"; + -- "AM29LV640MH90R";--High sect prot. + -- "AM29LV128ML93R";--Low sect. prot. + --------------------------------------------------------------------------- + SIGNAL ProtSecNum : NATURAL := SecNum ; + + --Flash Memory Array + TYPE SecType IS ARRAY (0 TO SecSize) OF + INTEGER RANGE -1 TO MaxData; + TYPE MemArray IS ARRAY (0 TO SecNum) OF + SecType; + + --Common Flash Interface Query codes + TYPE CFItype IS ARRAY (16#10# TO 16#50#) OF + NATURAL RANGE 0 TO 16#FF#; + + --SecSi Sector + TYPE SecSiType IS ARRAY ( 0 TO SecSiSize) OF + INTEGER RANGE -1 TO MaxData; + + --------------------------------------------------------------------------- + -- memory declaration + --------------------------------------------------------------------------- + -- -- Mem(SecAddr)(Address).... + SHARED VARIABLE Mem : MemArray := (OTHERS => (OTHERS=> MaxData)); + SHARED VARIABLE CFI_array : CFItype :=(OTHERS=>0); + SHARED VARIABLE SecSi : SecSiType :=(OTHERS=>0); + + --command sequence + SHARED VARIABLE cmd_seq : cmd_seq_type; + + SIGNAL status : status_type := none; + SIGNAL sts_check : std_logic_vector(7 downto 0); + + + SIGNAL check_err : std_logic := '0'; + SIGNAL ErrorInTest : std_logic := '0'; -- + ---------------------------------------------------------------------------- + --Personality module: + -- + -- instanciates the DUT module and adapts generic test signals to it + -- TBD: block port + ---------------------------------------------------------------------------- + --DUT port + SIGNAL T_DQ : std_logic_vector(15 downto 0) := (OTHERS=>'U'); + SIGNAL T_A : std_logic_vector(HiAddrBit downto 0) := (OTHERS=>'U'); + SIGNAL T_RESETNeg : std_logic := 'U'; + SIGNAL T_CENeg : std_logic := 'U'; + SIGNAL T_WENeg : std_logic := 'U'; + SIGNAL T_OENeg : std_logic := 'U'; + SIGNAL T_WPNeg : std_logic := 'U'; + SIGNAL T_BYTENeg : std_logic := 'U'; + SIGNAL T_RY : std_logic := 'U'; + + --------------------------------------------------------------------------- + -- + --------------------------------------------------------------------------- + --SecSi ProtectionStatus + SHARED VARIABLE FactoryProt : std_logic := '1'; + --Sector Protection Status + SHARED VARIABLE Sec_Prot : std_logic_vector (SecNum downto 0) := + (OTHERS => '0'); + SHARED VARIABLE Sect : NATURAL RANGE 0 TO SecNum := 0; + SHARED VARIABLE Addr : NATURAL RANGE 0 TO SecSize := 0; + SHARED VARIABLE WriteData : NATURAL RANGE 0 TO MaxData := 0; + + + --CONSTANT + --timming parameters + CONSTANT RESETNeg_pw : time := 500 ns; --tRP + + SIGNAL pwron : std_logic := '0'; + + SIGNAL Tseries : NATURAL; + SIGNAL Tcase : NATURAL; + + SHARED VARIABLE ts_cnt : NATURAL RANGE 1 TO 30:=1; -- testseries counter + SHARED VARIABLE tc_cnt : NATURAL RANGE 0 TO 10:=0; -- testcase counter + + + BEGIN + DUT : my_mem + GENERIC MAP ( + -- tipd delays: interconnect path delays + tipd_A0 => VitalZeroDelay01, -- + tipd_A1 => VitalZeroDelay01, -- + tipd_A2 => VitalZeroDelay01, -- + tipd_A3 => VitalZeroDelay01, -- + tipd_A4 => VitalZeroDelay01, -- + tipd_A5 => VitalZeroDelay01, -- + tipd_A6 => VitalZeroDelay01, -- + tipd_A7 => VitalZeroDelay01, -- + tipd_A8 => VitalZeroDelay01, -- + tipd_A9 => VitalZeroDelay01, --address + tipd_A10 => VitalZeroDelay01, --lines + tipd_A11 => VitalZeroDelay01, -- + tipd_A12 => VitalZeroDelay01, -- + tipd_A13 => VitalZeroDelay01, -- + tipd_A14 => VitalZeroDelay01, -- + tipd_A15 => VitalZeroDelay01, -- + tipd_A16 => VitalZeroDelay01, -- + tipd_A17 => VitalZeroDelay01, -- + tipd_A18 => VitalZeroDelay01, -- + tipd_A19 => VitalZeroDelay01, -- + tipd_A20 => VitalZeroDelay01, -- + tipd_A21 => VitalZeroDelay01, -- + + tipd_DQ0 => VitalZeroDelay01, -- + tipd_DQ1 => VitalZeroDelay01, -- + tipd_DQ2 => VitalZeroDelay01, -- + tipd_DQ3 => VitalZeroDelay01, -- + tipd_DQ4 => VitalZeroDelay01, -- + tipd_DQ5 => VitalZeroDelay01, -- + tipd_DQ6 => VitalZeroDelay01, -- data + tipd_DQ7 => VitalZeroDelay01, -- lines + tipd_DQ8 => VitalZeroDelay01, -- + tipd_DQ9 => VitalZeroDelay01, -- + tipd_DQ10 => VitalZeroDelay01, -- + tipd_DQ11 => VitalZeroDelay01, -- + tipd_DQ12 => VitalZeroDelay01, -- + tipd_DQ13 => VitalZeroDelay01, -- + tipd_DQ14 => VitalZeroDelay01, -- + + tipd_DQ15 => VitalZeroDelay01, -- DQ15/A-1 + + tipd_CENeg => VitalZeroDelay01, + tipd_OENeg => VitalZeroDelay01, + tipd_WENeg => VitalZeroDelay01, + tipd_RESETNeg => VitalZeroDelay01, + tipd_WPNeg => VitalZeroDelay01,--WP#/ACC + tipd_BYTENeg => VitalZeroDelay01, + + -- tpd delays + tpd_A0_DQ0 => UnitDelay01,--tACC + tpd_A0_DQ1 => UnitDelay01,--tPACC + tpd_CENeg_DQ0 => UnitDelay01Z, + --(tCE,tCE,tDF,-,tDF + tpd_OENeg_DQ0 => UnitDelay01Z, + --(tOE,tOE,tDF,-,tDF + tpd_RESETNeg_DQ0 => UnitDelay01Z, + --(-,-,0,-,0,-) + tpd_CENeg_RY => UnitDelay01, --tBUSY + tpd_WENeg_RY => UnitDelay01, --tBUSY + + --tsetup values + tsetup_A0_CENeg => UnitDelay, --tAS edge \ + tsetup_A0_OENeg => UnitDelay, --tASO edge \ + tsetup_DQ0_CENeg => UnitDelay, --tDS edge / + + --thold values + thold_CENeg_RESETNeg=> UnitDelay, --tRH edge / + thold_OENeg_WENeg => UnitDelay, --tOEH edge / + thold_A0_CENeg => UnitDelay, --tAH edge \ + thold_A0_OENeg => UnitDelay, --tAHT edge \ + thold_DQ0_CENeg => UnitDelay, --tDH edge / + thold_WENeg_OENeg => UnitDelay, --tGHVL edge / + + --tpw values: pulse width + tpw_RESETNeg_negedge=> UnitDelay, --tRP + tpw_OENeg_posedge => UnitDelay, --tOEPH + tpw_WENeg_negedge => UnitDelay, --tWP + tpw_WENeg_posedge => UnitDelay, --tWPH + tpw_CENeg_negedge => UnitDelay, --tCP + tpw_CENeg_posedge => UnitDelay, --tCEPH + tpw_A0_negedge => UnitDelay, --tWC tRC + -- tdevice values: values for internal delays + --Effective Write Buffer Program Operation tWHWH1 + tdevice_WBPB => 11 us, + --Program Operation + tdevice_POB => 100 us, + --Sector Erase Operation tWHWH2 + tdevice_SEO => 500 ms, + --Timing Limit Exceeded + tdevice_HANG => 400 ms, --? + --program/erase suspend timeout + tdevice_START_T1 => 5 us, + --sector erase command sequence timeout + tdevice_CTMOUT => 50 us, + --device ready after Hardware reset(during embeded algorithm) + tdevice_READY => 20 us, --tReady + + -- generic control parameters + InstancePath => DefaultInstancePath, + TimingChecksOn => TRUE,--DefaultTimingChecks, + MsgOn => DefaultMsgOn, + XOn => DefaultXon, + -- memory file to be loaded + mem_file_name => mem_file, + prot_file_name => prot_file , + secsi_file_name => secsi_file, + + UserPreload => UserPreload, + LongTimming => LongTimming, + -- For FMF SDF technology file usage + TimingModel => "AM29LV640MH90R" -- TimingModel + ) + PORT MAP( + A21 => T_A(21), -- + A20 => T_A(20), -- + A19 => T_A(19), -- + A18 => T_A(18), -- + A17 => T_A(17), -- + A16 => T_A(16), -- + A15 => T_A(15), -- + A14 => T_A(14), -- + A13 => T_A(13), --address + A12 => T_A(12), --lines + A11 => T_A(11), -- + A10 => T_A(10), -- + A9 => T_A(9), -- + A8 => T_A(8), -- + A7 => T_A(7), -- + A6 => T_A(6), -- + A5 => T_A(5),-- + A4 => T_A(4),-- + A3 => T_A(3), -- + A2 => T_A(2), -- + A1 => T_A(1), -- + A0 => T_A(0), -- + + DQ15 => T_DQ(15), -- DQ15/A-1 + DQ14 => T_DQ(14), -- + DQ13 => T_DQ(13), -- + DQ12 => T_DQ(12), -- + DQ11 => T_DQ(11), -- + DQ10 => T_DQ(10), -- + DQ9 => T_DQ(9), -- data + DQ8 => T_DQ(8), -- lines + DQ7 => T_DQ(7), -- + DQ6 => T_DQ(6), -- + DQ5 => T_DQ(5), -- + DQ4 => T_DQ(4), -- + DQ3 => T_DQ(3), -- + DQ2 => T_DQ(2), -- + DQ1 => T_DQ(1), -- + DQ0 => T_DQ(0), -- + + CENeg => T_CENeg, + OENeg => T_OENeg, + WENeg => T_WENeg, + RESETNeg => T_RESETNeg, + WPNeg => T_WPNeg, --WP#/ACC + BYTENeg => T_BYTENeg, + RY => T_RY --RY/BY# + ); + + --------------------------------------------------------------------------- + --protected sector + --------------------------------------------------------------------------- + ProtSecNum <= SecNum WHEN TimingModel(11) = 'H' ELSE + 0 ;-- WHEN TimingModel = "AM29LV128ML93R" + + pwron <= '0', '1' after 1 ns; + +--At the end of the simulation, if ErrorInTest='0' there were no errors +err_ctrl : PROCESS ( check_err ) + BEGIN + IF check_err = '1' THEN + ErrorInTest <= '1'; + END IF; + END PROCESS err_ctrl; + +tb :PROCESS + + -------------------------------------------------------------------------- + --= PROCEDURE to select TC + -- can be modified to read TC list from file, or to generate random list + -------------------------------------------------------------------------- + PROCEDURE Pick_TC + (Model : IN STRING := "AM29LV640MH90R" ) + IS + BEGIN + IF TC_cnt < tc(TS_cnt) THEN + TC_cnt := TC_cnt+1; + ELSE + TC_cnt:=1; + IF TS_cnt<30 THEN + TS_cnt := TS_cnt+1; + ELSE + -- end test + IF ErrorInTest='0' THEN + REPORT "Test Ended without errors" + SEVERITY note; + ELSE + REPORT "There were errors in test" + SEVERITY note; + END IF; + WAIT; + END IF; + END IF; + END PROCEDURE Pick_TC; + + --------------------------------------------------------------------------- + --bus commands, device specific implementation + --------------------------------------------------------------------------- + TYPE bus_type IS (bus_idle, + bus_standby, --CE# deasseretd, others are don't care + bus_enable, --CE# asserted, others deasserted + bus_output_disable, + bus_reset, + bus_write, + bus_read); + + --bus drive for specific command sequence cycle + PROCEDURE bus_cycle( + bus_cmd :IN bus_type := bus_idle; + byte :IN boolean ; + data :IN INTEGER RANGE -2 TO MaxData := -2; -- -1 for all Z + dataHi :IN INTEGER RANGE -2 TO MaxData := -2; -- -2 for ignore + sector :IN INTEGER RANGE -1 TO SecNum := -1; -- -1 for ignore addr + address :IN NATURAL RANGE 0 TO SecSize := 0; + disable :IN boolean := false; + violate :IN boolean := false; + tm :IN TIME := 10 ns) + IS + + VARIABLE tmp : std_logic_vector(15 downto 0); + BEGIN + + IF data=-1 THEN -- HiZ + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + END IF; + + IF (NOT byte)THEN --word access + IF dataHi=-1 THEN -- HiZ + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_BYTENeg <= '1'; + ELSE --byte access + T_BYTENeg <= '0'; + T_DQ(14 downto 8) <= (OTHERS => 'Z'); + END IF; + + IF sector > -1 THEN + T_A(HiAddrBit downto 15) <= to_slv(sector, HiAddrbit-14); + tmp := to_slv(address, 16); + IF byte THEN + T_A(14 downto 0) <= tmp(15 downto 1); + T_DQ(15) <= tmp(0); + ELSE + T_A(14 downto 0) <= tmp(14 downto 0); + END IF; + + END IF; + + wait for 1 ns; + + CASE bus_cmd IS + WHEN bus_output_disable => + T_OENeg <= '1'; + WAIT FOR 20 ns; + + WHEN bus_idle => + T_RESETNeg <= '1'; + T_WENeg <= '1'; + T_CENeg <= '1'; + T_OENeg <= '1'; + IF disable THEN + T_WPNeg <= '0'; + ELSE + T_WPNeg <= '1'; + END IF; + WAIT FOR 30 ns; + + WHEN bus_standby => + T_CENeg <= '1'; + WAIT FOR 30 ns; + + WHEN bus_reset => + T_RESETNeg <= '0', '1' AFTER tm ; + -- WAIT FOR 500 ns should follow this bus cmd for reset to + --complete + WAIT FOR 30 ns; + + WHEN bus_enable => + T_WENeg <= '1' AFTER 50 ns; --- + T_CENeg <= '0' AFTER 50 ns; --- + T_OENeg <= '1' AFTER 30 ns; --- + + WAIT FOR tm ; + + WHEN bus_write => + T_OENeg <= '1' ;-- AFTER 5 ns; + T_CENeg <= '0' AFTER 10 ns ; + T_WENeg <= '0' AFTER 20 ns; + + IF data>-1 THEN + T_DQ(7 downto 0) <= to_slv(data,8); + END IF; + IF NOT byte THEN + IF dataHi>-1 THEN + T_DQ(15 downto 8) <= to_slv(dataHi,8); + END IF; + END IF; + + IF violate THEN + T_WENeg <= '1'; + WAIT FOR 50 ns; + T_WENeg <= '0', '1' AFTER tm; + WAIT FOR 50 ns; + ELSE + WAIT FOR 100 ns; + END IF; + + WHEN bus_read => + + T_CENeg <= '0' ; + T_WENeg <= '1'AFTER 10 ns; + IF NOT disable THEN + T_OENeg <= '0' AFTER 15 ns; + ELSE + T_OENeg <= '1'; + END IF; + + IF NOT byte THEN + T_DQ(15 downto 8) <= (OTHERS => 'Z'); + END IF; + T_DQ(7 downto 0) <= (OTHERS => 'Z'); + + WAIT FOR 100 ns; + + -- T_OENeg <= '1' ; ----------- + + END CASE; + + + END PROCEDURE; + + + --------------------------------------------------------------------------- + --procedure to decode commands into specific bus command sequence + --------------------------------------------------------------------------- + PROCEDURE cmd_dc + ( command : IN cmd_rec ) + IS + VARIABLE D_hi : NATURAL ;--RANGE 0 to MaxData; + VARIABLE D_lo : NATURAL RANGE 0 to MaxData; + VARIABLE Addr : NATURAL RANGE 0 to SecSize :=0; + VARIABLE Addrfix : NATURAL RANGE 0 to SecSize/2:=0; + VARIABLE Sect : INTEGER RANGE -1 to SecNum :=0; + VARIABLE slv_1, slv_2 : std_logic_vector(7 downto 0); + VARIABLE byte : boolean; + VARIABLE i : NATURAL; + BEGIN + CASE command.cmd IS + WHEN idle => + bus_cycle(bus_cmd => bus_idle, + byte => command.byte, + disable => command.aux=disable); + + WHEN h_reset => + bus_cycle(bus_cmd => bus_reset, + byte => command.byte, + tm => command.wtime); + + WHEN rd => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => command.sect, + address => command.addr, + tm => 90 ns); + + bus_cycle(bus_cmd => bus_read, + byte => command.byte, + data => -1, + dataHi => -1, + sector => command.sect, + address => command.addr, + disable => command.aux=disable); + + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + WHEN rd_page => + bus_cycle(bus_cmd => bus_enable, + byte => command.byte, + data => -1, + sector => 0, + address => 0, + tm => 90 ns); + + Addr := command.addr; + Sect := command.sect; + byte := command.byte; + ---- 08July---- + WAIT FOR 10 ns; + -------------- + i := 0; + WHILE i < command.d_hi LOOP + + IF command.wtime > 0 ns THEN + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + --byte toggle mode + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := false; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + Addrfix := Addr /2; + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + --word read; + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addrfix); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 10 ns); + byte := true; + bus_cycle(bus_cmd => bus_enable, + byte => byte, + data => -1, + sector => -1, + tm => 30 ns); + + --first byte read + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_output_disable, ---- + byte => byte); ---- + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +3; + wait for 10 ns; ------- + ELSE + byte := command.byte; + END IF; + --second byte read in byte toggle mode + bus_cycle(bus_cmd => bus_read, + byte => byte, + data => -1, + dataHi => -1, + sector => Sect, + address => Addr); + + + IF Addr < SecSize THEN + Addr := Addr+1; + ELSE + Addr := 0; + IF Sect < SecNum THEN + Sect := Sect+1; + ELSE + REPORT "No more locations to read !!!" + SEVERITY warning; + END IF; + END IF; + i := i +1; + WAIT FOR 10 ns; + END LOOP; + bus_cycle(bus_cmd => bus_output_disable, + byte => command.byte); + + + + WHEN w_cycle => + + D_lo := 16#AA# ; --first command data + Addr := 16#AAA#; --first command byte address + D_hi := 16#55#; --second command data + Addrfix := 16#555#; --second command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + Addrfix := 16#2AA#; --second command byte address + END IF; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => 0, + sector => 0, + address => Addr, + violate => command.aux=violate, + tm => command.wtime); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_hi, + dataHi => 0, + sector => 0, + address => Addrfix); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_reset | w_prog | w_erase | w_unlock | + w_autoselect | w_enter_sec => + Addr := 16#AAA#; + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + + CASE command.cmd IS + WHEN w_reset => + d_lo := 16#F0#; + WHEN w_prog => + d_lo := 16#A0#; + WHEN w_erase => + d_lo := 16#80#; + WHEN w_unlock => + d_lo := 16#20#; + WHEN w_autoselect => + d_lo := 16#90#; + WHEN w_enter_sec => + d_lo := 16#88#; + WHEN OTHERS => + d_lo := 0; + END CASE; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => d_lo, + dataHi => 0, + sector => 0, + address => Addr); + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_unlock_reset => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#90#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#F0#, + dataHi => 0, + sector => 0, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_chip_ers => + Addr := 16#AAA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#555#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#10#, + dataHi => 0, + sector => 0, + Address => Addr); + FOR i IN 0 TO SecNum LOOP + IF Sec_Prot(i)/='1' THEN + mem(i) := (OTHERS=>16#FF#); + END IF; + END LOOP; + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_cfi => + Addr := 16#AA#; --first command byte address + IF NOT command.byte THEN + --if word addressing + Addr := 16#55#; --first command byte address + END IF; + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#98#, + dataHi => 0, + sector => 0, + Address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + + WHEN w_suspend => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#B0#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + WHEN w_resume => + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => 16#30#, + dataHi => 0, + sector => -1); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + WHEN w_data => + + D_hi := command.d_hi MOD 16#100#; + D_lo := command.d_lo ; + Addr := command.addr; + Sect := command.sect; + + bus_cycle(bus_cmd => bus_write, + byte => command.byte, + data => D_lo, + dataHi => D_hi, + sector => Sect, + address => Addr); + + bus_cycle(bus_cmd => bus_standby, + byte => command.byte); + + + IF NOT command.byte THEN + Addr := Addr*2; + END IF; + + --write value(s) in default mem + IF status = erase_active AND Sec_Prot(Sect)/='1'THEN + --sector should be erased + mem(Sect) := (OTHERS=>16#FF#); + + ELSIF status = erase_na AND Sec_Prot(Sect)/='1'THEN + --sector erase terminated = data integrity violated + mem(Sect) := (OTHERS=>-1); + + ELSIF status = readX AND Sec_Prot(Sect)/='1' THEN + mem(Sect)(Addr) := -1; + IF NOT command.byte THEN + mem(Sect)(Addr+1) := -1; + END IF; + + -- Write to Secure Silicon Sector Region + ELSIF status = rd_SecSi AND FactoryProt/='1' THEN + slv_1 := to_slv(d_lo,8); + IF SecSi(Addr)>-1 THEN + slv_2 := to_slv(SecSi(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF SecSi(Addr+1)>-1 THEN + slv_2 := to_slv(SecSi(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + SecSi(Addr+1) := to_nat(slv_1); + END IF; + + ELSIF status=buff_wr_busy THEN + --Write to Buffer command cycle + null; + + ELSIF status=erase_na THEN + --sector erase command sequence violation + null; + + -- Write to Flash Memory Array + ELSIF status /= err AND Sec_Prot(Sect)/='1'THEN + slv_1 := to_slv(d_lo,8); + IF mem(Sect)(Addr)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr) := to_nat(slv_1); + IF NOT command.byte THEN + slv_1 := to_slv(d_hi,8); + IF mem(Sect)(Addr+1)>-1 THEN + slv_2 := to_slv(mem(Sect)(Addr+1),8); + ELSE + slv_2 := (OTHERS=>'X'); + END IF; + FOR i IN 0 to 7 LOOP + IF slv_2(i)='0' THEN + slv_1(i):='0'; + END IF; + END LOOP; + mem(Sect)(Addr+1) := to_nat(slv_1); + END IF; + END IF; + + + WHEN wt => + WAIT FOR command.wtime; + + WHEN wt_rdy => + IF T_RY/='1' THEN + WAIT UNTIL rising_edge(T_RY) FOR command.wtime; + END IF; + + WHEN wt_bsy => + IF T_RY='1' THEN + WAIT UNTIL falling_edge(T_RY) FOR command.wtime; + END IF; + + WHEN OTHERS => null; + END CASE; + END PROCEDURE; + + + VARIABLE cmd_cnt : NATURAL; + VARIABLE command : cmd_rec; -- + +BEGIN + Pick_TC (Model => "AM29LV640MH90R" ); + + Tseries <= ts_cnt ; + Tcase <= tc_cnt ; + + Generate_TC + (Model => "AM29LV640MH90R" , + Series => ts_cnt, + TestCase => tc_cnt, + command_seq => cmd_seq); + + + cmd_cnt := 1; + WHILE cmd_seq(cmd_cnt).cmd/=done LOOP + command:= cmd_seq(cmd_cnt); + IF command.sect = -1 THEN + command.sect := ProtSecNum; + END IF; + status <= command.status; + sts_check<= to_slv(command.d_lo,8); --used only for toggle/status check + cmd_dc(command); + cmd_cnt :=cmd_cnt +1; + + END LOOP; + +END PROCESS tb; + +--process to monitor WP# +PROCESS(T_WPNeg) +VARIABLE reg : std_logic; +BEGIN + IF falling_edge(T_WPNeg) THEN + reg := Sec_Prot(ProtSecNum); + Sec_Prot(ProtSecNum) := '1'; + ELSIF rising_edge(T_WPNeg) THEN + Sec_Prot(ProtSecNum) := reg; + END IF; +END PROCESS; + +-------------------------------------------------------------------------------- +-- Checker process, +-- Bus transition extractor: when bus cycle is read samples addr and data +-- Transition checker : verifies correct read data using default memory +-------------------------------------------------------------------------------- +checker: PROCESS + VARIABLE RAddr : NATURAL; + VARIABLE RSect : NATURAL; + VARIABLE longread : boolean; + VARIABLE shortread : boolean; + VARIABLE toggle : boolean:=false; + VARIABLE toggle_sts : std_logic_vector(7 downto 0); + +BEGIN +-- Transition extractor + IF (T_CENeg='0'AND T_OENeg='0'AND T_WENeg='1') THEN + IF T_BYTENeg='1' THEN + RAddr := to_nat(T_A(14 downto 0)&'0'); + ELSE + RAddr := to_nat(T_A(14 downto 0)&T_DQ(15)); + END IF; + RSect := to_nat(T_A(HiAddrBit downto 15)); + + shortread:= false; + longread := false; + + --DUT specific timing + IF (T_CENeg'EVENT OR T_WENeg'EVENT OR T_A(HiAddrBit downto 2)'EVENT)AND -- + (status=read OR status=rd_cfi OR status=rd_secsi) THEN --OR status=readX) + longread := true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 95 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 105 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 115 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 125 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 125 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + ELSIF T_A(1 downto 0)'EVENT OR + (T_DQ(15)'EVENT AND T_BYTENeg='0')OR + (T_BYTENeg'EVENT) OR + T_OENeg'EVENT OR + (status/=read AND status/=rd_cfi AND + status/=rd_secsi) THEN --AND status/=readX) + shortread:=true; + CASE TimingModel IS + WHEN "AM29LV640MH90R" | + "AM29LV640ML90R" => WAIT FOR 30 ns; +-- WHEN "AM29LV640MH101" | +-- "AM29LV640ML101" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH101R" | +-- "AM29LV640ML101R" => WAIT FOR 40 ns; +-- WHEN "AM29LV640MH112" | +-- "AM29LV640ML112" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH112R" | +-- "AM29LV640ML112R" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120" | +-- "AM29LV640ML120" => WAIT FOR 45 ns; +-- WHEN "AM29LV640MH120R" | +-- "AM29LV640ML120R" => WAIT FOR 45 ns; + WHEN OTHERS => + REPORT "Timing model NOT supported : "&TimingModel + SEVERITY error; + END CASE; + + END IF; + + + + --Checker + IF longread OR shortread THEN + + CASE status IS + WHEN none => + toggle := false; + + -- read memory array data + WHEN read => + toggle := false; + Check_read ( + DQ => T_DQ, + D_lo => mem(RSect)(RAddr), + D_hi => mem(RSect)(RAddr+1), + Byte => T_BYTENeg, + check_err=> check_err); + + -- read secure silicon region + WHEN rd_secsi => + toggle := false; + Check_SecSi ( + DQ => T_DQ, + D_lo => SecSi(RAddr), + D_hi => SecSi(RAddr+1), + Byte => T_BYTENeg, + check_err=>check_err); + + + --read CFI query codes + WHEN rd_cfi => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_CFI ( + DQ => T_DQ, + D_lo => CFI_array(RAddr) , + D_hi => 0 , + Byte => T_BYTENeg, + check_err=>check_err); + + + + -- read Autoselect codes + WHEN rd_AS => + RAddr := to_nat(T_A(14 downto 0)); --x16 addressing + toggle := false; + Check_AS ( + DQ => T_DQ, + addr => RAddr, + ProtSecNum=>ProtSecNum, + secProt => Sec_Prot(RSect), + FactoryProt=>FactoryProt , + Byte => T_BYTENeg, + AS_E => to_slv(16#0C#,8), + AS_F => to_slv(1,8), + + check_err=>check_err); + + + WHEN rd_HiZ => + toggle:=false; + Check_Z ( + DQ => T_DQ, + check_err=>check_err); + + + + WHEN readX => + toggle:=false; + Check_X ( + DQ => T_DQ, + check_err=>check_err); + + + WHEN erase_na | erase_active => + IF toggle THEN + Check_Erase ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN ers_susp_e => + IF toggle THEN + Check_Ers_Susp ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN ers_susp_prog_na | ers_susp_prog => + IF toggle THEN + Check_Ers_Susp_Prog ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + +-- + + WHEN prog_na | prog_active => + IF toggle THEN + Check_Progr ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_wr_busy | buff_wr_N_busy => + IF toggle THEN + Check_Buff_Busy ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + + WHEN buff_abort => + IF toggle THEN + Check_Abort ( + DQ => T_DQ(7 downto 0), + sts => status, + toggle => toggle_sts, + sts_check=>sts_check, + RY => T_RY, + check_err=>check_err); + + toggle_sts := T_DQ(7 downto 0); --update toggle check + END IF; + WHEN OTHERS => null; + END CASE; + + -- get firs data for toggle check + CASE status IS + WHEN prog_active | prog_na | + erase_active | erase_na | + ers_susp_e | + ers_susp_prog | ers_susp_prog_na | + buff_wr_busy | buff_wr_N_busy | + buff_abort | get_toggle => + + IF (NOT toggle) OR (status=get_toggle) THEN + toggle:=true; + toggle_sts := T_DQ(7 downto 0); + END IF; + + WHEN OTHERS => null; + END CASE; + + + END IF; + + END IF; + + WAIT ON T_A, T_CENeg, T_OENeg, T_WENeg, T_DQ(15), T_BYTENeg; + +END PROCESS checker; + + +default: PROCESS + -- text file input variables + FILE mem_f : text is mem_file; + FILE prot_f : text is prot_file; + FILE secsi_f : text is secsi_file; + + VARIABLE S_ind : NATURAL RANGE 0 TO SecNum:= 0; + VARIABLE ind : NATURAL RANGE 0 TO SecSize:= 0; + VARIABLE buf : line; + +BEGIN + --Preload Control + ----------------------------------------------------------------------- + -- File Read Section + ----------------------------------------------------------------------- + IF UserPreload THEN + --- Sector protection preload + IF (prot_file /= "none" ) THEN + ind := 0; + FactoryProt := '0'; + Sec_Prot := (OTHERS => '0'); + WHILE (not ENDFILE (prot_f)) LOOP + READLINE (prot_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind > SecNum THEN + --SecSi Factory protect preload + IF buf(1)='1' THEN + FactoryProt := '1'; + END IF; + ELSE + -- Standard Sector prload + IF buf(1)='1' THEN + Sec_Prot(ind):= '1'; + END IF; + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + -- Secure Silicon Sector Region preload + IF (SecSi_file /= "none" ) THEN + SecSi := (OTHERS => MaxData); + ind := 0; + WHILE (not ENDFILE (SecSi_f)) LOOP + READLINE (SecSi_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 3)); --address + ELSE + IF ind <= SecSiSize THEN + SecSi(ind) := h(buf(1 TO 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + END IF; + + --- Memory Preload + IF (mem_file /= "none" ) THEN + ind := 0; + Mem := (OTHERS => (OTHERS => MaxData)); + -- load sector 0 + WHILE (not ENDFILE (mem_f)) LOOP + READLINE (mem_f, buf); + IF buf(1) = '/' THEN + NEXT; + ELSIF buf(1) = '@' THEN + ind := h(buf(2 to 5)); --address + ELSE + IF ind <= SecSize THEN + Mem(0)(ind) := h(buf(1 to 2)); + ind := ind + 1; + END IF; + END IF; + END LOOP; + -- load other sectors + FOR i IN 1 TO SecNum LOOP + Mem(i) := Mem(0); + END LOOP; + END IF; + + END IF; + ----------------------------------------------------------------------- + --CFI array data / AM29LV640MH90R !!! DEVICE SPECIFIC + ----------------------------------------------------------------------- + --CFI query identification string + -- !!!!!! WORD ADDRESSES (x16) - for x8 addressing double addr + --CFI query identification string + CFI_array(16#10#) := 16#51#; + CFI_array(16#11#) := 16#52#; + CFI_array(16#12#) := 16#59#; + CFI_array(16#13#) := 16#02#; + CFI_array(16#14#) := 16#00#; + CFI_array(16#15#) := 16#40#; + CFI_array(16#16#) := 16#00#; + CFI_array(16#17#) := 16#00#; + CFI_array(16#18#) := 16#00#; + CFI_array(16#19#) := 16#00#; + CFI_array(16#1A#) := 16#00#; + --system interface string + CFI_array(16#1B#) := 16#27#; + CFI_array(16#1C#) := 16#36#; + CFI_array(16#1D#) := 16#00#; + CFI_array(16#1E#) := 16#00#; + CFI_array(16#1F#) := 16#07#; + CFI_array(16#20#) := 16#07#; + CFI_array(16#21#) := 16#0A#; + CFI_array(16#22#) := 16#00#; + CFI_array(16#23#) := 16#01#; + CFI_array(16#24#) := 16#05#; + CFI_array(16#25#) := 16#04#; + CFI_array(16#26#) := 16#00#; + --device geometry definition + CFI_array(16#27#) := 16#17#; + CFI_array(16#28#) := 16#02#; + CFI_array(16#29#) := 16#00#; + CFI_array(16#2A#) := 16#05#; + CFI_array(16#2B#) := 16#00#; + CFI_array(16#2C#) := 16#01#; + CFI_array(16#2D#) := 16#7F#; + CFI_array(16#2E#) := 16#00#; + CFI_array(16#2F#) := 16#00#; + CFI_array(16#30#) := 16#01#; + CFI_array(16#31#) := 16#00#; + CFI_array(16#32#) := 16#00#; + CFI_array(16#33#) := 16#00#; + CFI_array(16#34#) := 16#00#; + CFI_array(16#35#) := 16#00#; + CFI_array(16#36#) := 16#00#; + CFI_array(16#37#) := 16#00#; + CFI_array(16#38#) := 16#00#; + CFI_array(16#39#) := 16#00#; + CFI_array(16#3A#) := 16#00#; + CFI_array(16#3B#) := 16#00#; + CFI_array(16#3C#) := 16#00#; + --primary vendor-specific extended query + CFI_array(16#40#) := 16#50#; + CFI_array(16#41#) := 16#52#; + CFI_array(16#42#) := 16#49#; + CFI_array(16#43#) := 16#31#; + CFI_array(16#44#) := 16#33#; + CFI_array(16#45#) := 16#08#; + CFI_array(16#46#) := 16#02#; + CFI_array(16#47#) := 16#01#; + CFI_array(16#48#) := 16#01#; + CFI_array(16#49#) := 16#04#; + CFI_array(16#4A#) := 16#00#; + CFI_array(16#4B#) := 16#00#; + CFI_array(16#4C#) := 16#01#; + CFI_array(16#4D#) := 16#B5#; + CFI_array(16#4E#) := 16#C5#; + IF TimingModel(11) = 'L' THEN + CFI_array(16#4F#) := 16#04#; + ELSE + CFI_array(16#4F#) := 16#05#; --uniform sectors top protect + END IF; + CFI_array(16#50#) := 16#01#; + + WAIT; + +END PROCESS default; + + + +END vhdl_behavioral; + diff --git a/lib/models/memory/flash/serial/S25fl032p/utilities/conversions.vhd b/lib/models/memory/flash/serial/S25fl032p/utilities/conversions.vhd new file mode 100644 index 0000000..e5fc0d6 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/utilities/conversions.vhd @@ -0,0 +1,1035 @@ +-------------------------------------------------------------------------------- +-- File Name: conversions_p.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1997, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- This package was written by SEVA Technologies, Inc. and donated to the FMF. +-- www.seva.com +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 97 DEC 05 Added header and formatting to SEVA file +-- V1.1 R. Munden 98 NOV 28 Corrected some comments +-- Corrected function b +-- V1.2 R. Munden 01 MAY 27 Corrected function to_nat for weak values +-- and combined into a single file +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; + +-------------------------------------------------------------------------------- +-- CONVERSION FUNCTION SELECTION TABLES +-------------------------------------------------------------------------------- +-- +-- FROM TO: std_logic_vector std_logic natural time string +-- -----------------|---------------|---------|---------|---------|----------- +-- std_logic_vector | N/A | N/A | to_nat | combine | see below +-- std_logic | N/A | N/A | to_nat | combine | see below +-- natural | to_slv | to_sl | N/A | to_time | see below +-- time | N/A | N/A | to_nat | N/A | to_time_str +-- hex string | h | N/A | h | combine | N/A +-- decimal string | d | N/A | d | combine | N/A +-- octal string | o | N/A | o | combine | N/A +-- binary string | b | N/A | b | combine | N/A +-- -----------------|---------------|---------|---------|---------|----------- +-- +-- FROM TO: hex string decimal string octal string binary string +-- -----------------|------------|-------------|------------|---------------- +-- std_logic_vector | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- std_logic | N/A | N/A | N/A | to_bin_str +-- natural | to_hex_str | to_int_str | to_oct_str | to_bin_str +-- -----------------|------------|-------------|------------|---------------- +-- +-------------------------------------------------------------------------------- + +PACKAGE conversions IS + + ---------------------------------------------------------------------------- + -- the conversions in this package are not guaranteed to be synthesizable. + -- + -- others functions available + -- fill creates a variable length string of the fill character + -- + -- + -- + -- input parameters of type natural or integer can be in the form: + -- normal -> 8, 99, 4_237 + -- base#value# -> 2#0101#, 16#fa4C#, 8#6_734# + -- with exponents(x10) -> 8e4, 16#2e#E4 + -- + -- input parameters of type string can be in the form: + -- "99", "4_237", "0101", "1010_1010" + -- + -- for bit/bit_vector <-> std_logic/std_logic_vector conversions use + -- package std_logic_1164 + -- to_bit(std_logic) + -- to_bitvector(std_logic_vector) + -- to_stdlogic(bit) + -- to_stdlogicvector(bit_vector) + -- + -- for "synthesizable" signed/unsigned/std_logic_vector/integer + -- conversions use + -- package std_logic_arith + -- conv_integer(signed/unsigned) + -- conv_unsigned(integer/signed,size) + -- conv_signed(integer/unsigned,size) + -- conv_std_logic_vector(integer/signed/unsigned,size) + -- + -- for "synthesizable" std_logic_vector -> integer conversions use + -- package std_logic_unsigned/std_logic_signed + -- + -- conv_integer(std_logic_vector) + -- + -- type1'(expression of type2) + -- + -- most conversions have 4 parmeters: + -- x : value to be converted + -- rtn_len : size of the return value + -- justify : justify value 'left' or 'right', default is right + -- basespec : print the base of the value - 'yes'/'no', default is yes + -- + -- Typical ways to call these functions: + -- simple, all defaults used + -- to_bin_str(x) + -- x will be converted to a string of minimum size with a + -- base specification appended for clarity + -- if x is 10101 then return is b"10101" + -- + -- to control size of return string + -- to_hex_str(x, + -- 6) + -- length of string returned will be 6 characters + -- value will be right justified in the field + -- if x is 10101 then return is ....h"15" + -- where '.' represents a blank + -- if 'rtn_len' parm defaults or is set to 0 then + -- return string will always be minimum size + -- + -- to left justify and suppress base specification + -- to_int_str(x, + -- 6, + -- justify => left, + -- basespec => yes) + -- length of return string will be 6 characters + -- the base specification will be suppressed + -- if x is 10101 then return is 21.... + -- where '.' represents a blank + -- + -- other usage notes + -- + -- if rtn_len less than or equal to x'length then ignore + -- rtn_len and return string of x'length + -- the 'justify' parm is effectively ignored in this case + -- + -- if rtn_len greater than x'length then return string + -- of rtn_len with blanks based on 'justify' parm + -- + -- these routines do not handle negative numbers + ---------------------------------------------------------------------------- + + type justify_side is (left, right); + type b_spec is (no , yes); + + -- std_logic_vector to binary string + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- std_logic to binary string + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to binary string + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to hex string + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to hex string + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to octal string + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- natural to octal string + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- natural to integer string + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + -- see note above regarding possible formats for x + + -- std_logic_vector to integer string + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string; + + -- time to string + function to_time_str (x : time) + return string; + + -- add characters to a string + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string; + -- usage: + -- fill + -- returns * + -- fill(' ',10) + -- returns .......... when '.' represents a blank + -- fill(lf) or fill(ht) + -- returns line feed character or tab character respectively + + -- std_logic_vector to natural + function to_nat (x : std_logic_vector) + return natural; + + -- std_logic to natural + function to_nat (x : std_logic) + return natural; + + -- time to natural + function to_nat (x : time) + return natural; + + -- hex string to std_logic_vector + function h (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F + -- or x,X,z,Z,u,U,-,w,W, result will be 0 + + -- decimal string to std_logic_vector + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- octal string to std_logic_vector + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 7 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- binary string to std_logic_vector + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- result will be 0 + + -- hex string to natural + function h (x : string) + return natural; + -- if x is other than characters 0 to 9 or a,A to f,F, result will be 0 + + -- decimal string to natural + function d (x : string) + return natural; + -- if x is other than characters 0 to 9, result will be 0 + + -- octal string to natural + function o (x : string) + return natural; + -- if x is other than characters 0 to 7, result will be 0 + + -- binary string to natural + function b (x : string) + return natural; + -- if x is other than characters 0 to 1, result will be 0 + + -- natural to std_logic_vector + function to_slv (x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector; + -- if rtn_len is < than sizeof(x), result will be truncated on the left + -- see note above regarding possible formats for x + + -- natural to std_logic + function to_sl (x : natural) + return std_logic; + + -- natural to time + function to_time (x : natural) + return time; + -- see note above regarding possible formats for x + +END conversions; +-- +-------------------------------------------------------------------------------- +-- + +PACKAGE BODY conversions IS + + -- private declarations for this package + type basetype is (binary, octal, decimal, hex); + + function max(x,y: integer) return integer is + begin + if x > y then return x; else return y; end if; + end max; + + function min(x,y: integer) return integer is + begin + if x < y then return x; else return y; end if; + end min; + + -- consider function sizeof for string/slv/???, return natural + + -- function size(len: natural) return natural is + -- begin + -- if len=0 then + -- return 31; + -- else return len; + -- end if; + -- end size; + + function nextmultof (x : positive; + size : positive) return positive is + begin + case x mod size is + when 0 => return size * x/size; + when others => return size * (x/size + 1); + end case; + end nextmultof; + + function rtn_base (base : basetype) return character is + begin + case base is + when binary => return 'b'; + when octal => return 'o'; + when decimal => return 'd'; + when hex => return 'h'; + end case; + end rtn_base; + + function format (r : string; + base : basetype; + rtn_len : natural ; + justify : justify_side; + basespec : b_spec) return string is + variable int_rtn_len : integer; + begin + if basespec=yes then + int_rtn_len := rtn_len - 3; + else + int_rtn_len := rtn_len; + end if; + if int_rtn_len <= r'length then + case basespec is + when no => return r ; + when yes => return rtn_base(base) & '"' & r & '"'; + end case; + else + case justify is + when left => + case basespec is + when no => + return r & fill(' ',int_rtn_len - r'length); + when yes => + return rtn_base(base) & '"' & r & '"' & + fill(' ',int_rtn_len - r'length); + end case; + when right => + case basespec is + when no => + return fill(' ',int_rtn_len - r'length) & r ; + when yes => + return fill(' ',int_rtn_len - r'length) & + rtn_base(base) & '"' & r & '"'; + end case; + end case; + end if; + end format; + + -- convert numeric string of any base to natural + function cnvt_base (x : string; + inbase : natural range 2 to 16) return natural is + -- assumes x is an unsigned number string of base 'inbase' + -- values larger than natural'high are not supported + variable r,t : natural := 0; + variable place : positive := 1; + begin + for i in x'reverse_range loop + case x(i) is + when '0' => t := 0; + when '1' => t := 1; + when '2' => t := 2; + when '3' => t := 3; + when '4' => t := 4; + when '5' => t := 5; + when '6' => t := 6; + when '7' => t := 7; + when '8' => t := 8; + when '9' => t := 9; + when 'a'|'A' => t := 10; + when 'b'|'B' => t := 11; + when 'c'|'C' => t := 12; + when 'd'|'D' => t := 13; + when 'e'|'E' => t := 14; + when 'f'|'F' => t := 15; + when '_' => t := 0; -- ignore these characters + place := place / inbase; + when others => + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + if t / inbase > 1 then -- invalid value for base + assert false + report lf & + "CNVT_BASE found input value larger than base: " & lf & + "Input value: " & x(i) & + " Base: " & to_int_str(inbase) & lf & + "converting input to integer 0" + severity warning; + return 0; + else + r := r + (t * place); + place := place * inbase; + end if; + end loop; + return r; + end cnvt_base; + + function extend (x : std_logic; + len : positive) return std_logic_vector is + variable v : std_logic_vector(1 to len) := (others => x); + begin + return v; + end extend; + + + -- implementation of public declarations + + function to_bin_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + + variable int : std_logic_vector(1 to x'length):=x; + variable r : string(1 to x'length):=(others=>'$'); + begin + for i in int'range loop + r(i to i) := to_bin_str(int(i),basespec=>no); + end loop; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : std_logic; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable r : string(1 to 1); + begin + case x is + when '0' => r(1) := '0'; + when '1' => r(1) := '1'; + when 'U' => r(1) := 'U'; + when 'X' => r(1) := 'X'; + when 'Z' => r(1) := 'Z'; + when 'W' => r(1) := 'W'; + when 'H' => r(1) := 'H'; + when 'L' => r(1) := 'L'; + when '-' => r(1) := '-'; + end case; + return format (r,binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_bin_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 2 to 32 := 32; + variable r : string(2 to 32):=(others=>'$'); + begin + if int = 0 then + return format ("0",binary,rtn_len,justify,basespec); + end if; + + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_BIN_STR, shouldn't happen" + severity failure; + return "$"; + null; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),binary,rtn_len,justify,basespec); + end to_bin_str; + + function to_hex_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/4 + variable nxt : positive := nextmultof(x'length,4); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/4)+1 := 1; + variable r : string(1 to nxt/4):=(others=>'$'); + subtype slv4 is std_logic_vector(1 to 4); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 4 /= 1; + case slv4'(int(i to i+3)) is + when "0000" => r(ptr) := '0'; + when "0001" => r(ptr) := '1'; + when "0010" => r(ptr) := '2'; + when "0011" => r(ptr) := '3'; + when "0100" => r(ptr) := '4'; + when "0101" => r(ptr) := '5'; + when "0110" => r(ptr) := '6'; + when "0111" => r(ptr) := '7'; + when "1000" => r(ptr) := '8'; + when "1001" => r(ptr) := '9'; + when "1010" => r(ptr) := 'A'; + when "1011" => r(ptr) := 'B'; + when "1100" => r(ptr) := 'C'; + when "1101" => r(ptr) := 'D'; + when "1110" => r(ptr) := 'E'; + when "1111" => r(ptr) := 'F'; + when "ZZZZ" => r(ptr) := 'Z'; + when "WWWW" => r(ptr) := 'W'; + when "LLLL" => r(ptr) := 'L'; + when "HHHH" => r(ptr) := 'H'; + when "UUUU" => r(ptr) := 'U'; + when "XXXX" => r(ptr) := 'X'; + when "----" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_HEX_STR found illegal value: " & + to_bin_str(int(i to i+3)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_hex_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 16 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when 10 => r(ptr) := 'A'; + when 11 => r(ptr) := 'B'; + when 12 => r(ptr) := 'C'; + when 13 => r(ptr) := 'D'; + when 14 => r(ptr) := 'E'; + when 15 => r(ptr) := 'F'; + when others => + assert false report lf & "TO_HEX_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 16; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),hex,rtn_len,justify,basespec); + end to_hex_str; + + function to_oct_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + -- will return x'length/3 + variable nxt : positive := nextmultof(x'length,3); + variable int : std_logic_vector(1 to nxt):= (others => '0'); + variable ptr : positive range 1 to (nxt/3)+1 := 1; + variable r : string(1 to nxt/3):=(others=>'$'); + subtype slv3 is std_logic_vector(1 to 3); + begin + int(nxt-x'length+1 to nxt) := x; + if nxt-x'length > 0 and x(x'left) /= '1' then + int(1 to nxt-x'length) := extend(x(x'left),nxt-x'length); + end if; + for i in int'range loop + next when i rem 3 /= 1; + case slv3'(int(i to i+2)) is + when "000" => r(ptr) := '0'; + when "001" => r(ptr) := '1'; + when "010" => r(ptr) := '2'; + when "011" => r(ptr) := '3'; + when "100" => r(ptr) := '4'; + when "101" => r(ptr) := '5'; + when "110" => r(ptr) := '6'; + when "111" => r(ptr) := '7'; + when "ZZZ" => r(ptr) := 'Z'; + when "WWW" => r(ptr) := 'W'; + when "LLL" => r(ptr) := 'L'; + when "HHH" => r(ptr) := 'H'; + when "UUU" => r(ptr) := 'U'; + when "XXX" => r(ptr) := 'X'; + when "---" => r(ptr) := '-'; + when others => + assert false + report lf & + "TO_OCT_STR found illegal value: " & + to_bin_str(int(i to i+2)) & lf & + "converting input to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr + 1; + end loop; + return format (r,octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_oct_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 20 := 20; + variable r : string(1 to 20):=(others=>'$'); + begin + if x=0 then return format ("0",octal,rtn_len,justify,basespec); end if; + while int > 0 loop + case int rem 8 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when others => + assert false report lf & "TO_OCT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 8; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 20),octal,rtn_len,justify,basespec); + end to_oct_str; + + function to_int_str(x : natural; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) return string is + variable int : natural := x; + variable ptr : positive range 1 to 32 := 32; + variable r : string(1 to 32):=(others=>'$'); + begin + if x=0 then return format ("0",hex,rtn_len,justify,basespec); + else + while int > 0 loop + case int rem 10 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when 2 => r(ptr) := '2'; + when 3 => r(ptr) := '3'; + when 4 => r(ptr) := '4'; + when 5 => r(ptr) := '5'; + when 6 => r(ptr) := '6'; + when 7 => r(ptr) := '7'; + when 8 => r(ptr) := '8'; + when 9 => r(ptr) := '9'; + when others => + assert false report lf & "TO_INT_STR, shouldn't happen" + severity failure; + return "$"; + end case; + int := int / 10; + ptr := ptr - 1; + end loop; + return format (r(ptr+1 to 32),decimal,rtn_len,justify,basespec); + end if; + end to_int_str; + + function to_int_str(x : std_logic_vector; + rtn_len : natural := 0; + justify : justify_side := right; + basespec : b_spec := yes) + return string is + begin + return to_int_str(to_nat(x),rtn_len,justify,basespec); + end to_int_str; + + + function to_time_str (x : time) + return string is + begin + return to_int_str(to_nat(x),basespec=>no) & " ns"; + end to_time_str; + + function fill (fill_char : character := '*'; + rtn_len : integer := 1) + return string is + variable r : string(1 to max(rtn_len,1)) := (others => fill_char); + variable len : integer; + begin + if rtn_len < 2 then -- always returns at least 1 fill char + len := 1; + else + len := rtn_len; + end if; + return r(1 to len); + end fill; + + function to_nat(x : std_logic_vector) return natural is + -- assumes x is an unsigned number, lsb on right, + -- more than 31 bits are truncated on left + variable t : std_logic_vector(1 to x'length) := x; + variable int : std_logic_vector(1 to 31) := (others => '0'); + variable r : natural := 0; + variable place : positive := 1; + begin + if x'length < 32 then + int(max(32-x'length,1) to 31) := t(1 to x'length); + else -- x'length >= 32 + int(1 to 31) := t(x'length-30 to x'length); + end if; + for i in int'reverse_range loop + case int(i) is + when '1' | 'H' => r := r + place; + when '0' | 'L' => null; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(int(i)) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + exit when i=1; + place := place * 2; + end loop; + return r; + end to_nat; + + function to_nat (x : std_logic) + return natural is + begin + case x is + when '0' => return 0 ; + when '1' => return 1 ; + when others => + assert false + report lf & + "TO_NAT found illegal value: " & to_bin_str(x) & lf & + "converting input to integer 0" + severity warning; + return 0; + end case; + end to_nat; + + function to_nat (x : time) + return natural is + begin + return x / 1 ns; + end to_nat; + + function h(x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*4, result will be truncated on the left + -- if x is other than characters 0 to 9 or a,A to f,F or + -- x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*4,rtn_len); + variable ptr : integer range -3 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-3 to ptr) := "0000"; + when '1' => r(ptr-3 to ptr) := "0001"; + when '2' => r(ptr-3 to ptr) := "0010"; + when '3' => r(ptr-3 to ptr) := "0011"; + when '4' => r(ptr-3 to ptr) := "0100"; + when '5' => r(ptr-3 to ptr) := "0101"; + when '6' => r(ptr-3 to ptr) := "0110"; + when '7' => r(ptr-3 to ptr) := "0111"; + when '8' => r(ptr-3 to ptr) := "1000"; + when '9' => r(ptr-3 to ptr) := "1001"; + when 'a'|'A' => r(ptr-3 to ptr) := "1010"; + when 'b'|'B' => r(ptr-3 to ptr) := "1011"; + when 'c'|'C' => r(ptr-3 to ptr) := "1100"; + when 'd'|'D' => r(ptr-3 to ptr) := "1101"; + when 'e'|'E' => r(ptr-3 to ptr) := "1110"; + when 'f'|'F' => r(ptr-3 to ptr) := "1111"; + when 'U' => r(ptr-3 to ptr) := "UUUU"; + when 'X' => r(ptr-3 to ptr) := "XXXX"; + when 'Z' => r(ptr-3 to ptr) := "ZZZZ"; + when 'W' => r(ptr-3 to ptr) := "WWWW"; + when 'H' => r(ptr-3 to ptr) := "HHHH"; + when 'L' => r(ptr-3 to ptr) := "LLLL"; + when '-' => r(ptr-3 to ptr) := "----"; + when '_' => ptr := ptr + 4; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '----'" + severity warning; + r(ptr-3 to ptr) := "----"; + end case; + ptr := ptr - 4; + end loop; + return r(size-rtn_len+1 to size); + end h; + + function d (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than binary length of x, result will be truncated on + -- the left + -- if x is other than characters 0 to 9, result will be 0 + begin + return to_slv(cnvt_base(x,10),rtn_len); + end d; + + function o (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length*3, result will be truncated on the left + -- if x is other than characters 0 to 7 or or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length*3,rtn_len); + variable ptr : integer range -2 to size := size; + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr-2 to ptr) := "000"; + when '1' => r(ptr-2 to ptr) := "001"; + when '2' => r(ptr-2 to ptr) := "010"; + when '3' => r(ptr-2 to ptr) := "011"; + when '4' => r(ptr-2 to ptr) := "100"; + when '5' => r(ptr-2 to ptr) := "101"; + when '6' => r(ptr-2 to ptr) := "110"; + when '7' => r(ptr-2 to ptr) := "111"; + when 'U' => r(ptr-2 to ptr) := "UUU"; + when 'X' => r(ptr-2 to ptr) := "XXX"; + when 'Z' => r(ptr-2 to ptr) := "ZZZ"; + when 'W' => r(ptr-2 to ptr) := "WWW"; + when 'H' => r(ptr-2 to ptr) := "HHH"; + when 'L' => r(ptr-2 to ptr) := "LLL"; + when '-' => r(ptr-2 to ptr) := "---"; + when '_' => ptr := ptr + 3; + when others => + assert false + report lf & + "O conversion found illegal input character: " & + int(i) & lf & "converting character to '---'" + severity warning; + r(ptr-2 to ptr) := "---"; + end case; + ptr := ptr - 3; + end loop; + return r(size-rtn_len+1 to size); + end o; + + function b (x : string; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than x'length, result will be truncated on the left + -- if x is other than characters 0 to 1 or x,X,z,Z,u,U,-,w,W, + -- those result bits will be set to 0 + variable int : string(1 to x'length) := x; + variable size: positive := max(x'length,rtn_len); + variable ptr : integer range 0 to size+1 := size; -- csa + variable r : std_logic_vector(1 to size) := (others=>'0'); + begin + for i in int'reverse_range loop + case int(i) is + when '0' => r(ptr) := '0'; + when '1' => r(ptr) := '1'; + when 'U' => r(ptr) := 'U'; + when 'X' => r(ptr) := 'X'; + when 'Z' => r(ptr) := 'Z'; + when 'W' => r(ptr) := 'W'; + when 'H' => r(ptr) := 'H'; + when 'L' => r(ptr) := 'L'; + when '-' => r(ptr) := '-'; + when '_' => ptr := ptr + 1; + when others => + assert false + report lf & + "B conversion found illegal input character: " & + int(i) & lf & "converting character to '-'" + severity warning; + r(ptr) := '-'; + end case; + ptr := ptr - 1; + end loop; + return r(size-rtn_len+1 to size); + end b; + + function h (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- a,A to f,F + -- blanks, underscore + begin + return cnvt_base(x,16); + end h; + + function d (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 9 + -- blanks, underscore + begin + return cnvt_base(x,10); + end d; + + function o (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 7 + -- blanks, underscore + begin + return cnvt_base(x,8); + end o; + + function b (x : string) + return natural is + -- only following characters are allowed, otherwise result will be 0 + -- 0 to 1 + -- blanks, underscore + begin + return cnvt_base(x,2); + end b; + + function to_slv(x : natural; + rtn_len : positive range 1 to 32 := 32) + return std_logic_vector is + -- if rtn_len is < than sizeof(x), result will be truncated on the left + variable int : natural := x; + variable ptr : positive := 32; + variable r : std_logic_vector(1 to 32) := (others=>'0'); + begin + while int > 0 loop + case int rem 2 is + when 0 => r(ptr) := '0'; + when 1 => r(ptr) := '1'; + when others => + assert false report lf & "TO_SLV, shouldn't happen" + severity failure; + return "0"; + end case; + int := int / 2; + ptr := ptr - 1; + end loop; + return r(33-rtn_len to 32); + end to_slv; + + function to_sl(x : natural) + return std_logic is + variable r : std_logic := '0'; + begin + case x is + when 0 => null; + when 1 => r := '1'; + when others => + assert false + report lf & + "TO_SL found illegal input character: " & + to_int_str(x) & lf & "converting character to '-'" + severity warning; + return '-'; + end case; + return r; + end to_sl; + + function to_time (x: natural) return time is + begin + return x * 1 ns; + end to_time; + +END conversions; diff --git a/lib/models/memory/flash/serial/S25fl032p/utilities/gen_utils.vhd b/lib/models/memory/flash/serial/S25fl032p/utilities/gen_utils.vhd new file mode 100644 index 0000000..65c0e77 --- /dev/null +++ b/lib/models/memory/flash/serial/S25fl032p/utilities/gen_utils.vhd @@ -0,0 +1,144 @@ +-------------------------------------------------------------------------------- +-- File name: gen_utils.vhd +-------------------------------------------------------------------------------- +-- Copyright (C) 1996, 1998, 2001 Free Model Foundry; http://eda.org/fmf/ +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License version 2 as +-- published by the Free Software Foundation. +-- +-- MODIFICATION HISTORY: +-- +-- version: | author: | mod date: | changes made: +-- V1.0 R. Steele 96 SEP 26 Initial release +-- V1.1 REV3 97 Feb 27 Added Xon and MsgOn generics +-- V1.2 R. Steele 97 APR 16 Changed wired-or to wired-and +-- V1.3 R. Steele 97 APR 16 Added diff. receiver table +-- V1.4 R. Munden 98 APR 13 Added GenParity and CheckParity +-- V1.5 R. Munden 01 NOV 24 Added UnitDelay01ZX +-- +-------------------------------------------------------------------------------- +LIBRARY IEEE; USE IEEE.std_Logic_1164.ALL; + USE IEEE.VITAL_primitives.ALL; + USE IEEE.VITAL_timing.ALL; + +PACKAGE gen_utils IS + + ---------------------------------------------------------------------------- + -- Result map for Wired-and output values (open collector) + ---------------------------------------------------------------------------- + CONSTANT STD_wired_and_rmap : VitalResultMapType := ('U','X','0','Z'); + + ---------------------------------------------------------------------------- + -- Table for computing a single signal from a differential receiver input + -- pair. + ---------------------------------------------------------------------------- + CONSTANT diff_rec_tab : VitalStateTableType := ( + + ------INPUTS--|-PREV-|-OUTPUT---- + -- A ANeg | Aint | Aint' -- + --------------|------|----------- + ( 'X', '-', '-', 'X'), -- A unknown + ( '-', 'X', '-', 'X'), -- A unknown + ( '1', '-', 'X', '1'), -- Recover from 'X' + ( '0', '-', 'X', '0'), -- Recover from 'X' + ( '/', '0', '0', '1'), -- valid diff. rising edge + ( '1', '\', '0', '1'), -- valid diff. rising edge + ( '\', '1', '1', '0'), -- valid diff. falling edge + ( '0', '/', '1', '0'), -- valid diff. falling edge + ( '-', '-', '-', 'S') -- default + ); -- end of VitalStateTableType definition + + + ---------------------------------------------------------------------------- + -- Default Constants + ---------------------------------------------------------------------------- + CONSTANT UnitDelay : VitalDelayType := 1 ns; + CONSTANT UnitDelay01 : VitalDelayType01 := (1 ns, 1 ns); + CONSTANT UnitDelay01Z : VitalDelayType01Z := (others => 1 ns); + CONSTANT UnitDelay01ZX : VitalDelayType01ZX := (others => 1 ns); + + CONSTANT DefaultInstancePath : STRING := "*"; + CONSTANT DefaultTimingChecks : BOOLEAN := FALSE; + CONSTANT DefaultTimingModel : STRING := "UNIT"; + CONSTANT DefaultXon : BOOLEAN := TRUE; + CONSTANT DefaultMsgOn : BOOLEAN := TRUE; + + -- Older VITAL generic being phased out + CONSTANT DefaultXGeneration : BOOLEAN := TRUE; + + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic; -- '0' - Parity Error + +END gen_utils; + +PACKAGE BODY gen_utils IS + + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 403 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + ------------------------------------------------------------------- + -- Generate Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION GenParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic_vector + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic_vector (Data'Length - 1 DOWNTO 0); + BEGIN + I := 0; + WHILE (I < SIZE) LOOP + Result(I+7 DOWNTO I) := Data(I+7 downto I); + Result(I+8) := XOR_REDUCE( Data(I+7 downto I) ) XOR ODDEVEN; + I := I + 9; + END LOOP; + RETURN Result; + END GenParity; + + ------------------------------------------------------------------- + -- Check Parity for each 8-bit in 9th bit + ------------------------------------------------------------------- + FUNCTION CheckParity + (Data : in std_logic_vector; -- Data + ODDEVEN : in std_logic; -- ODD (1) / EVEN(0) + SIZE : in POSITIVE) -- Bit Size + RETURN std_logic -- '0' - Parity Error + IS + VARIABLE I: NATURAL; + VARIABLE Result: std_logic; + BEGIN + I := 0; Result := '1'; + WHILE (I < SIZE) LOOP + Result := Result AND + NOT (XOR_REDUCE( Data(I+8 downto I) ) XOR ODDEVEN); + I := I + 9; + END LOOP; + RETURN Result; + END CheckParity; + +END gen_utils;