////////////////////////////////////////////////////////////////////////////// // File name : s29ns512p.v ////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2006-2007 Free Model Foundry; http://www.FreeModelFoundry.com // // 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: | date: | changes made: // V1.0 M.Milanovic 06 May 28 Initial Release // V1.1 A.Anic 06 Jul 25 Update according new datasheet: // change Tabel time,burst in PPB // and DYB mode is disabled,VPP pin is // replaced with VACC pin,latching data // on the rising edge of CE# is enabled // V1.2 I.Milutinovic 07 Apr 04 Address and data latching fixed // V1.3 M.Vlahovic 07 Jun 01 Status read bug fixed // ////////////////////////////////////////////////////////////////////////////// // PART DESCRIPTION: // // Library: FLASH // Technology: FLASH MEMORY // Part: S29NS512P // // Description: 512 Mb (32 M x 16 bit) 1.8 V Burst Simultaneous Read/Write, // Multiplexed MirrorBit Flash Memory // ////////////////////////////////////////////////////////////////////////////// // Comments : // For correct simulation, simulator resolution should be set to 1ps // ////////////////////////////////////////////////////////////////////////////// // Known Bugs: // ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // MODULE DECLARATION // ////////////////////////////////////////////////////////////////////////////// `timescale 1 ps/1 ps module s29ns512p ( A24 , A23 , A22 , A21 , A20 , A19 , A18 , A17 , A16 , ADQ15 , ADQ14 , ADQ13 , ADQ12 , ADQ11 , ADQ10 , ADQ9 , ADQ8 , ADQ7 , ADQ6 , ADQ5 , ADQ4 , ADQ3 , ADQ2 , ADQ1 , ADQ0 , CLK , RESETNeg , CENeg , OENeg , WENeg , AVDNeg , WPNeg , VACC , RDY ); //////////////////////////////////////////////////////////////////////// // Port / Part Pin Declarations //////////////////////////////////////////////////////////////////////// input A24 ; input A23 ; input A22 ; input A21 ; input A20 ; input A19 ; input A18 ; input A17 ; input A16 ; inout ADQ15 ; inout ADQ14 ; inout ADQ13 ; inout ADQ12 ; inout ADQ11 ; inout ADQ10 ; inout ADQ9 ; inout ADQ8 ; inout ADQ7 ; inout ADQ6 ; inout ADQ5 ; inout ADQ4 ; inout ADQ3 ; inout ADQ2 ; inout ADQ1 ; inout ADQ0 ; input CLK ; input RESETNeg ; input CENeg ; input OENeg ; input WENeg ; input AVDNeg ; input WPNeg ; input VACC ; output RDY ; // interconnect path delay signals wire A24_ipd ; wire A23_ipd ; wire A22_ipd ; wire A21_ipd ; wire A20_ipd ; wire A19_ipd ; wire A18_ipd ; wire A17_ipd ; wire A16_ipd ; wire ADQ15_ipd ; wire ADQ14_ipd ; wire ADQ13_ipd ; wire ADQ12_ipd ; wire ADQ11_ipd ; wire ADQ10_ipd ; wire ADQ9_ipd ; wire ADQ8_ipd ; wire ADQ7_ipd ; wire ADQ6_ipd ; wire ADQ5_ipd ; wire ADQ4_ipd ; wire ADQ3_ipd ; wire ADQ2_ipd ; wire ADQ1_ipd ; wire ADQ0_ipd ; wire [24 : 0] A; assign A = { A24_ipd, A23_ipd, A22_ipd, A21_ipd, A20_ipd, A19_ipd, A18_ipd, A17_ipd, A16_ipd, ADQ15_ipd, ADQ14_ipd, ADQ13_ipd, ADQ12_ipd, ADQ11_ipd, ADQ10_ipd, ADQ9_ipd, ADQ8_ipd, ADQ7_ipd, ADQ6_ipd, ADQ5_ipd, ADQ4_ipd, ADQ3_ipd, ADQ2_ipd, ADQ1_ipd, ADQ0_ipd }; wire [15 : 0 ] DIn; assign DIn = {ADQ15_ipd, ADQ14_ipd, ADQ13_ipd, ADQ12_ipd, ADQ11_ipd, ADQ10_ipd, ADQ9_ipd, ADQ8_ipd, ADQ7_ipd, ADQ6_ipd, ADQ5_ipd, ADQ4_ipd, ADQ3_ipd, ADQ2_ipd, ADQ1_ipd, ADQ0_ipd }; wire [15 : 0 ] DOut; assign DOut = {ADQ15, ADQ14, ADQ13, ADQ12, ADQ11, ADQ10, ADQ9, ADQ8, ADQ7, ADQ6, ADQ5, ADQ4, ADQ3, ADQ2, ADQ1, ADQ0 }; wire CLK_ipd ; wire RESETNeg_ipd ; wire CENeg_ipd ; wire OENeg_ipd ; wire WENeg_ipd ; wire AVDNeg_ipd ; wire WPNeg_ipd ; wire VACC_ipd ; // internal delays reg IACC_in ; reg IACC_out ; reg PPBP_in ; reg PPBP_out ; reg PPBE_in ; reg PPBE_out ; reg PUT_in ; reg PUT_out ; reg START_in ; reg START_out ; reg SET_in ; reg SET_out ; reg RSTMOUT_in ; reg RSTMOUT_out ; reg [15 : 0] DOut_zd; wire DQ15_Pass ; wire DQ14_Pass ; wire DQ13_Pass ; wire DQ12_Pass ; wire DQ11_Pass ; wire DQ10_Pass ; wire DQ9_Pass ; wire DQ8_Pass ; wire DQ7_Pass ; wire DQ6_Pass ; wire DQ5_Pass ; wire DQ4_Pass ; wire DQ3_Pass ; wire DQ2_Pass ; wire DQ1_Pass ; wire DQ0_Pass ; reg [15 : 0] DOut_Pass; assign {DQ15_Pass, DQ14_Pass, DQ13_Pass, DQ12_Pass, DQ11_Pass, DQ10_Pass, DQ9_Pass, DQ8_Pass, DQ7_Pass, DQ6_Pass, DQ5_Pass, DQ4_Pass, DQ3_Pass, DQ2_Pass, DQ1_Pass, DQ0_Pass } = DOut_Pass; reg RDY_zd; reg RDY_temp = 1'b0; parameter mem_file_name = "none"; parameter prot_file_name = "none"; parameter secsi_file_name = "none"; parameter UserPreload = 1'b0; parameter TimingModel = "DefaultTimingModel"; parameter PartID = "s29ns512p"; parameter MaxData = 16'hFFFF; parameter MaxAddr = 25'h1FFFFFF; parameter SecNum = 511; parameter BankNum = 15; parameter SecSize64 = 16'hFFFF; parameter BankSize = 21'h1FFFFF; parameter SecBit64 = 9; parameter BankBit = 4; parameter HiAddrBit = 24; parameter PWLength = 3; parameter WrBuffLength = 31; parameter WrBuffPgNum = 20'hFFFFF; // If speedsimulation is needed uncomment following line //`define SPEEDSIM; // powerup reg PoweredUp; reg SYN; //Synchronous mode reg CLK_PATH_EN; //FSM control signals reg ULBYPASS =1'b0;//Unlock Bypass Active reg ESP_ACT =1'b0;//Erase Suspend reg PSP_ACT =1'b0;//Program Suspend reg LOCK_ACT =1'b0;//Lock Register program reg PASS_ACT =1'b0;//Password program reg WRBUFF_ACT=1'b0;//Wrbuffer program reg SecSi =1'b0;//SecSi Sector mapped in Sec 0 reg PDONE ; //Prog. Done reg PSTART ; //Start Programming reg PSUSP ; //Suspend Programming reg PRES ; //Resume Programming reg PERR ; //Protected reg EDONE ; //Ers. Done reg ESTART ; //Start Erase reg ESUSP ; //Suspend Erase reg ERES ; //Resume Erase //All sectors selected for erasure are protected reg EERR ; reg WP_l ;// WP control signal reg HI_FREQ ;// signal that indicates clk frequency //Sectors selected for erasure reg [SecNum:0] ERS_QUEUE; // = SecNum'b0; //Banks selected for erasure reg [BankNum:0] ERS_QUEUE_B; // = BankNum'b0; //Command Register reg write = 1'b0; reg read = 1'b0; reg burst_rd = 1'b0; //Parameters of bank specific operations //Supports 15 (or less) bank architecture reg[3:0] BankASAddr; reg[3:0] BankCFIAddr; reg[3:0] BankErSuspAddr; reg[3:0] BankDYBAddr; reg[3:0] BankPPBAddr; reg[3:0] BankPPBLAddr; reg[4:0] PrgBank; //must support -1 recognition // write buffer signals integer PrevBuffAd; integer WrBuffSec; integer WrBuffPage; integer WrBuffCnt; integer WrCnt; integer WrBuffData[0:WrBuffLength]; integer WrBuffAddr[0:WrBuffLength]; //password signals integer PASS_UNLCK = 1'b0; integer PASS_TEMP[0:PWLength]; //protection bit signals integer SecDYBAddr; integer SecPPBAddr; //Address integer Address = -1; // -1 - MaxAddr //Address 11 downto 0 integer AddrCom = 0; integer AddrPass = 0; // 0 - 3 //Sector Address integer SecAddr = -1; // -1 - SecNum //Bank Address integer BankAddr = -1; // 0 - BankNum //Write page buffer address integer BuffPageAddr = -1; // -1 - WrBuffPgNum integer Data; //-1 TO MaxData; integer DataLo; //0 TO MaxData; //glitch protection reg gWE_n ; reg gCE_n ; reg gOE_n ; reg gAVD_n ; reg tAVD_p ; reg RST ; reg reseted ; //Memory integer Mem[0:MaxAddr]; integer SecSiMem[0:8'hFF]; integer CFIMem[8'h10:8'h67]; reg[15:0] CONF_REG0; reg[15:0] CONF_REG1; reg[15:0] LOCK_REG; //Sector Protection status integer Password[0:PWLength]; reg[SecNum:0] DYB; reg[SecNum:0] PPB; reg PPB_LOCK; reg PPB_MODE = 1'b0; reg DYB_MODE = 1'b0; reg[SecNum:0] Boot_Sec = 0; // timing check violation reg Viol = 1'b0; reg HWResetGlitch = 1'b0; reg HWResetStart = 1'b0; reg Glitch = 1'b0; reg ResumeFlag = 1'b0; // StateTransition values reg R; reg E; //Bus Cycle Decode reg[HiAddrBit:0] A_tmp; integer LatchedWrAddr; reg RD; reg LATCHED; //StateGen //Command Sequence detection reg PATTERN_1 = 1'b0; reg PATTERN_2 = 1'b0; //Functional integer WS_CNT; integer WS_CNT_f; reg Prior_IACC; reg oe = 1'b0; //status reg. reg[15:0] status = 16'b0; reg[15:0] old_bit; reg[15:0] new_bit; integer old_int; integer new_int; reg[7:0] temp; integer x; //Burst Params integer BurstAddr; integer BurstSec; integer BurstLength; integer RdCnt; reg [15 : 0] DOut_burst; integer DelayCyc_CNT; integer DelayCycSwitch; integer BoundarySwitch; reg ONE_READ; reg CONF_REG_8; //Burst mode control reg INITIAL_WAIT; reg INITIAL_ACCESS; reg BOUNDARY_CROSS; reg NO_PROGRESS; reg BURST_END; reg IN_W_ELAPSED; integer i,j,k; //TPD_XX_DATA time OEDQ_t; time CEDQ_t; time ADDRDQ_t; time AddrTime; time OENeg_event; time CENeg_event; time ADDR_event; reg FROMOE; reg FROMCE; integer OEDQ_01; integer CEDQ_01; integer ADDRDQ_01; reg[15:0] TempData; event oe_event; reg [6:0] current_state; reg [6:0] next_state; reg [6:0] read_rise_state; reg [2:0] RD_MODE; // FSM states parameter RESET =8'h00; parameter Z001 =8'h01; parameter CFI =8'h02; parameter PREL_SETBWB =8'h03; parameter PREL_ULBYPASS =8'h04; parameter PREL_ULBYPASS_RESET =8'h05; parameter A0SEEN =8'h06; parameter C8 =8'h07; parameter C8_Z001 =8'h08; parameter C8_PREL =8'h09; parameter ERS =8'h0A; parameter SERS =8'h0B; parameter ESPS =8'h0C; parameter SERS_EXEC =8'h0D; parameter ESP =8'h0E; parameter ESP_Z001 =8'h0F; parameter ESP_PREL =8'h10; parameter PREL_WR2BUFF =8'h11; parameter WR2BUFF_0 =8'h12; parameter WR2BUFF_CNT =8'h13; parameter PREL_PRFLASH =8'h14; parameter PGMS =8'h15; parameter PGSPS =8'h16; parameter PGS =8'h17; parameter PGS_Z001 =8'h18; parameter PGS_PREL =8'h19; parameter WR2BUFF_AB =8'h1A; parameter WR2BUFF_AB_Z001 =8'h1B; parameter WR2BUFF_AB_PREL =8'h1C; parameter AS =8'h1D; parameter SECSI_EX =8'h1E; parameter SET_CONF =8'h1F; parameter SET_CONF1 =8'h20; parameter RD_CONF =8'h21; parameter PREL_PASS =8'h22; parameter PASS_A0SEEN =8'h23; parameter PASS_EX =8'h24; parameter PASS_UN_Z001 =8'h25; parameter PASS_UN_PREL =8'h26; parameter PASS_UN1 =8'h27; parameter PASS_UN2 =8'h28; parameter PASS_UN3 =8'h29; parameter PASS_UN4 =8'h2A; parameter PASS_UN_W =8'h2B; parameter PREL_LR =8'h2C; parameter LR_A0SEEN =8'h2D; parameter LR_PREL_EX =8'h2E; parameter PREL_PPB =8'h2F; parameter PPB_PREL_PR =8'h30; parameter PPB_PGMS =8'h31; parameter PPB_PREL_ER =8'h32; parameter PPB_ERS =8'h33; parameter PPB_PREL_EX =8'h34; parameter PREL_PPBLCK =8'h35; parameter PPBLCK_PREL_ST =8'h36; parameter PPBLCK_PREL_EX =8'h37; parameter PREL_DYB =8'h38; parameter DYB_PREL_ST =8'h39; parameter DYB_PREL_EX =8'h3A; parameter SECSI_A0SEEN =8'h3B; parameter HW_RESET_UNKNOWN =8'h3C; parameter HW_RESET_INIT =8'h3D; //read mode parameter NONE = 4'd0; parameter SINGLE_RD = 4'd1; parameter LINEAR = 4'd2; parameter LINEAR_NO_WRAP = 4'd3; parameter CONTINUOUS = 4'd4; /////////////////////////////////////////////////////////////////////////////// //Interconnect Path Delay Section /////////////////////////////////////////////////////////////////////////////// buf (A24_ipd, A24); buf (A23_ipd, A23); buf (A22_ipd, A22); buf (A21_ipd, A21); buf (A20_ipd, A20); buf (A19_ipd, A19); buf (A18_ipd, A18); buf (A17_ipd, A17); buf (A16_ipd, A16); buf (ADQ15_ipd, ADQ15); buf (ADQ14_ipd, ADQ14); buf (ADQ13_ipd, ADQ13); buf (ADQ12_ipd, ADQ12); buf (ADQ11_ipd, ADQ11); buf (ADQ10_ipd, ADQ10); buf (ADQ9_ipd , ADQ9 ); buf (ADQ8_ipd , ADQ8 ); buf (ADQ7_ipd , ADQ7 ); buf (ADQ6_ipd , ADQ6 ); buf (ADQ5_ipd , ADQ5 ); buf (ADQ4_ipd , ADQ4 ); buf (ADQ3_ipd , ADQ3 ); buf (ADQ2_ipd , ADQ2 ); buf (ADQ1_ipd , ADQ1 ); buf (ADQ0_ipd , ADQ0 ); buf (CLK_ipd , CLK ); buf (RESETNeg_ipd , RESETNeg ); buf (CENeg_ipd , CENeg ); buf (OENeg_ipd , OENeg ); buf (WENeg_ipd , WENeg ); buf (AVDNeg_ipd , AVDNeg ); buf (WPNeg_ipd , WPNeg ); buf (VACC_ipd , VACC ); /////////////////////////////////////////////////////////////////////////////// // Propagation delay Section /////////////////////////////////////////////////////////////////////////////// nmos (ADQ15, DQ15_Pass , 1); nmos (ADQ14, DQ14_Pass , 1); nmos (ADQ13, DQ13_Pass , 1); nmos (ADQ12, DQ12_Pass , 1); nmos (ADQ11, DQ11_Pass , 1); nmos (ADQ10, DQ10_Pass , 1); nmos (ADQ9 , DQ9_Pass , 1); nmos (ADQ8 , DQ8_Pass , 1); nmos (ADQ7 , DQ7_Pass , 1); nmos (ADQ6 , DQ6_Pass , 1); nmos (ADQ5 , DQ5_Pass , 1); nmos (ADQ4 , DQ4_Pass , 1); nmos (ADQ3 , DQ3_Pass , 1); nmos (ADQ2 , DQ2_Pass , 1); nmos (ADQ1 , DQ1_Pass , 1); nmos (ADQ0 , DQ0_Pass , 1); nmos (RDY , RDY_zd , 1); wire deg; // Needed for TimingChecks // VHDL CheckEnable Equivalent wire Check_ADQ0_CLK; assign Check_ADQ0_CLK = ~CENeg && SYN && WENeg && ~AVDNeg; wire Check_ADQ0_AVDNeg; assign Check_ADQ0_AVDNeg = ~CENeg && ~OENeg; wire Check_ADQ0_WENeg; assign Check_ADQ0_WENeg = ~CENeg && OENeg; wire Check_OENeg_WENeg; assign Check_OENeg_WENeg = ~PDONE || ~EDONE; wire Check_AVDNeg_CLK; assign Check_AVDNeg_CLK = ~CENeg && ~AVDNeg && SYN; wire Check_CENeg_CLK; assign Check_CENeg_CLK = SYN; wire CLK_PATH_ENABLE; assign CLK_PATH_ENABLE = CLK_PATH_EN && SYN; 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 specparam tpd_RESETNeg_ADQ0 = 1; specparam tpd_CENeg_ADQ0 = 1;//tce, tcez specparam tpd_OENeg_ADQ0 = 1;//toe, toez specparam tpd_CLK_ADQ0 = 1;//tbacc specparam tpd_CENeg_RDY = 1;//trdy, tcez specparam tpd_OENeg_RDY = 1;//toe specparam tpd_CLK_RDY = 1;//tracc //tsetup values specparam tsetup_ADQ0_CLK = 1;//tacs / specparam tsetup_CENeg_CLK = 1;//tces / specparam tsetup_AVDNeg_CLK = 1;//tavds / specparam tsetup_ADQ0_AVDNeg = 1;//taavds,tas / specparam tsetup_CENeg_WENeg = 1;//tcs \ specparam tsetup_ADQ0_WENeg = 1;//tds / specparam tsetup_AVDNeg_WENeg = 1;//tavhw \ //thold values specparam thold_CENeg_RESETNeg = 1;//trh /,trph \ specparam thold_OENeg_RESETNeg = 1;//trh /,trph \ specparam thold_ADQ0_CLK = 1;//tach / specparam thold_AVDNeg_CLK = 1;//tavdh / specparam thold_ADQ0_AVDNeg = 1;//taavdh,tah / specparam thold_OENeg_WENeg = 1;//toeh / specparam thold_CENeg_WENeg = 1;//tch / specparam thold_OENeg_AVDNeg = 1;//tavdo / specparam thold_ADQ0_WENeg = 1;//tdh / specparam thold_WENeg_AVDNeg = 1;//tavsw \ //tpw values specparam tpw_RESETNeg_negedge = 1;//trp specparam tpw_CLK_negedge = 1;//tcl specparam tpw_CLK_posedge = 1;//tch specparam tpw_AVDNeg_negedge = 1;//tavdp specparam tpw_WENeg_negedge = 1;//twp specparam tpw_WENeg_posedge = 1;//twph //tperiod values specparam tperiod_WENeg = 1;//twc specparam tperiod_CLK = 1;//tclk //tdevice values: values for internal delays `ifdef SPEEDSIM specparam tdevice_PWO = 6000; specparam tdevice_WRBO = 3000; //Sector Erase Operation specparam tdevice_SEO64 = 600000; //Protection Bit Program specparam tdevice_PPBP = 7500; //Protection Bit Erase specparam tdevice_PPBE = 15000; //Password Unlock specparam tdevice_PUT = 1000; //program/erase suspend timeout specparam tdevice_START = 4000; //sector erase command sequence timeout specparam tdevice_SET = 10000; //Resume to Suspend specparam tdevice_RSTMOUT = 6000; `else specparam tdevice_PWO = 30000; specparam tdevice_WRBO = 6000; //Sector Erase Operation specparam tdevice_SEO64 = 600000000; //Protection Bit Program specparam tdevice_PPBP = 150000; //Protection Bit Erase specparam tdevice_PPBE = 15000000; //Password Unlock specparam tdevice_PUT = 1000; //program/erase suspend timeout specparam tdevice_START = 20000; //sector erase command sequence timeout specparam tdevice_SET = 50000; //Resume to Suspend specparam tdevice_RSTMOUT = 30000; `endif //SPEEDSIM //tIACC - access time //Must be specifed aligned to model timescale due to its usage //within path delay section and access time calculations specparam tdevice_TIACC_ts = 80000; /////////////////////////////////////////////////////////////////////////////// // Input Port Delays don't require Verilog description /////////////////////////////////////////////////////////////////////////////// // Path delays // /////////////////////////////////////////////////////////////////////////////// // Data ouptut paths if (FROMCE) ( CENeg => ADQ0 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ1 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ2 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ3 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ4 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ5 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ6 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ7 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ8 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ9 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ10 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ11 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ12 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ13 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ14 ) = tpd_CENeg_ADQ0; if (FROMCE) ( CENeg => ADQ15 ) = tpd_CENeg_ADQ0; if (FROMOE) ( OENeg => ADQ0 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ1 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ2 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ3 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ4 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ5 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ6 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ7 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ8 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ9 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ10 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ11 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ12 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ13 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ14 ) = tpd_OENeg_ADQ0; if (FROMOE) ( OENeg => ADQ15 ) = tpd_OENeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ0 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ1 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ2 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ3 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ4 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ5 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ6 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ7 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ8 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ9 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ10 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ11 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ12 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ13 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ14 ) = tpd_RESETNeg_ADQ0; if (~RESETNeg) ( RESETNeg => ADQ15 ) = tpd_RESETNeg_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ0 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ1 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ2 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ3 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ4 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ5 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ6 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ7 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ8 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ9 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ10 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ11 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ12 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ13 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ14 ) = tpd_CLK_ADQ0; if (CLK_PATH_ENABLE) ( CLK => ADQ15 ) = tpd_CLK_ADQ0; // RDY output paths (CENeg => RDY) = tpd_CENeg_RDY; if ( ~CENeg && SYN ) ( OENeg => RDY ) = tpd_OENeg_RDY; if ( CLK_PATH_ENABLE ) ( CLK => RDY ) = tpd_CLK_RDY; //////////////////////////////////////////////////////////////////////////////// // Timing Violation // //////////////////////////////////////////////////////////////////////////////// $setup ( ADQ0 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ1 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ2 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ3 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ4 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ5 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ6 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ7 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ8 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ9 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ10 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ11 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ12 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ13 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ14 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( ADQ15 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( A16 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( A17 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( A18 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( A19 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( A20 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( A21 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( A22 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( A23 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $setup ( A24 , posedge CLK &&& Check_ADQ0_CLK , tsetup_ADQ0_CLK,Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ0 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ1 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ2 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ3 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ4 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ5 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ6 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ7 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ8 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ9 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ10, thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ11, thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ12, thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ13, thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ14, thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , ADQ15, thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , A16 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , A17 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , A18 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , A19 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , A20 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , A21 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , A22 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , A23 , thold_ADQ0_CLK, Viol); $hold ( posedge CLK &&& Check_ADQ0_CLK , A24 , thold_ADQ0_CLK, Viol); $setup ( ADQ0 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ1 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ2 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ3 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ4 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ5 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ6 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ7 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ8 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ9 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ10 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ11 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ12 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ13 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ14 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( ADQ15 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( A16 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( A17 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( A18 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( A19 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( A20 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( A21 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( A22 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( A23 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $setup ( A24 , posedge AVDNeg &&& Check_ADQ0_AVDNeg, tsetup_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ0 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ1 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ2 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ3 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ4 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ5 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ6 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ7 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ8 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ9 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ10 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ11 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ12 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ13 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ14 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, ADQ15 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, A16 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, A17 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, A18 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, A19 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, A20 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, A21 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, A22 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, A23 , thold_ADQ0_AVDNeg, Viol); $hold ( posedge AVDNeg &&& Check_ADQ0_AVDNeg, A24 , thold_ADQ0_AVDNeg, Viol); $setup ( ADQ0 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ1 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ2 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ3 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ4 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ5 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ6 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ7 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ8 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ9 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ10 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ11 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ12 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ13 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ14 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $setup ( ADQ15 , posedge WENeg &&& Check_ADQ0_WENeg, tsetup_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ0 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ1 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ2 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ3 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ4 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ5 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ6 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ7 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ8 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ9 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ10 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ11 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ12 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ13 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ14 , thold_ADQ0_WENeg, Viol); $hold ( posedge WENeg &&& Check_ADQ0_WENeg, ADQ15 , thold_ADQ0_WENeg, Viol); $setup ( AVDNeg ,posedge CLK &&& Check_AVDNeg_CLK, tsetup_AVDNeg_CLK, Viol); $hold ( posedge CLK &&& Check_AVDNeg_CLK, AVDNeg , thold_AVDNeg_CLK, Viol); $setup ( CENeg , posedge CLK &&& Check_CENeg_CLK, tsetup_CENeg_CLK, Viol); $setup ( CENeg , negedge WENeg, tsetup_CENeg_WENeg, Viol); $hold ( posedge WENeg , CENeg, thold_CENeg_WENeg, Viol); $hold ( posedge WENeg , OENeg &&& Check_OENeg_WENeg, thold_OENeg_WENeg, Viol); $hold ( posedge AVDNeg , OENeg &&& ~CENeg , thold_OENeg_AVDNeg, Viol); $hold ( posedge RESETNeg, CENeg , thold_CENeg_RESETNeg, Viol); $hold ( posedge RESETNeg, OENeg , thold_OENeg_RESETNeg, Viol); $hold ( negedge RESETNeg, CENeg , thold_CENeg_RESETNeg, Viol); $hold ( negedge RESETNeg, OENeg , thold_OENeg_RESETNeg, Viol); $setup ( AVDNeg , negedge WENeg, tsetup_AVDNeg_WENeg, Viol); $hold ( negedge AVDNeg, WENeg , thold_WENeg_AVDNeg, Viol); $width (negedge RESETNeg, tpw_RESETNeg_negedge); $width (negedge AVDNeg , tpw_AVDNeg_negedge); $width (posedge WENeg , tpw_WENeg_posedge); $width (negedge WENeg , tpw_WENeg_negedge); $width (posedge CLK , tpw_CLK_posedge); $width (negedge CLK , tpw_CLK_negedge); $period(negedge WENeg, tperiod_WENeg); $period(posedge WENeg, tperiod_WENeg); $period(negedge CLK, tperiod_CLK); $period(posedge CLK, tperiod_CLK); endspecify //tdevice parameters aligned to model timescale //32bits exceeded time tdevice_PWO_ts = tdevice_PWO * 1000; time tdevice_WRBO_ts = tdevice_WRBO * 1000; //Sector Erase Operation time tdevice_SEO64_ts = tdevice_SEO64 * 1000; //Protection Bit Program time tdevice_PPBP_ts = tdevice_PPBP * 1000; //Protection Bit Erase time tdevice_PPBE_ts = tdevice_PPBE * 1000; //Password Unlock time tdevice_PUT_ts = tdevice_PUT * 1000; //program/erase suspend timeout time tdevice_START_ts = tdevice_START * 1000; //sector erase command sequence timeout time tdevice_SET_ts = tdevice_SET * 1000; //Resume to Suspend time tdevice_RSTMOUT_ts = tdevice_RSTMOUT * 1000; //Used as wait periods `ifdef SPEEDSIM time poweredupT_ts = 30000000; // 30 us time resetpulseT_ts = 50000; // 50 ns time perrpulseT_ts = 1000000; // 1 us time eerrpulseT_ts = 2800000; // 2.8 us time wepulseT_ts = 3000; // 3 ns `else // not SPEEDSIM time poweredupT_ts = 30000000; // 30 us time resetpulseT_ts = 50000; // 50 ns time perrpulseT_ts = 1000000; // 1 us time eerrpulseT_ts = 280000000; // 280 us time wepulseT_ts = 3000; // 3 ns `endif // SPEEDSIM //////////////////////////////////////////////////////////////////////////////// // Main Behavior Block // //////////////////////////////////////////////////////////////////////////////// reg deq; ////////////////////////////////////////////////////////// // Output Data Gen ////////////////////////////////////////////////////////// always @(DOut_zd) begin : OutputGen if (DOut_zd[0] !== 1'bz) begin CEDQ_t = CENeg_event + CEDQ_01; OEDQ_t = OENeg_event + OEDQ_01; //tACC relevant for asynchronous access time ADDRDQ_t = AddrTime + ADDRDQ_01; FROMCE = ((CEDQ_t >= OEDQ_t) && ( CEDQ_t >= $time)); FROMOE = ((OEDQ_t >= CEDQ_t) && ( OEDQ_t >= $time)); if ((ADDRDQ_t > $time )&& (((ADDRDQ_t>OEDQ_t)&&FROMOE) || ((ADDRDQ_t>CEDQ_t)&&FROMCE))) begin TempData = DOut_zd; DOut_Pass = 16'bx; DOut_Pass <= #( ADDRDQ_t - $time ) TempData; end else DOut_Pass = DOut_zd; end end always @(DOut_zd) begin if (DOut_zd[0] === 1'bz) begin disable OutputGen; FROMCE = 1'b1; FROMOE = 1'b1; DOut_Pass = 16'bz; end end ////////////////////////////////////////////////////////// // RDY Pin Value Gen ////////////////////////////////////////////////////////// always @(RDY_temp,OENeg,CENeg) begin if (~CENeg) begin if (SYN) begin if (~OENeg) begin if ( CONF_REG0[10]) RDY_zd = RDY_temp; else RDY_zd = ~RDY_temp; end else RDY_zd = CONF_REG0[10]; end else RDY_zd = 1'b1; end else RDY_zd = 1'bz; end always @(DIn, DOut) begin if (DIn==DOut) deq=1'b1; else deq=1'b0; end // check when data is generated from model to avoid setuphold check in // those occasions assign deg=deq; initial begin for (i=0;i<=SecNum;i=i+1) begin ERS_QUEUE[i] = 0; end for (i=0;i<=BankNum;i=i+1) begin ERS_QUEUE_B[i] = 0; end //////////////////////////////////////////////////////////////////- //CFI array data / S29NS512P DEVICE SPECIFIC //////////////////////////////////////////////////////////////////- //CFI query identification string CFIMem[16'h10] = 16'h51; CFIMem[16'h11] = 16'h52; CFIMem[16'h12] = 16'h59; CFIMem[16'h13] = 16'h02; CFIMem[16'h14] = 16'h00; CFIMem[16'h15] = 16'h40; CFIMem[16'h16] = 16'h00; CFIMem[16'h17] = 16'h00; CFIMem[16'h18] = 16'h00; CFIMem[16'h19] = 16'h00; CFIMem[16'h1A] = 16'h00; //System interface string CFIMem[16'h1B] = 16'h17; CFIMem[16'h1C] = 16'h19; CFIMem[16'h1D] = 16'h00; CFIMem[16'h1E] = 16'h00; CFIMem[16'h1F] = 16'h05; CFIMem[16'h20] = 16'h09; CFIMem[16'h21] = 16'h0A; CFIMem[16'h22] = 16'h00; CFIMem[16'h23] = 16'h03; CFIMem[16'h24] = 16'h03; CFIMem[16'h25] = 16'h03; CFIMem[16'h26] = 16'h00; //device geometry definition CFIMem[16'h27] = 16'h1A; CFIMem[16'h28] = 16'h01; CFIMem[16'h29] = 16'h00; CFIMem[16'h2A] = 16'h06; CFIMem[16'h2B] = 16'h00; CFIMem[16'h2C] = 16'h01; CFIMem[16'h2D] = 16'h1FF; CFIMem[16'h2E] = 16'h00; CFIMem[16'h2F] = 16'h00; CFIMem[16'h30] = 16'h02; CFIMem[16'h31] = 16'h00; CFIMem[16'h32] = 16'h00; CFIMem[16'h33] = 16'h00; CFIMem[16'h34] = 16'h00; CFIMem[16'h35] = 16'h00; CFIMem[16'h36] = 16'h00; CFIMem[16'h37] = 16'h00; CFIMem[16'h38] = 16'h00; CFIMem[16'h39] = 16'h00; CFIMem[16'h3A] = 16'h00; CFIMem[16'h3B] = 16'h00; CFIMem[16'h3C] = 16'h00; //primary vendor-specific extended query CFIMem[16'h40] = 16'h50; CFIMem[16'h41] = 16'h52; CFIMem[16'h42] = 16'h49; CFIMem[16'h43] = 16'h31; CFIMem[16'h44] = 16'h34; CFIMem[16'h45] = 16'h05; CFIMem[16'h46] = 16'h02; CFIMem[16'h47] = 16'h01; CFIMem[16'h48] = 16'h00; CFIMem[16'h49] = 16'h08; CFIMem[16'h4A] = 16'h1E3; CFIMem[16'h4B] = 16'h01; CFIMem[16'h4C] = 16'h00; CFIMem[16'h4D] = 16'h85; CFIMem[16'h4E] = 16'h95; CFIMem[16'h4F] = 16'h05; CFIMem[16'h50] = 16'h01; CFIMem[16'h51] = 16'h01; CFIMem[16'h52] = 16'h08; CFIMem[16'h53] = 16'h14; CFIMem[16'h54] = 16'h14; CFIMem[16'h55] = 16'h05; CFIMem[16'h56] = 16'h05; CFIMem[16'h57] = 16'h10; CFIMem[16'h58] = 16'h20; CFIMem[16'h59] = 16'h20; CFIMem[16'h5A] = 16'h20; CFIMem[16'h5B] = 16'h20; CFIMem[16'h5C] = 16'h20; CFIMem[16'h5D] = 16'h20; CFIMem[16'h5E] = 16'h20; CFIMem[16'h5F] = 16'h20; CFIMem[16'h60] = 16'h20; CFIMem[16'h61] = 16'h20; CFIMem[16'h62] = 16'h20; CFIMem[16'h63] = 16'h20; CFIMem[16'h64] = 16'h20; CFIMem[16'h65] = 16'h20; CFIMem[16'h66] = 16'h20; CFIMem[16'h67] = 16'h20; end // initialize memory and load preoload files if any initial begin: InitMemory integer i,j; integer secsi[0:8'hFF]; reg sector_prot[0:SecNum]; for (i=0;i<=MaxAddr;i=i+1) begin Mem[i]=MaxData; end for (i=0;i<8'hFF;i=i+1) begin secsi[i]=MaxData; end for (i=0;i<=SecNum;i=i+1) begin sector_prot[i]=1'b1; end if (UserPreload && !(prot_file_name == "none")) begin // s29ns512p prot file // / - comment // @sss - is the hexadecimal number of // the sector to be protected // b is 0 if the sector should be protected // If not specified a sector is unprotected // sss is incremented on every load // No empty lines. $readmemb(prot_file_name,sector_prot); end if (UserPreload && !(mem_file_name == "none")) begin // s29ns512p memory file // / - comment // @aaaaaaa- stands for address // dddd - is word to be written at Mem(aaaaaaa++) // (aaaaaaa is incremented at every load) // No empty lines. $readmemh(mem_file_name,Mem); end if (UserPreload && !(secsi_file_name == "none")) begin // s29ns512p SecSi file // / - comment // @aa - stands for address // dddd - is word to be written at SecSi(aa++) // (aa is incremented at every load) // No empty lines. $readmemh(secsi_file_name,secsi); end for (i=0;i<=SecNum;i=i+1) begin PPB[i] = sector_prot[i]; end //SecSi Preload for (i=0;i<=8'hFF;i=i+1) begin SecSiMem[i] = secsi[i]; end end //Power Up time 30 us; initial begin PoweredUp = 1'b0; #poweredupT_ts PoweredUp = 1'b1; end always @(negedge RESETNeg) begin : RST_falling_edge #(resetpulseT_ts-1) RST <= 1'b0; end always @(posedge RESETNeg) begin disable RST_falling_edge; #1 RST <= 1'b1; end always @(posedge PoweredUp) begin for (i=0;i<=SecNum;i=i+1) Boot_Sec[i] = 1'b0; end initial begin SYN = 1'b0; ULBYPASS = 1'b0; ESP_ACT = 1'b0; PSP_ACT = 1'b0; LOCK_ACT = 1'b0; PASS_ACT = 1'b0; WRBUFF_ACT = 1'b0; SecSi = 1'b0; PDONE = 1'b1; PSTART = 1'b0; PRES = 1'b0; PSUSP = 1'b0; PERR = 1'b0; EDONE = 1'b1; ESTART = 1'b0; ESUSP = 1'b0; ERES = 1'b0; EERR = 1'b0; ERS_QUEUE = 0; ERS_QUEUE_B = 0; WP_l = 1'b0; HI_FREQ = 1'b0; R = 0; E = 0; OENeg_event = 0; CENeg_event = 0; ADDR_event = 0; AddrTime = 0; RD_MODE = NONE; PPB_MODE = 1'b0; DYB_MODE = 1'b0; CONF_REG0 = 16'b0010111111001000; CONF_REG1 = 16'b1111111111101111; LOCK_REG = ~(0); for(i=0;i<=SecNum;i=i+1) DYB[i] = 1'b1; for(i=0;i<=3;i=i+1) Password[i] = MaxData; PPB_LOCK = 1'b1; end always @(posedge START_in) begin:TSTARTr #(tdevice_START_ts-1) START_out = START_in; end always @(negedge START_in) begin:TSTARTf #1 START_out = START_in; end // Protection Bit Program always @(posedge PPBP_in) begin : ProtProgTime #(tdevice_PPBP_ts - 1) PPBP_out = 1'b1; end always @(negedge PPBP_in) begin disable ProtProgTime; PPBP_out = 1'b0; end // Protection Bit Erase always @(posedge PPBE_in) begin : ProtEraseTime #(tdevice_PPBE_ts - 1) PPBE_out = 1'b1; end always @(negedge PPBE_in) begin disable ProtEraseTime; PPBE_out = 1'b0; end // Sector erase timeout always @(posedge SET_in) begin : SectorEraseTimeout #(tdevice_SET_ts - 1) SET_out = 1'b1; end always @(negedge SET_in) begin disable SectorEraseTimeout; SET_out = 1'b0; end // Password Unlock always @(posedge PUT_in) begin : UnlockTime #(tdevice_PUT_ts - 1) PUT_out = 1'b1; end always @(negedge PUT_in) begin disable UnlockTime; PUT_out = 1'b0; end //Initial Access always @(posedge IACC_in) begin : AccessTime #(tdevice_TIACC_ts - 1) IACC_out = 1'b1; end always @(negedge IACC_in) begin disable AccessTime; IACC_out = 1'b0; end //Resume to Suspend always @(posedge RSTMOUT_in) begin : ResToSusp #(tdevice_RSTMOUT_ts - 1) RSTMOUT_out = 1'b1; end always @(negedge RSTMOUT_in) begin disable ResToSusp; RSTMOUT_out = 1'b0; end //////////////////////////////////////////////////////////////////////////// //// obtain 'LAST_EVENT information //////////////////////////////////////////////////////////////////////////// always @(negedge OENeg) begin OENeg_event = $time; end always @(negedge CENeg) begin CENeg_event = $time; end //////////////////////////////////////////////////////////////////////////// // Process that determines clock frequency //////////////////////////////////////////////////////////////////////////// time CLK_PER = 0; time LAST_CLK = 0; reg Check_freq1 = 0; reg Check_freq2 = 0; always @(posedge CLK) begin CLK_PER = $time - LAST_CLK; LAST_CLK = $time; if (Check_freq1 && Check_freq2) begin Check_freq2 = 0; if ((CLK_PER < 71429 && WS_CNT_f < 3) || (CLK_PER < 37037 && WS_CNT_f < 4) || (CLK_PER < 25000 && WS_CNT_f < 5) || (CLK_PER < 18519 && WS_CNT_f < 6) || (CLK_PER < 14925 && WS_CNT_f < 7) || (CLK_PER < 12048 && WS_CNT_f < 8) || (CLK_PER < 10526 && WS_CNT_f < 9)) begin Check_freq1 = 0; $display("More wait states are required for "); $display("this clock frequency value"); end end end //////////////////////////////////////////////////////////////////////////// //// sequential process for reset control and FSM state transition //////////////////////////////////////////////////////////////////////////// reg rising_edge_RESETNeg; reg falling_edge_RESETNeg; reg rising_edge_RST; reg falling_edge_RST; reg rising_edge_PDONE; reg falling_edge_PDONE; reg rising_edge_EDONE; reg falling_edge_EDONE; reg rising_edge_gCE_n; reg rising_edge_gWE_n; reg falling_edge_WENeg; reg rising_edge_CENeg; reg rising_edge_OENeg; reg falling_edge_OENeg; reg rising_edge_write; reg falling_edge_write; reg A_event; reg falling_edge_reseted; reg rising_edge_reseted; reg rising_edge_PSTART; reg rising_edge_ESUSP; reg rising_edge_PSUSP; reg rising_edge_PRES; reg falling_edge_ESUSP; reg rising_edge_ERES; reg falling_edge_ERES; reg rising_edge_ESTART; reg falling_edge_ESTART; reg rising_edge_EERR; reg falling_edge_EERR; reg rising_edge_SET_out; reg falling_edge_SET_out; reg rising_edge_START_out; reg falling_edge_START_out; reg rising_edge_PERR; reg falling_edge_PERR; reg rising_edge_PPBE_out; reg rising_edge_PPBP_out; reg rising_edge_PUT_out; reg rising_edge_HWResetStart; reg rising_edge_HWResetGlitch; reg rising_edge_AVDNeg; reg falling_edge_AVDNeg; reg rising_edge_CLK; reg falling_edge_gWE_n; reg falling_edge_gCE_n; reg rising_edge_burst_rd; reg rising_edge_IACC_out; reg rising_edge_oe; always @(falling_edge_RESETNeg or rising_edge_RESETNeg or next_state or RST or PoweredUp) begin if (PoweredUp ) begin if (falling_edge_RESETNeg ) begin Glitch = 1'b0; HWResetStart = 1'b1; HWResetStart <= #1 1'b0; current_state = HW_RESET_INIT; end else if ( rising_edge_RESETNeg) begin if ( RST === 1'b1 ) begin Glitch = 1'b1; HWResetGlitch = 1'b1; HWResetGlitch <= #1 1'b0; end end else if ( RESETNeg === 1'b1 ) begin current_state = next_state; reseted = 1'b1; end else if (RESETNeg === 1'b0 && RST === 1'b0) begin current_state = RESET; //reset reseted = 1'b0; CONF_REG0 = 16'b0010111111001000; CONF_REG1 = 16'b1111111111101111; SYN = 1'b0; RD_MODE = NONE; DYB_MODE = 1'b0; PPB_MODE = 1'b0; if( LOCK_REG[2] === 1'b0 ) PPB_LOCK= 1'b0; else PPB_LOCK= 1'b1; if( LOCK_REG[4] === 1'b1 ) DYB = ~(0); else DYB = 0; end end else begin current_state = RESET; reseted = 1'b0; end end ////////////////////////////////////////////////////////////////////////// //Glitch Protection: Inertial Delay does not propagate pulses <5ns ////////////////////////////////////////////////////////////////////////// always @(negedge WENeg_ipd) begin: gWE_n_f #3000 gWE_n = WENeg_ipd; end always @(posedge WENeg_ipd) begin disable gWE_n_f; gWE_n = WENeg_ipd; end always @(negedge CENeg_ipd) begin: gCE_n_f #3000 gCE_n = CENeg_ipd; end always @(posedge CENeg_ipd) begin disable gCE_n_f; gCE_n = CENeg_ipd; end always @(negedge OENeg_ipd) begin: gOE_n_f #3000 gOE_n = OENeg_ipd; end always @(posedge OENeg_ipd) begin disable gOE_n_f; gOE_n = OENeg_ipd; end always @(negedge AVDNeg_ipd) begin: gAVD_n_f #3000 gAVD_n = AVDNeg_ipd; end always @(posedge AVDNeg_ipd) begin disable gAVD_n_f; gAVD_n = AVDNeg_ipd; end always @(posedge AVDNeg_ipd) begin: tAVD_p_f #3000 tAVD_p = AVDNeg_ipd; end always @(negedge AVDNeg_ipd) begin disable tAVD_p_f; tAVD_p = AVDNeg_ipd; end ////////////////////////////////////////////////////// //Process for generating the write and read signals ///////////////////////////////////////////////////// always @(gWE_n, gCE_n, gOE_n, RESETNeg, reseted) begin if (RESETNeg !== 1'b0 && reseted === 1'b1) if (~gWE_n && ~gCE_n && gOE_n ) write = 1'b1; else if (gWE_n && ~gCE_n && gOE_n) write = 1'b0; else if (~gWE_n && gCE_n && gOE_n) write = 1'b0; if (gWE_n && ~gCE_n && ~gOE_n ) read = 1'b1; else read = 1'b0; end ///////////////////////////////////////////////////// //Process that saves current state when read signal //goes to '1' ///////////////////////////////////////////////////// always @(posedge read) begin read_rise_state = current_state; end ////////////////////////////////////////////////////////////// // Address/ Data Latch ////////////////////////////////////////////////////////////// always @(falling_edge_AVDNeg or rising_edge_AVDNeg or A_event or rising_edge_CLK or falling_edge_gWE_n or rising_edge_gWE_n or rising_edge_gCE_n or falling_edge_gCE_n) begin if ((falling_edge_gCE_n || falling_edge_gWE_n) && ~tAVD_p ) A_tmp = A[HiAddrBit:0]; if (falling_edge_AVDNeg && reseted === 1'b1 && ~CENeg) begin A_tmp = A[HiAddrBit:0]; AddrTime = $time; end if(rising_edge_AVDNeg) begin if (reseted === 1'b1 && ~gCE_n && OENeg) LatchedWrAddr = A[HiAddrBit:0] ; if (reseted === 1'b1 && ~gCE_n && gWE_n) ADDRESS_GENERATE(LatchedWrAddr,Address,AddrCom,SecAddr, BankAddr,BuffPageAddr,AddrPass); end if (A_event) begin if ( reseted === 1'b1 && ~AVDNeg && ~CENeg) begin A_tmp = A[HiAddrBit:0]; AddrTime = $time; end end if (falling_edge_AVDNeg) begin burst_rd = 0; IACC_in = 0; LATCHED = 0; RD = 0; SYN = 0; RD_MODE = NONE; end if (rising_edge_CLK && reseted===1'b1 && WENeg && OENeg && PPB_MODE == 1'b0 && DYB_MODE == 1'b0 && ~CENeg && ~AVDNeg && ~LATCHED) begin RD = 1'b1; LATCHED = 1'b1; ADDRESS_GENERATE(A_tmp,Address,AddrCom,SecAddr, BankAddr,BuffPageAddr,AddrPass); IACC_in = 1'b1; WS_CNT = 0; SYN = 1; Check_freq1 = 1; end if(rising_edge_CLK && reseted ===1'b1 && WENeg && RD && PPB_MODE == 1'b0 && DYB_MODE == 1'b0) begin burst_rd= 1'b1; Check_freq2 = 1; end if ((falling_edge_gWE_n || falling_edge_gCE_n) && reseted ===1'b1 && ~gCE_n && gOE_n && ~tAVD_p) begin ADDRESS_GENERATE(A_tmp,Address,AddrCom,SecAddr, BankAddr,BuffPageAddr,AddrPass); RD = 1'b0; end if ( rising_edge_gWE_n ) begin if (reseted === 1'b1 && ~gCE_n ) begin Data = DIn[15:0]; if (DIn[7] !== 1'bx) DataLo = DIn[7:0]; end end if ( rising_edge_gCE_n ) begin if (reseted === 1'b1 && ~gWE_n ) begin Data = DIn[15:0]; if (DIn[7] !== 1'bx) DataLo = DIn[7:0]; end end end ////////////////////////////////////////////////////////////////////////// // Timing control for the Program / Write Buffer Operation // start/ suspend/ resume ////////////////////////////////////////////////////////////////////////// event pdone_event; time elapsed_p; time duration_p; time start_p; time pow; time wrbo; always @( rising_edge_PSTART or rising_edge_reseted or rising_edge_PSUSP or rising_edge_PRES) begin: program integer i; if (rising_edge_reseted) begin PDONE = 1'b1; end else if (rising_edge_PSTART && reseted && PDONE) begin start_p = $time; elapsed_p = 0; i = WrBuffSec; if ((((~PPB[i] || ~DYB[i] || (~WP_l && Boot_Sec[i]) || ~VACC) || (ESP_ACT && ERS_QUEUE[i])) && ~PASS_ACT && ~LOCK_ACT) || (SecSi && ((WrBuffAddr[0] < 128) || (WrBuffAddr[0] >= 128 && WrBuffAddr[0] < 256 && (~WP_l || ~(LOCK_REG[0]))) || (WrBuffAddr[0] >= 256 && WrBuffAddr[0] <= BankSize))) || ( PASS_ACT && ~(LOCK_REG[2]))) begin PERR = 1'b1; PERR <= #perrpulseT_ts 1'b0; end else begin if ( WRBUFF_ACT ) duration_p = (WrBuffCnt+1) * tdevice_WRBO_ts; else duration_p = tdevice_PWO_ts; PDONE = 1'b0; ->pdone_event; end end else if (rising_edge_PSUSP && reseted && ~PDONE) begin disable pdone_process; PDONE = 1'b0; elapsed_p = $time - start_p; duration_p = duration_p - elapsed_p; end else if (rising_edge_PRES && reseted && ~PDONE) begin start_p = $time; ->pdone_event; end end always @(pdone_event) begin:pdone_process #duration_p PDONE = 1'b1; end // ////////////////////////////////////////////////////////////////////////// // // Timing control for the Erase Operations // ////////////////////////////////////////////////////////////////////////// event edone_event; integer cnt_erase = 0; time elapsed_e; time duration_e; time start_e; time seo64; always @(rising_edge_reseted or rising_edge_ESTART or rising_edge_ESUSP or rising_edge_ERES) begin: erase integer i; if (rising_edge_reseted) begin EDONE = 1'b1; end else if (reseted && EDONE && rising_edge_ESTART) begin seo64 = tdevice_SEO64_ts; cnt_erase = 0; duration_e = 0; start_e = $time; for (i=0;i<=SecNum;i=i+1) if ( ERS_QUEUE[i] && DYB[i] && PPB[i] && ( WP_l || (~Boot_Sec[i])) && VACC) begin cnt_erase = cnt_erase +1; duration_e = duration_e + seo64; end if (cnt_erase>0) begin elapsed_e = 0; EDONE = 1'b0; ->edone_event; end else begin EERR = 1'b1; EERR <= #eerrpulseT_ts 1'b0; end end else if (rising_edge_ESUSP && reseted && ~EDONE) begin disable edone_process; elapsed_e = $time - start_e; duration_e = duration_e - elapsed_e; EDONE = 1'b0; end else if(reseted && ~EDONE && rising_edge_ERES ) begin start_e = $time; EDONE = 1'b0; ->edone_event; end end always @(edone_event) begin:edone_process #(duration_e-2) EDONE = 1'b1; end // ////////////////////////////////////////////////////////////////////////// // // Main Behavior Process // // combinational process for next state generation // ////////////////////////////////////////////////////////////////////////// //WRITE CYCLE TRANSITIONS always @(falling_edge_write or negedge reseted or rising_edge_PUT_out or rising_edge_PPBE_out or rising_edge_PPBP_out or rising_edge_EDONE or falling_edge_EERR or rising_edge_SET_out or rising_edge_START_out or rising_edge_PDONE or falling_edge_PERR or rising_edge_HWResetStart or rising_edge_HWResetGlitch) begin: StateGen0 if (falling_edge_write) begin PATTERN_1 = (AddrCom == 12'h555 && DataLo == 8'hAA); PATTERN_2 = (AddrCom == 12'h2AA && DataLo == 8'h55); end if (rising_edge_HWResetGlitch) next_state = HW_RESET_UNKNOWN; else if(rising_edge_HWResetStart) next_state = HW_RESET_INIT; else begin if (reseted!=1'b1) next_state = current_state; else case (current_state) RESET : begin if (falling_edge_write) begin if (PATTERN_1) begin next_state = Z001; end else if((AddrCom == 12'h55 && (DataLo==16'h98)) && ~SecSi) next_state = CFI; end end Z001 : begin if (falling_edge_write) begin if (PATTERN_2) next_state = PREL_SETBWB; else next_state = RESET; end end CFI : begin if (falling_edge_write) begin if (DataLo == 8'hF0) begin if (PSP_ACT) next_state = PGS; else if (ESP_ACT) next_state = ESP; else if (ULBYPASS) next_state = PREL_ULBYPASS; else next_state = RESET; end end end PREL_SETBWB: begin if (falling_edge_write) begin if ((AddrCom == 12'h555) && (DataLo == 8'hE0) && ~SecSi) next_state = PREL_DYB; else if ((AddrCom==12'h555) && (DataLo==8'h50) && ~SecSi) next_state = PREL_PPBLCK; else if ((AddrCom==12'h555) && (DataLo==8'hC0) && ~SecSi) next_state = PREL_PPB; else if ((AddrCom==12'h555) && (DataLo==8'h40) && ~SecSi) next_state = PREL_LR; else if ((AddrCom==12'h555) && (DataLo==8'h20) && ~SecSi) next_state = PREL_ULBYPASS; else if ((AddrCom==12'h555) && (DataLo==8'h90) && ~SecSi) next_state = AS; else if ((AddrCom==12'h555) && (DataLo==8'hA0) && SecSi) next_state = SECSI_A0SEEN; else if ((AddrCom==12'h555) && (DataLo==8'h90) && SecSi) next_state = SECSI_EX; else if ((AddrCom==12'h555) && (DataLo==8'h60) && ~SecSi) next_state = PREL_PASS; // Password entry else if (DataLo==8'hA0) next_state = A0SEEN; else if (DataLo==8'h25) next_state = PREL_WR2BUFF; else if ((AddrCom==12'h555) && (DataLo==8'hD0) && ~SecSi) next_state = SET_CONF; else if ((AddrCom==12'h555) && (DataLo==8'hC6) && ~SecSi) next_state = RD_CONF; else if ((AddrCom==12'h555) && (DataLo==8'h80)) next_state = C8; else if ((AddrCom==12'h555) && (DataLo==8'h88)) next_state = RESET; // SecSi Entry else next_state = RESET; end end PREL_ULBYPASS : begin if (falling_edge_write) begin if (DataLo == 8'hA0) next_state = A0SEEN; else if (DataLo == 8'h80) next_state = C8_PREL; else if (DataLo == 8'h98) next_state = CFI; else if (DataLo == 8'h90) next_state = PREL_ULBYPASS_RESET; end end PREL_ULBYPASS_RESET : begin if (falling_edge_write) begin if (DataLo == 8'h00) next_state = RESET; else next_state = PREL_ULBYPASS; end end A0SEEN : begin if (falling_edge_write) next_state = PGMS; end SECSI_A0SEEN : begin if (falling_edge_write) begin if ( SecAddr == 0) next_state = PGMS; else begin if (ESP_ACT) next_state = ESP; else next_state = RESET; end end end C8 : begin if (falling_edge_write) begin if (PATTERN_1) next_state = C8_Z001; else next_state = RESET; end end C8_Z001: begin if (falling_edge_write) begin if (PATTERN_2) next_state = C8_PREL; else next_state = RESET; end end C8_PREL: begin if (falling_edge_write) begin if ((AddrCom==12'h555) && (DataLo==8'h10) && ~SecSi) next_state = ERS; else if ((DataLo==8'h30) && (BankAddr !==0 || ~SecSi)) next_state = SERS; else if (ULBYPASS) next_state = PREL_ULBYPASS; else next_state = RESET; end end SERS : begin if (falling_edge_write) begin if ((DataLo == 8'hB0) && ERS_QUEUE_B[BankAddr]) next_state = ESP; else if ((DataLo == 8'h30) && (BankAddr !==0 || ~SecSi)) next_state = SERS; else if (ULBYPASS) next_state = PREL_ULBYPASS; else next_state = RESET; end else if (rising_edge_SET_out) next_state = SERS_EXEC; end SERS_EXEC: begin if (rising_edge_EDONE || falling_edge_EERR) if (ULBYPASS) next_state = PREL_ULBYPASS; else next_state = RESET; else if (falling_edge_write && ~EERR) begin if ((DataLo == 8'hB0) && ERS_QUEUE_B[BankAddr] && (RSTMOUT_out || ~ResumeFlag)) next_state = ESPS; end end ESP : begin if (falling_edge_write) begin if ((DataLo == 8'h30) && ERS_QUEUE_B[BankAddr]) next_state = SERS_EXEC; else if (PATTERN_1) next_state = ESP_Z001; else if ((AddrCom == 12'h55) && (DataLo== 8'h98) && ~SecSi) next_state = CFI; end end ESP_Z001: begin if (falling_edge_write) begin if (PATTERN_2) next_state = ESP_PREL; else next_state = ESP; end end ESP_PREL: begin if (falling_edge_write) begin if (DataLo == 8'h25) next_state = PREL_WR2BUFF; else if ((AddrCom==12'h555) && (DataLo==8'hE0) && ~SecSi) next_state = PREL_DYB; else if ((AddrCom==12'h555) && (DataLo==8'hC0) && ~SecSi) next_state = PREL_PPB; else if ((AddrCom==12'h555) && (DataLo==8'h90) && ~SecSi) next_state = AS; else if ((AddrCom==12'h555) && (DataLo==8'hA0) && SecSi) next_state = SECSI_A0SEEN; else if ((AddrCom==12'h555) && (DataLo==8'h90) && SecSi) next_state = SECSI_EX; else if ((AddrCom==12'h555) && (DataLo == 8'h88) && ~(ERS_QUEUE[0])) next_state = ESP; //SecSi Entry else next_state = ESP; end end PREL_WR2BUFF: begin if (falling_edge_write) begin if ((SecAddr == WrBuffSec) && (DataLo < 32)) next_state = WR2BUFF_0; else next_state = WR2BUFF_AB; end end WR2BUFF_0 : begin if (falling_edge_write) begin if ((SecAddr == WrBuffSec) && (WrCnt >0)) next_state = WR2BUFF_CNT; else if ((SecAddr == WrBuffSec) && (WrCnt ==0)) next_state = PREL_PRFLASH; else next_state = WR2BUFF_AB; end end WR2BUFF_CNT : begin if (falling_edge_write) begin if ((BuffPageAddr == WrBuffPage) && (Address >= PrevBuffAd) && (WrCnt >0)) next_state = WR2BUFF_CNT; else if ((BuffPageAddr == WrBuffPage) && (Address >= PrevBuffAd) && (WrCnt ==0)) next_state = PREL_PRFLASH; else next_state = WR2BUFF_AB; end end PREL_PRFLASH : begin if (falling_edge_write) begin if ((SecAddr==WrBuffSec) && (DataLo==8'h29)) next_state = PGMS; else next_state = WR2BUFF_AB; end end PGMS: begin if (falling_edge_write && ~PERR) begin if ((DataLo == 16'hB0) && (RSTMOUT_out || ~ResumeFlag)) next_state = PGSPS; end else if (falling_edge_PERR || rising_edge_PDONE) begin if ( ESP_ACT ) next_state = ESP; else if ( ULBYPASS ) next_state = PREL_ULBYPASS; else if ( LOCK_ACT ) next_state = PREL_LR; else if ( PASS_ACT ) next_state = PREL_PASS; else next_state = RESET; end end PGS: begin if (falling_edge_write) begin if (DataLo == 16'h30) next_state = PGMS; else if (PATTERN_1) next_state = PGS_Z001; else if ((AddrCom == 16'h55) && (DataLo== 16'h98) && ~SecSi) next_state = CFI; end end PGS_Z001: begin if (falling_edge_write) begin if (PATTERN_2) next_state = PGS_PREL; else next_state = PGS; end end PGS_PREL: begin if (falling_edge_write) begin if ((AddrCom==12'h555) && (DataLo==8'hE0) && ~SecSi) next_state = PREL_DYB; else if ((AddrCom==12'h555) && (DataLo==8'hC0) && ~SecSi) next_state = PREL_PPB; else if ((AddrCom==12'h555) && (DataLo== 8'h90) && ~SecSi) next_state = AS; else if ((AddrCom==12'h555) && (DataLo==8'h90) && SecSi) next_state = SECSI_EX; else if ((AddrCom==12'h555) && (DataLo == 8'h88) && (WrBuffSec !==0)) next_state = PGS; //SecSi Entry else next_state = PGS; end end WR2BUFF_AB: begin if (falling_edge_write) begin if (PATTERN_1) next_state = WR2BUFF_AB_Z001; end end WR2BUFF_AB_Z001 : begin if (falling_edge_write) begin if (PATTERN_2) next_state = WR2BUFF_AB_PREL; else next_state = WR2BUFF_AB; end end WR2BUFF_AB_PREL : begin if (falling_edge_write) begin if ((AddrCom == 12'h555) && (DataLo == 8'hF0)) begin if (ESP_ACT) next_state = ESP; else next_state = RESET; end else next_state = WR2BUFF_AB; end end SET_CONF : begin if (falling_edge_write) begin if (DataLo == 8'hF0) next_state = RESET; else if (AddrCom == 12'h000) next_state = SET_CONF1; // set conf reg else next_state = SET_CONF; end end SET_CONF1 : begin if (falling_edge_write) begin if (DataLo == 8'hF0) next_state = RESET; else if (AddrCom == 12'h001) next_state = SET_CONF; // set conf reg else next_state = SET_CONF; end end RD_CONF : begin if (falling_edge_write) begin if (DataLo == 8'hF0) next_state = RESET; else next_state = RD_CONF; end end PREL_PASS : begin if (falling_edge_write) begin if (DataLo == 8'hA0) next_state = PASS_A0SEEN; else if (DataLo == 8'h90) next_state = PASS_EX; else if ((AddrCom == 12'h000) && (DataLo== 8'h25)) next_state = PASS_UN_Z001; end end PASS_A0SEEN : begin if (falling_edge_write) next_state = PGMS; end PASS_EX : begin if (falling_edge_write) begin if (DataLo == 8'h00) next_state = RESET; // exit password else next_state = PREL_PASS; end end PASS_UN_Z001 : begin if (falling_edge_write) begin if ((DataLo == 8'h03) && (AddrCom == 12'h000)) next_state = PASS_UN_PREL; else next_state = PREL_PASS; end end PASS_UN_PREL : begin if (falling_edge_write) next_state = PASS_UN1; end PASS_UN1 : begin if (falling_edge_write) next_state = PASS_UN2; end PASS_UN2 : begin if (falling_edge_write) next_state = PASS_UN3; end PASS_UN3 : begin if (falling_edge_write) next_state = PASS_UN4; end PASS_UN4 : begin if (falling_edge_write) begin if ((AddrCom == 12'h000) && (DataLo == 8'h29)) next_state = PASS_UN_W; else next_state = PREL_PASS; end end PREL_LR : begin if (falling_edge_write) begin if (DataLo == 8'hA0) next_state = LR_A0SEEN; else if (DataLo == 8'h90) next_state = LR_PREL_EX; end end LR_A0SEEN : begin if (falling_edge_write) begin if (AddrCom == 12'h00) next_state = PGMS; // write to LR else next_state = PREL_LR; end end LR_PREL_EX : begin if (falling_edge_write) begin if (DataLo == 8'h00) next_state = RESET; else next_state = PREL_LR; end end PREL_PPB : begin if (falling_edge_write) begin if (DataLo == 8'hA0) next_state = PPB_PREL_PR; else if (DataLo == 8'h80) next_state = PPB_PREL_ER; else if (DataLo == 8'h90) next_state = PPB_PREL_EX; end end PPB_PREL_PR : begin if (falling_edge_write) begin if ((DataLo == 8'h00) && (~ESP_ACT || ~(ERS_QUEUE[SecAddr])) && (~PSP_ACT || (SecAddr !== WrBuffSec ))) next_state = PPB_PGMS; else next_state = PREL_PPB; end end PPB_PREL_ER : begin if (falling_edge_write) begin if ((DataLo == 8'h30) && ~ESP_ACT && ~PSP_ACT ) next_state = PPB_ERS; else next_state = PREL_PPB; end end PPB_PREL_EX : begin if (falling_edge_write) begin if (DataLo == 8'h00) begin if (PSP_ACT) next_state = PGS; else if (ESP_ACT) next_state = ESP; else next_state = RESET; end else next_state = PREL_PPB; end end PREL_PPBLCK : begin if (falling_edge_write) begin if (DataLo == 8'hA0) next_state = PPBLCK_PREL_ST; else if (DataLo == 8'h90) next_state = PPBLCK_PREL_EX; end end PPBLCK_PREL_ST : begin if (falling_edge_write) begin if (DataLo == 8'h00) next_state = PREL_PPBLCK; // set PPB Lock Bit else next_state = PREL_PPBLCK; end end PPBLCK_PREL_EX : begin if (falling_edge_write) begin if (DataLo == 8'h00) next_state = RESET; else next_state = PREL_PPBLCK; end end PREL_DYB : begin if (falling_edge_write) begin if (DataLo == 8'hA0) next_state = DYB_PREL_ST; else if (DataLo == 8'h90) next_state = DYB_PREL_EX; end end DYB_PREL_ST : begin if (falling_edge_write) next_state = PREL_DYB; // set/reset DYB end DYB_PREL_EX : begin if (falling_edge_write) begin if (DataLo == 8'h00) begin if (PSP_ACT) next_state = PGS; else if (ESP_ACT) next_state = ESP; else next_state = RESET; end else next_state = PREL_DYB; end end AS : begin if (falling_edge_write) begin if (DataLo == 8'hF0) begin if (PSP_ACT) next_state = PGS; else if (ESP_ACT) next_state = ESP; else next_state = RESET; end end end SECSI_EX : begin if (falling_edge_write) begin if (PSP_ACT) next_state = PGS; else if (ESP_ACT) next_state = ESP; else next_state = RESET; end end PPB_PGMS : begin if (rising_edge_PPBP_out) next_state = PREL_PPB; end PPB_ERS : begin if (rising_edge_PPBE_out) next_state = PREL_PPB; end PASS_UN_W: begin if (rising_edge_PUT_out) next_state = PREL_PASS; end ERS: begin if (rising_edge_EDONE || falling_edge_EERR) if (ULBYPASS) next_state = PREL_ULBYPASS; else next_state = RESET; end ESPS: begin if (rising_edge_START_out) next_state = ESP; end PGSPS: begin if (rising_edge_START_out) next_state = PGS; end HW_RESET_UNKNOWN : begin end HW_RESET_INIT : begin end endcase end end reg FlagOE=1; reg FlagOE2 = 1; reg FlagWrite=1; reg FlagPDONErising =1; reg FlagPDONEfalling=1; reg FlagEDONEfalling=1; reg FlagEDONErising =1; reg FlagSET_out =1; reg FlagSTART_out =1; reg FlagPUT_out =1; reg FlagPPBP_out =1; reg FlagPPBE_out =1; /////////////////////////////////////////////////////////////////////////// //FSM Output generation and general funcionality /////////////////////////////////////////////////////////////////////////// always @( oe or falling_edge_write or rising_edge_PPBP_out or EERR or rising_edge_EDONE or falling_edge_EDONE or rising_edge_SET_out or rising_edge_START_out or rising_edge_PDONE or falling_edge_PDONE or rising_edge_burst_rd or rising_edge_IACC_out or falling_edge_RESETNeg or falling_edge_RST or rising_edge_PPBE_out or rising_edge_CLK or rising_edge_gCE_n or rising_edge_OENeg or rising_edge_PUT_out) begin: Output integer i,j; begin if (oe) begin ONE_READ = 1'b0; end //Output Disable Control if (rising_edge_OENeg) DOut_zd = 16'bz; //Output Disable Control if (rising_edge_gCE_n) begin DOut_zd = 16'bZ; DOut_burst = 16'bZ; end // Hardware RESET cycle //Output Disable Control if(falling_edge_RESETNeg) begin DOut_zd = 16'bZ; DOut_burst = 16'bZ; end if (falling_edge_RST && ~RESETNeg) begin RD_MODE = NONE; CONF_REG0 = 16'b0010111111001000; CONF_REG1 = 16'b1111111111101111; SYN = 1'b0; if( ~(LOCK_REG[2])) PPB_LOCK = 1'b0; else PPB_LOCK = 1'b1; if (LOCK_REG[4]) DYB = ~(0); else DYB = 0; ESP_ACT = 1'b0; ULBYPASS = 1'b0; PSP_ACT = 1'b0; PASS_ACT = 1'b0; LOCK_ACT = 1'b0; SecSi = 1'b0; end if (falling_edge_write) begin PATTERN_1 = (AddrCom == 12'h555 && DataLo == 8'hAA); PATTERN_2 = (AddrCom == 12'h2AA && DataLo == 8'h55); end //Initializing burst parameters if (rising_edge_burst_rd) begin BurstAddr = Address; BurstSec = SecAddr; if (CONF_REG0[2:0] == 2 ) BurstLength = 8; else if (CONF_REG0[2:0] == 3) BurstLength = 16; else if (CONF_REG0[2:0] == 4) BurstLength = 32; else BurstLength = 0; RdCnt = BurstLength; WS_CNT = 8*CONF_REG1[0] + CONF_REG0[13:11] + 2; if (8*CONF_REG1[0] + CONF_REG0[13:11] >=8) WS_CNT = WS_CNT - 2; WS_CNT_f = WS_CNT; if (WS_CNT <= 9) HI_FREQ = 0; else HI_FREQ = 1; DelayCyc_CNT = (BurstAddr % 8); if (WS_CNT >= 3 && WS_CNT <= 8) DelayCyc_CNT = DelayCyc_CNT - (9 - WS_CNT); else if (WS_CNT < 3) DelayCyc_CNT = 0; CONF_REG_8 = CONF_REG0[8]; if ( DelayCyc_CNT < 0 ) DelayCyc_CNT = 0; if ((BurstAddr % 128 > 120 || (BurstLength != 8 && BurstAddr % 128 == 120)) && WS_CNT > 9 && (CONF_REG0[2:0] == 0 || (CONF_REG0[2:0] <= 4 && CONF_REG0[3] == 0))) DelayCyc_CNT = DelayCyc_CNT + 1; DelayCycSwitch = 0; CLK_PATH_EN = 1'b0; INITIAL_WAIT = ( WS_CNT > 2); INITIAL_ACCESS = ( WS_CNT <= 2); BOUNDARY_CROSS = 1'b0; NO_PROGRESS = 1'b0; BURST_END = 1'b0; Prior_IACC = 1'b1; IN_W_ELAPSED = ( WS_CNT <= 2); DOut_burst = 16'bz; end if (reseted === 1'b1) case (current_state) RESET : begin //reading array data if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; ESP_ACT = 1'b0; ULBYPASS = 1'b0; SET_in = 1'b0; PPBP_in = 1'b0; PPBE_in = 1'b0; PUT_in = 1'b0; START_in = 1'b0; ResumeFlag = 1'b0; if ((AddrCom==12'h55) && (DataLo==8'h98) && ~SecSi ) BankCFIAddr = BankAddr; end else if (oe && FlagOE ) begin FlagOE = 1'b0; READ_ARRAY_DATA(Address,BankAddr,SecAddr,SecSi,ONE_READ); end end CFI : begin if (oe && FlagOE ) begin FlagOE = 1'b0; if ( BankAddr == BankCFIAddr ) begin if (((Address % (BankSize+1) >= 8'h10) && (Address % (BankSize+1) <= 8'h3C)) || ((Address % (BankSize+1) >= 8'h40) && (Address % (BankSize+1) <= 8'h67))) DOut_zd = CFIMem[Address % (BankSize+1)]; else begin DOut_zd = 16'bz; // error CFI Address out of range $display("Invalid CFI query address"); end ONE_READ = 1'b1; end else begin if ( ESP_ACT && ERS_QUEUE[SecAddr]) begin //////////////////////////////////////////////////// //erase suspend active //////////////////////////////////////////////////// if (read) begin status[7] = 1'b1; // status[6] No toggle status[5] = 1'b0; status[2] = ~ status[2]; // toggle end DOut_zd[7:0] = status; DOut_zd[15:8] = 8'bz; ONE_READ = 1'b1; end else if ( ~PSP_ACT || SecAddr !== WrBuffSec ) READ_ARRAY_DATA(Address,BankAddr, SecAddr,SecSi,ONE_READ); else ONE_READ = 1'b1; end end end PREL_SETBWB: if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ((AddrCom==12'h555) && (DataLo==8'hE0) && ~SecSi ) begin RD_MODE = NONE; DYB_MODE = 1'b1; BankDYBAddr = BankAddr; SecDYBAddr = SecAddr; end else if (( AddrCom==12'h555) && (DataLo==8'hC0) && ~SecSi) begin RD_MODE = NONE; PPB_MODE = 1'b1; BankPPBAddr = BankAddr; SecPPBAddr = SecAddr; end else if (( AddrCom==12'h555) && (DataLo==8'h50) && ~SecSi) BankPPBLAddr = BankAddr; else if (( AddrCom==12'h555) && (DataLo==8'h40) && ~SecSi) LOCK_ACT = 1'b1; else if (( AddrCom==12'h555) && (DataLo==8'h20) && ~SecSi) begin PrgBank = -1; ULBYPASS = 1'b1; end else if (( AddrCom==12'h555) && (DataLo==8'h90) && ~SecSi) BankASAddr = BankAddr; else if ((AddrCom==12'h555) && (DataLo==8'h60) && ~SecSi) PASS_ACT = 1'b1; else if (DataLo==8'h25) begin PrgBank = BankAddr; WrBuffSec = SecAddr; end else if (( AddrCom==12'h555) && (DataLo==8'h88)) SecSi = 1'b1; // SecSi Entry end PREL_ULBYPASS: if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (DataLo == 8'h98) BankCFIAddr = BankAddr; end else if (oe && FlagOE ) begin FlagOE = 1'b0; READ_ARRAY_DATA(Address,BankAddr,SecAddr,SecSi,ONE_READ); end A0SEEN: if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; PSTART = 1'b1; PSTART <= #1 1'b0; WRBUFF_ACT = 1'b0; WrBuffData[0] = Data; WrBuffAddr[0] = Address; WrBuffSec = SecAddr; WrBuffCnt = 0; PrgBank = BankAddr; WP_l = WPNeg; temp = DataLo; status[7] = ~ temp[7]; end SECSI_A0SEEN: if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ( SecAddr == 0 ) begin PSTART = 1'b1; PSTART <= #1 1'b0; WRBUFF_ACT = 1'b0; WrBuffData[0] = Data; WrBuffAddr[0] = Address; WrBuffSec = SecAddr; WrBuffCnt = 0; PrgBank = BankAddr; WP_l = WPNeg; temp = DataLo; status[7] = ~ temp[7]; end end C8_PREL: if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ((AddrCom==12'h555) && (DataLo==8'h10) && ~SecSi) begin ESTART = 1'b1; ESTART <= #1 1'b0; ESUSP = 1'b0; ERES = 1'b0; ERS_QUEUE = ~(0); ERS_QUEUE_B = ~(0); status = 8'b0; WP_l = WPNeg; end else if ((DataLo==8'h30) && ((SecAddr!==0) || ~SecSi)) begin ERS_QUEUE = 0; ERS_QUEUE_B = 0; ERS_QUEUE[SecAddr] =1'b1; ERS_QUEUE_B[BankAddr]=1'b1; SET_in =1'b1; WP_l = WPNeg; end end ERS : begin // reading status enabled //////////////////////////////////////////////////////////- // read status / embeded erase algorithm - Chip Erase //////////////////////////////////////////////////////////- if (oe && FlagOE ) begin FlagOE = 1'b0; if (read) begin status[7] = 1'b0; status[6] = ~ status[6]; //toggle status[5] = 1'b0; status[3] = 1'b1; status[2] = ~ status[2]; //toggle end DOut_zd[7:0] = status; DOut_zd[15:8]=8'bz; ONE_READ =1'b1; end //ERS state, EDONE falling edge, EDONE rising edge if (EERR!=1'b1) begin if (falling_edge_EDONE && FlagEDONEfalling)//falling edge begin FlagEDONEfalling=1'b0; for (i=0;i<=SecNum;i=i+1) begin if (PPB[i] && DYB[i] && (WP_l || ~( Boot_Sec[i])) && VACC) for (j =i*(SecSize64+1); j<=i*(SecSize64+1) + SecSize64; j=j+1) Mem[j] = -1; end end if (rising_edge_EDONE && FlagEDONErising)//rising edge begin FlagEDONErising=1'b0; for (i=0;i<=SecNum;i=i+1) begin if (PPB[i] && DYB[i] && (WP_l || ~( Boot_Sec[i])) && VACC) for (j =i*(SecSize64+1); j<=i*(SecSize64+1) + SecSize64; j=j+1) Mem[j] = MaxData; end end end end SERS : begin //SERS state, SET_out if (rising_edge_SET_out && FlagSET_out ) begin FlagSET_out = 1'b0; SET_in = 1'b0; START_in = 1'b0; ESUSP = 1'b0; ERES = 1'b0; ESTART = 1'b1; ESTART <= #1 1'b0; end if (oe && FlagOE ) begin FlagOE = 1'b0; if ( ERS_QUEUE_B[BankAddr] ) begin //////////////////////////////////////////////////////// //read status - sector erase timeout //////////////////////////////////////////////////////// if (read) begin status[3] = 1'b0; status[7] = 1'b1; end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; ONE_READ = 1'b1; end else begin READ_ARRAY_DATA(Address,BankAddr,SecAddr ,SecSi,ONE_READ); end end else if (falling_edge_write && FlagWrite) begin FlagWrite = 1'b0; if ((DataLo == 8'hB0) && ERS_QUEUE_B[BankAddr]) begin BankErSuspAddr=BankAddr; //erasure must ERES = 1'b0; //begin before SET_in = 1'b0; //suspending ESTART = 1'b1; ESTART <= #1 1'b0; ESUSP = #1 1'b1; ESUSP <= #2 1'b0; end else if ((DataLo == 8'h30) && (SecAddr!==0 || ~SecSi)) begin SET_in = 1'b0; SET_in <= #1 1'b1; //one more timeout ERS_QUEUE[SecAddr] =1'b1; ERS_QUEUE_B[BankAddr] =1'b1; end else begin SET_in =1'b0; end end end ESPS : begin //ESPS state, START_out if (rising_edge_START_out && FlagSTART_out) begin FlagSTART_out = 1'b0; ESP_ACT = 1'b1; START_in = 1'b0; SET_in = 1'b0; end if (oe && FlagOE ) begin FlagOE = 1'b0; if ( ERS_QUEUE_B[BankAddr]) begin //////////////////////////////////////////////////////// //read status / erase suspend timeout - stil erasing //////////////////////////////////////////////////////// if (read) begin if ( ERS_QUEUE[SecAddr]) begin status[7] = 1'b0; status[2] = ~ status[2]; //toggle end else status[7] = 1'b1; status[6] = ~ status[6]; //toggle status[5] = 1'b0; status[3] = 1'b1; end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; ONE_READ = 1'b1; end else READ_ARRAY_DATA(Address,BankAddr,SecAddr ,SecSi,ONE_READ); end end SERS_EXEC: begin // reading data && status enabled if (oe && FlagOE ) begin FlagOE = 1'b0; if ( ERS_QUEUE_B[BankAddr]) begin //////////////////////////////////////////////////// //read status Erase Busy //////////////////////////////////////////////////// if (read) begin if (ERS_QUEUE[SecAddr]) begin status[7] = 1'b0; status[2] = ~ status[2]; //toggle end else status[7] = 1'b1; status[6] = ~ status[6]; //toggle status[5] = 1'b0; status[3] = 1'b1; end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; ONE_READ = 1'b1; end else READ_ARRAY_DATA(Address,BankAddr,SecAddr ,SecSi,ONE_READ); end else if (falling_edge_write && FlagWrite) begin FlagWrite =1'b0; if ((DataLo == 8'hB0) && ERS_QUEUE_B[BankAddr] && (RSTMOUT_out || ~ResumeFlag)) begin ERES = 1'b0; ESUSP = 1'b1; ESUSP <= #1 1'b0; START_in = 1'b1; end end //SERS_EXEC state, EDONE falling edge, EDONE rising edge if (EERR!=1'b1) begin if (falling_edge_EDONE && FlagEDONEfalling) begin FlagEDONEfalling =1'b0; for (i=0;i<=SecNum;i=i+1) begin if (ERS_QUEUE[i] && PPB[i] && DYB[i] && (WP_l || ~( Boot_Sec[i])) && VACC) for (j =i*(SecSize64+1); j<=i*(SecSize64+1) + SecSize64; j=j+1) Mem[j] = -1; end end if (rising_edge_EDONE && FlagEDONErising) begin FlagEDONErising =1'b0; for (i=0;i<=SecNum;i=i+1) begin if (ERS_QUEUE[i] && PPB[i] && DYB[i] && (WP_l || ~( Boot_Sec[i])) && VACC) for (j =i*(SecSize64+1); j<=i*(SecSize64+1) + SecSize64; j=j+1) Mem[j] = MaxData; end end end end ESP : begin //////////////////////////////////////////////////////////// //read //////////////////////////////////////////////////////////// if (oe && FlagOE ) begin FlagOE = 1'b0; if ( ~(ERS_QUEUE[SecAddr]) ) begin READ_ARRAY_DATA(Address,BankAddr,SecAddr ,SecSi,ONE_READ); end else begin //////////////////////////////////////////////////////// //read status //////////////////////////////////////////////////////// if (read) begin status[7] = 1'b1; // status[6] No toggle status[5] = 1'b0; status[2] = ~ status[2]; // toggle end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; ONE_READ = 1'b1; end end else if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ((DataLo == 8'h30) && ERS_QUEUE_B[BankAddr]) begin ERES = 1'b1; ERES <= #1 1'b0; RSTMOUT_in = 1'b0; RSTMOUT_in <= #1 1'b1; ESP_ACT = 1'b0; ResumeFlag = 1'b1; end else if ((AddrCom==12'h55) && (DataLo==8'h98) && ~SecSi ) BankCFIAddr = BankAddr; end end ESP_PREL: if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (DataLo == 8'h25) begin PrgBank = BankAddr; WrBuffSec = SecAddr; end else if ((AddrCom==12'h555) && (DataLo==8'hE0) && ~SecSi) begin RD_MODE = NONE; DYB_MODE = 1'b1; BankDYBAddr = BankAddr; SecDYBAddr = SecAddr; end else if ((AddrCom==12'h555) && (DataLo==8'hC0) && ~SecSi) begin RD_MODE = NONE; PPB_MODE = 1'b1; BankPPBAddr = BankAddr; SecPPBAddr = SecAddr; end else if ((AddrCom==12'h555) && (DataLo==8'h90) && ~SecSi) BankASAddr = BankAddr; else if ((AddrCom==12'h555) && (DataLo ==8'h88) && ~(ERS_QUEUE[0])) SecSi = 1'b1; //SecSi Entry end PREL_WR2BUFF: if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ( SecAddr == WrBuffSec && DataLo < 32 ) begin WrCnt = DataLo; WrBuffCnt = DataLo; end else begin temp = DataLo; status[7] = ~ temp[7]; end end WR2BUFF_0 : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (SecAddr == WrBuffSec && WrCnt > 0 ) begin WrBuffPage = BuffPageAddr; WrBuffAddr[WrCnt] = Address; WrBuffData[WrCnt] = Data; WrCnt = WrCnt-1; PrevBuffAd = Address; end else if ( SecAddr == WrBuffSec && WrCnt == 0 ) begin WrBuffAddr[WrCnt] = Address; WrBuffData[WrCnt] = Data; end else begin temp = DataLo; status[7] = ~ temp[7]; end end WR2BUFF_CNT : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ( BuffPageAddr == WrBuffPage && Address >= PrevBuffAd && WrCnt > 0 ) begin WrBuffAddr[WrCnt] = Address; WrBuffData[WrCnt] = Data; WrCnt = WrCnt-1; PrevBuffAd = Address; end else if ( BuffPageAddr == WrBuffPage && Address >= PrevBuffAd && WrCnt == 0 ) begin WrBuffAddr[WrCnt] = Address; WrBuffData[WrCnt] = Data; end else begin temp = DataLo; status[7] = ~ temp[7]; end end PREL_PRFLASH : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (SecAddr == WrBuffSec && DataLo==8'h29) begin WRBUFF_ACT = 1'b1; WP_l = WPNeg; PSTART = 1'b1; PSTART <= #1 1'b0; end temp = DataLo; status[7] = ~ temp[7]; end PGSPS : begin //PGSPS state, START_out if (rising_edge_START_out && FlagSTART_out) begin FlagSTART_out =1'b0; START_in = 1'b0; PSP_ACT = 1'b1; end if (oe && FlagOE ) begin FlagOE = 1'b0; // reading data && status enabled if ( BankAddr == PrgBank ) begin //////////////////////////////////////////////////////// //read status //////////////////////////////////////////////////////// if (read) begin status[6] = ~ status[6]; //toggle status[5] = 1'b0; //status[2] no toggle status[1] = 1'b0; end DOut_zd[7:0]= status; if ( SecAddr == WrBuffSec || LOCK_ACT || PASS_ACT) DOut_zd[7] = status[7]; else DOut_zd[7] = ~ status[7]; DOut_zd[15:8]= 8'bz; ONE_READ = 1'b1; end else if ( ~ESP_ACT || ~(ERS_QUEUE[SecAddr]) ) READ_ARRAY_DATA(Address,BankAddr, SecAddr ,SecSi,ONE_READ); else begin //////////////////////////////////////////////////////// //erase suspend active //////////////////////////////////////////////////////// if (read) begin status[7] = 1'b1; // status[6] No toggle status[5] = 1'b0; status[2] = ~ status[2]; // toggle end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; ONE_READ = 1'b1; end end end PGMS: begin if (oe && FlagOE ) begin FlagOE = 1'b0; if ( BankAddr == PrgBank) begin //////////////////////////////////////////////////////// //read status //////////////////////////////////////////////////////// if (read) begin status[6] = ~ status[6]; //toggle status[5] = 1'b0; //status[2] no toggle status[1] = 1'b0; end DOut_zd[7:0]= status; if ( SecAddr == WrBuffSec || LOCK_ACT || PASS_ACT ) DOut_zd[7] = status[7]; else DOut_zd[7] = ~ status[7]; DOut_zd[15:8]= 8'bz; ONE_READ = 1'b1; end else if ( ~ESP_ACT || ~(ERS_QUEUE[SecAddr]) ) begin ONE_READ = 1'b1; if (~LOCK_ACT) begin READ_ARRAY_DATA(Address,BankAddr, SecAddr ,SecSi,ONE_READ); ONE_READ = 1'b0; end end else begin //////////////////////////////////////////////////////// //erase suspend active //////////////////////////////////////////////////////// if (read) begin status[7] = 1'b1; // status[6] No toggle status[5] = 1'b0; status[2] = ~ status[2]; // toggle end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; ONE_READ = 1'b1; end end //PGMS state, PDONE rising edge, PDONE falling edge if (PERR != 1'b1) begin if (falling_edge_PDONE && FlagPDONEfalling)//falling begin FlagPDONEfalling=1'b0; x = WrBuffSec; for(i=WrBuffCnt;i>=0;i=i-1) begin new_int = WrBuffData[i]; old_int = -1; if (PASS_ACT ) old_int = Password[WrBuffAddr[i]]; else if (LOCK_ACT) begin if (LOCK_REG[0]=== 1'bx) old_int =-1; else old_int =LOCK_REG; end else if( SecSi && (x==0) && (WrBuffAddr[0]<=8'hFF) && (WrBuffAddr[0]>=8'h80)) old_int =SecSiMem[WrBuffAddr[i]]; else old_int =Mem[WrBuffAddr[i]]; 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 WrBuffData[i]= new_int; end end if (PASS_ACT && LOCK_REG[2]) Password[WrBuffAddr[0]] = -1; else if (LOCK_ACT) begin if ( new_bit[1] || new_bit[2]) LOCK_REG[4:0] = 5'bx; end else if ( SecSi && (x==0) && (WrBuffAddr[0]<=8'hFF) && WrBuffAddr[0]>=8'h80 && LOCK_REG[0]) for(i=WrBuffCnt;i>=0;i=i-1) SecSiMem[WrBuffAddr[i]] = -1; else if(( PPB[x] && DYB[x] && (WP_l || ~(Boot_Sec[x])) && VACC) && ( ~ESP_ACT || ~(ERS_QUEUE[x]))) for(i=WrBuffCnt;i>=0;i=i-1) Mem[WrBuffAddr[i]] = -1; end if (rising_edge_PDONE && FlagPDONErising)//rising begin FlagPDONErising = 1'b0; WRBUFF_ACT = 1'b0; x = WrBuffSec; if (PASS_ACT && LOCK_REG[2]) begin Password[WrBuffAddr[0]] = WrBuffData[0]; WrBuffData[0] = -1; end else if (LOCK_ACT) begin if ( new_bit[1] || new_bit[2]) LOCK_REG[4:0] = new_bit[4:0]; end else if ( SecSi && (x==0) && (WrBuffAddr[0]<=8'hFF) && WrBuffAddr[0]>=8'h80 && LOCK_REG[0]) begin for(i=WrBuffCnt;i>=0;i=i-1) begin SecSiMem[WrBuffAddr[i]] = WrBuffData[i]; WrBuffData[i] = -1; end end else if(( PPB[x] && DYB[x] && (WP_l || ~(Boot_Sec[x])) && VACC) && ( ~ESP_ACT || ~(ERS_QUEUE[x]))) begin for(i=WrBuffCnt;i>=0;i=i-1) begin Mem[WrBuffAddr[i]] = WrBuffData[i]; WrBuffData[i] = -1; end end end end if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ((DataLo == 8'hB0) && (RSTMOUT_out || ~ResumeFlag)) begin PRES = 1'b0; PSUSP = 1'b1; PSUSP <= #1 1'b0; START_in = 1'b1; end end end PGS: begin if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (DataLo == 16'h30) begin PRES = 1'b1; PRES <= #1 1'b0; RSTMOUT_in = 1'b0; RSTMOUT_in <= #1 1'b1; PSP_ACT = 1'b0; ResumeFlag = 1'b1; end else if ((AddrCom==12'h55) && (DataLo==8'h98) && ~SecSi ) BankCFIAddr = BankAddr; end else if (oe && FlagOE) begin FlagOE =1'b0; // reading data && status enabled if ( SecAddr !== WrBuffSec ) if ( ESP_ACT && ERS_QUEUE[SecAddr] ) begin //////////////////////////////////////////////////// //read status //////////////////////////////////////////////////// if (read) begin status[7] = 1'b1; // status[6] No toggle status[5] = 1'b0; status[2] = ~ status[2]; // toggle end DOut_zd[7:0]= status; DOut_zd[15:8]=8'bz; ONE_READ = 1'b1; end else READ_ARRAY_DATA(Address,BankAddr, SecAddr ,SecSi,ONE_READ); else ONE_READ=1'b1; end end PGS_PREL: if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (( AddrCom == 12'h555) && (DataLo==8'hE0) && ~SecSi) begin RD_MODE = NONE; DYB_MODE = 1'b1; BankDYBAddr = BankAddr; SecDYBAddr = SecAddr; end else if (( AddrCom==12'h555) && (DataLo==12'hC0) && ~SecSi) begin RD_MODE = NONE; PPB_MODE = 1'b1; BankPPBAddr = BankAddr; SecPPBAddr = SecAddr; end else if (( AddrCom==12'h555) && (DataLo==12'h90) && ~SecSi) BankASAddr = BankAddr; else if (( AddrCom==12'h555) && (DataLo == 12'h88) && (WrBuffSec !==0)) SecSi = 1'b1; //SecSi Entry end WR2BUFF_AB: begin if (oe && FlagOE ) begin FlagOE = 1'b0; if ( BankAddr == PrgBank ) begin //////////////////////////////////////////////////////// //read status //////////////////////////////////////////////////////// if (read) begin status[7] = status[7]; status[6] = ~ status[6]; status[5] = 1'b0; status[1] = 1'b1; end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; ONE_READ = 1'b1; end else if ( ~ESP_ACT || ~(ERS_QUEUE[SecAddr])) READ_ARRAY_DATA(Address,BankAddr, SecAddr ,SecSi,ONE_READ); else begin //////////////////////////////////////////////////////// //erase suspend active //////////////////////////////////////////////////////// if (read) begin status[7] = 1'b1; // status[6] No toggle status[5] = 1'b0; status[2] = ~ status[2]; // toggle end DOut_zd[7:0]= status; DOut_zd[15:8]=8'bz; ONE_READ = 1'b1; end end end SET_CONF : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (( DataLo !== 8'hF0) && (AddrCom == 12'h000)) CONF_REG0 = Data; end SET_CONF1 : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (( DataLo !== 8'hF0) && (AddrCom == 12'h001)) CONF_REG1 = Data; end RD_CONF : begin if (oe && FlagOE ) begin FlagOE = 1'b0; ONE_READ = 1'b1; if ( Address == 12'h000) DOut_zd = CONF_REG0; else if ( Address == 12'h001) DOut_zd = CONF_REG1; end end PREL_PASS : begin if (oe && FlagOE ) begin FlagOE = 1'b0; if ( BankAddr == 0 ) begin if ( LOCK_REG[2]) DOut_zd = Password[AddrPass]; else DOut_zd = MaxData; ONE_READ = 1'b1; end else READ_ARRAY_DATA(Address,BankAddr,SecAddr ,SecSi,ONE_READ); end end PASS_A0SEEN : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; PSTART = 1'b1; PSTART <= #1 1'b0; WRBUFF_ACT = 1'b0; WrBuffData[0] = Data; WrBuffAddr[0] = AddrPass; WrBuffSec = 0; WrBuffCnt = 0; PrgBank = 0; temp = DataLo; status[7] = ~ temp[7]; end PASS_EX : begin if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (DataLo == 8'h00) PASS_ACT = 1'b0; end end PASS_UN_Z001 : begin if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ((DataLo == 8'h03) && (AddrCom == 12'h000)) for (i=0;i<=PWLength;i=i+1) PASS_TEMP[i] = MaxData; end end PASS_UN_PREL : begin if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; PASS_TEMP[AddrPass] = Data; end end PASS_UN1 : begin if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; PASS_TEMP[AddrPass] = Data; end end PASS_UN2 : begin if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; PASS_TEMP[AddrPass] = Data; end end PASS_UN3 : begin if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; PASS_TEMP[AddrPass] = Data; end end PASS_UN4 : begin if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (( AddrCom == 12'h000) && (DataLo == 8'h29)) PASS_UNLCK = 1'b1; for (i=0;i<=PWLength;i=i+1) if ( PASS_TEMP[i] !== Password[i] ) begin PASS_UNLCK = 1'b0; end PUT_in = 1'b1; end end PASS_UN_W : //PASS_UN_W state, PUT_out begin if (rising_edge_PUT_out && FlagPUT_out) begin FlagPUT_out=1'b0; PUT_in = 1'b0; if ( PASS_UNLCK && ~(LOCK_REG[2])) PPB_LOCK = 1'b1; end end PREL_LR : begin if (oe && FlagOE ) begin FlagOE = 1'b0; // reading Lock Register is allowed or Data if ( BankAddr == 0 ) begin ONE_READ = 1'b1; if ( AddrCom == 12'h00 ) DOut_zd = LOCK_REG; end else READ_ARRAY_DATA(Address,BankAddr, SecAddr,SecSi,ONE_READ); end end LR_A0SEEN : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (AddrCom == 12'h00) begin PSTART = 1'b1; PSTART <= #1 1'b0; WRBUFF_ACT = 1'b0; WrBuffData[0] = Data; WrBuffAddr[0] = 0; WrBuffSec = 0; WrBuffCnt = 0; PrgBank = 0; temp = DataLo; status[7] = ~ temp[7]; end end LR_PREL_EX : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ( DataLo == 8'h00 ) LOCK_ACT = 1'b0; end PREL_PPB : begin if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; PPBP_in = 1'b0; PPBE_in = 1'b0; end else if (oe && FlagOE ) begin FlagOE = 1'b0; // reading PPB && array data allowed if ( BankAddr == BankPPBAddr ) begin DOut_zd = 16'b0; DOut_zd[0] = PPB[SecAddr]; end else if ( ESP_ACT && ERS_QUEUE[SecAddr]) begin //////////////////////////////////////////////////// //erase suspend active //////////////////////////////////////////////////// if (read) begin status[7] = 1'b1; // status[6] No toggle status[5] = 1'b0; status[2] = ~ status[2]; // toggle end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; end else if ( ~PSP_ACT || SecAddr !== WrBuffSec ) READ_ARRAY_DATA(Address,BankAddr, SecAddr,SecSi,ONE_READ); end end PPB_PREL_PR : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ((DataLo == 8'h00) && (~ESP_ACT || ~(ERS_QUEUE[SecAddr])) && (~PSP_ACT || (SecAddr !== WrBuffSec ))) begin SecPPBAddr = SecAddr; BankPPBAddr = BankAddr; PPBP_in = 1'b1; end end PPB_PGMS : begin //PPB_PGMS state, PPBP_out if (rising_edge_PPBP_out && FlagPPBP_out) begin FlagPPBP_out=1'b0; PPBP_in = 1'b0; if ( PPB_LOCK == 1'b1) PPB[SecPPBAddr] = 1'b0; end else if (oe && FlagOE ) begin FlagOE = 1'b0; if ( BankAddr == 0 ) begin //////////////////////////////////////////////////////- // reading PPB program status //////////////////////////////////////////////////////- if (read) begin status[6] = ~ status[6]; // toggle end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; end else if ( ESP_ACT && ERS_QUEUE[SecAddr]) begin //////////////////////////////////////////////////// //erase suspend active //////////////////////////////////////////////////// if (read) begin status[7] = 1'b1; // status[6] No toggle status[5] = 1'b0; status[2] = ~ status[2]; // toggle end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; end else if ( ~PSP_ACT || SecAddr !== WrBuffSec ) READ_ARRAY_DATA(Address,BankAddr, SecAddr,SecSi,ONE_READ); end end PPB_ERS : begin //PPB_ERS state, PPBE_out if (rising_edge_PPBE_out && FlagPPBE_out) begin FlagPPBE_out=1'b0; PPBE_in = 1'b0; if ( PPB_LOCK == 1'b1 && LOCK_REG[3]) PPB = ~(0); end else if (oe && FlagOE ) begin FlagOE = 1'b0; if ( BankAddr == 0 ) begin //////////////////////////////////////////////////////// // reading All PPB erase status //////////////////////////////////////////////////////// if (read) begin status[6] = ~ status[6]; // toggle end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; end else READ_ARRAY_DATA(Address,BankAddr,SecAddr ,SecSi,ONE_READ); end end PPB_PREL_ER : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ((DataLo == 8'h30) && ~ESP_ACT && ~PSP_ACT ) PPBE_in = 1'b1; end PPB_PREL_EX : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (DataLo == 8'h00) PPB_MODE = 1'b0; end PREL_PPBLCK : begin if (oe && FlagOE ) begin FlagOE = 1'b0; // reading PPB Lock enabled if ( BankAddr == BankPPBLAddr ) begin DOut_zd = 16'b0; DOut_zd[0] = PPB_LOCK; ONE_READ = 1'b1; end else READ_ARRAY_DATA(Address,BankAddr, SecAddr,SecSi,ONE_READ); end end PPBLCK_PREL_ST : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (DataLo == 8'h00) PPB_LOCK = 1'b0; // set PPB Lock Bit end PREL_DYB : begin if (oe && FlagOE ) begin FlagOE = 1'b0; //reading DYB && array data enabled if ( BankAddr == BankDYBAddr ) begin ONE_READ = 1'b1; DOut_zd = 16'b0; DOut_zd[0] = DYB[SecAddr]; end else if ( ESP_ACT && ERS_QUEUE[SecAddr] ) begin //////////////////////////////////////////////////// //erase suspend active //////////////////////////////////////////////////// if (read) begin status[7] = 1'b1; // status[6] No toggle status[5] = 1'b0; status[2] = ~ status[2]; // toggle end DOut_zd[7:0] = status; DOut_zd[15:8]= 8'bz; ONE_READ = 1'b1; end else if ( ~PSP_ACT || SecAddr !== WrBuffSec ) READ_ARRAY_DATA(Address,BankAddr, SecAddr,SecSi,ONE_READ); end end DYB_PREL_ST : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if ((DataLo == 8'h00) && ( ~ESP_ACT || ~(ERS_QUEUE[SecAddr])) && ( ~PSP_ACT || SecAddr!== WrBuffSec)) begin DYB[SecAddr] = 1'b0; BankDYBAddr = BankAddr; end else if ((DataLo == 8'h01) && ( ~ESP_ACT || ~(ERS_QUEUE[SecAddr])) && ( ~PSP_ACT || SecAddr!==WrBuffSec)) begin DYB[SecAddr] = 1'b1; BankDYBAddr = BankAddr; end end DYB_PREL_EX : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (DataLo == 8'h00) DYB_MODE = 1'b0; end SECSI_EX : if (falling_edge_write && FlagWrite) begin FlagWrite=1'b0; if (DataLo == 8'h00) SecSi = #5000 1'b0; end AS : begin if (oe && FlagOE ) begin FlagOE = 1'b0; if ( BankAddr == BankASAddr ) begin case ( Address % (BankSize+1)) 8'h00 : DOut_zd= 16'h0001; 8'h01 : DOut_zd= 16'h307E; 8'h03 : DOut_zd= 16'h0000; //TBD 8'h07 : DOut_zd= 16'h0088; 8'h0E : DOut_zd= 16'h307E; 8'h0F : DOut_zd= 16'h2200; default : if ((Address % 12'h100) == 8'h02) begin DOut_zd[15:1] = 15'b0; DOut_zd[0] = ~ PPB[SecAddr]; end else DOut_zd = 16'bz; endcase ONE_READ = 1'b1; end else begin if ( ESP_ACT && ERS_QUEUE[SecAddr]) begin //////////////////////////////////////////////////// //erase suspend active //////////////////////////////////////////////////// if (read) begin status[7] = 1'b1; // status[6] No toggle status[5] = 1'b0; status[2] = ~ status[2]; // toggle end DOut_zd[7:0] = status; DOut_zd[15:8] = 8'bz; ONE_READ = 1'b1; end else if ( ~PSP_ACT || SecAddr !== WrBuffSec ) READ_ARRAY_DATA(Address,BankAddr, SecAddr,SecSi,ONE_READ); else ONE_READ = 1'b1; end end end endcase end if (oe && FlagOE2 ) begin FlagOE2 = 1'b0; if (burst_rd && SYN) begin if (ONE_READ) RD_MODE = SINGLE_RD; else begin if ((CONF_REG0[2:0] >= 2) && (CONF_REG0[2:0] <=4) && CONF_REG0[3]) RD_MODE = LINEAR; else if((CONF_REG0[2:0]>=2)&&(CONF_REG0[2:0]<=4) && ~(CONF_REG0[3])) RD_MODE = LINEAR_NO_WRAP; else if( CONF_REG0[2:0] == 0) RD_MODE = CONTINUOUS; end if(Address <= -1) RD_MODE = NONE; end if( oe && SYN && (RD_MODE !== NONE)) DOut_zd = DOut_burst; if( OENeg || CENeg || ~RESETNeg) DOut_zd = 16'bz; end else if ((rising_edge_CLK) || (rising_edge_IACC_out && IN_W_ELAPSED)) begin if (RD_MODE == LINEAR) // linear mode only implemented begin if (INITIAL_WAIT ) begin WS_CNT = WS_CNT - 1; RDY_temp = 1'b0; if ( WS_CNT <= 2 ) begin INITIAL_WAIT = 1'b0; INITIAL_ACCESS= 1'b1; CLK_PATH_EN = 1'b1; if (~CONF_REG_8) begin RDY_temp = 1'b1; end end end else if ( INITIAL_ACCESS ) begin if ( IACC_out ) begin if (CLK) CLK_PATH_EN= 1'b1; Prior_IACC = 1'b0; if ( DelayCycSwitch ==0 && (BurstAddr % 8 < 7)) begin RDY_temp = 1'b1; READ_BURST_DATA(BurstAddr,BurstSec); BurstAddr = BurstAddr + 1; CHECK_END(RdCnt,1'b1,BURST_END); if ( (BurstAddr % 8) == 7 ) if ( DelayCyc_CNT == 0 ) DelayCycSwitch = 4; else DelayCycSwitch = 1; end else if ( DelayCycSwitch==0 && (BurstAddr % 8 == 7)) begin READ_BURST_DATA(BurstAddr,BurstSec); if ( DelayCyc_CNT == 0 ) begin RDY_temp = 1'b1; DelayCycSwitch = 4; NEXT_ADDR_LIN(BurstAddr,BurstLength); CHECK_END(RdCnt,1'b1,BURST_END); end else begin RDY_temp = CONF_REG_8; DelayCyc_CNT = DelayCyc_CNT -1; if ( DelayCyc_CNT == 0 ) DelayCycSwitch = 3; else DelayCycSwitch = 2; end end else if ( DelayCycSwitch == 1 ) begin RDY_temp = CONF_REG_8; READ_BURST_DATA(BurstAddr,BurstSec); DelayCyc_CNT = DelayCyc_CNT -1; if ( DelayCyc_CNT == 0 ) DelayCycSwitch = 3; else DelayCycSwitch = 2; end else if ( DelayCycSwitch == 2 ) begin RDY_temp = 1'b0; READ_BURST_DATA(BurstAddr,BurstSec); DelayCyc_CNT = DelayCyc_CNT -1; if ( DelayCyc_CNT == 0 ) DelayCycSwitch = 3; end else if ( DelayCycSwitch == 3 ) begin RDY_temp = ~ CONF_REG_8; READ_BURST_DATA(BurstAddr,BurstSec); NEXT_ADDR_LIN(BurstAddr,BurstLength); CHECK_END(RdCnt,1'b1,BURST_END); DelayCycSwitch = 4; end else // DelayCycSwitch == 4 begin INITIAL_ACCESS = 1'b0; DelayCycSwitch = 0; RDY_temp = 1'b1; READ_BURST_DATA(BurstAddr,BurstSec); NEXT_ADDR_LIN(BurstAddr,BurstLength); CHECK_END(RdCnt,1'b1,BURST_END); if (~ BURST_END ) RDY_temp = 1'b1; else RDY_temp = CONF_REG_8; end end else RDY_temp = ~ CONF_REG_8; IN_W_ELAPSED = 1'b1; end else if ( BURST_END ) begin RDY_temp = 1'b0; DOut_burst = 16'bz; end else // begin READ_BURST_DATA(BurstAddr,BurstSec); NEXT_ADDR_LIN(BurstAddr,BurstLength); CHECK_END(RdCnt,1'b1,BURST_END); if (~ BURST_END ) RDY_temp = 1'b1; else RDY_temp = CONF_REG_8; end end else if (RD_MODE ==CONTINUOUS || RD_MODE==LINEAR_NO_WRAP) // continuous mode && linear without wrap begin if ( INITIAL_WAIT ) begin WS_CNT = WS_CNT - 1; RDY_temp = 1'b0; if ( WS_CNT <= 2 ) begin INITIAL_WAIT = 1'b0; INITIAL_ACCESS= 1'b1; CLK_PATH_EN = 1'b1; if ( ~CONF_REG_8) begin RDY_temp = 1'b1; end end end else if ( INITIAL_ACCESS ) begin if ( IACC_out ) begin if (CLK) CLK_PATH_EN= 1'b1; Prior_IACC = 1'b0; if ( DelayCycSwitch==0 && (BurstAddr % 8 < 7 )) begin RDY_temp = 1'b1; READ_BURST_DATA(BurstAddr,BurstSec); NEXT_ADDR(BurstAddr,BurstSec,SecSi); CHECK_END(RdCnt,RD_MODE==LINEAR_NO_WRAP,BURST_END); if ( BurstAddr % 8 == 7 ) if ( DelayCyc_CNT == 0 ) DelayCycSwitch = 4; else DelayCycSwitch = 1; end else if ( DelayCycSwitch == 0 && (BurstAddr % 8) ==7) begin READ_BURST_DATA(BurstAddr,BurstSec); if ( DelayCyc_CNT == 0 ) begin RDY_temp = 1'b1; DelayCycSwitch = 4; NEXT_ADDR(BurstAddr,BurstSec,SecSi); CHECK_END(RdCnt,RD_MODE==LINEAR_NO_WRAP ,BURST_END); end else begin RDY_temp = CONF_REG_8; DelayCyc_CNT = DelayCyc_CNT -1; if ( DelayCyc_CNT == 0 ) DelayCycSwitch = 3; else DelayCycSwitch = 2; end end else if ( DelayCycSwitch == 1 ) begin RDY_temp = CONF_REG_8; READ_BURST_DATA(BurstAddr,BurstSec); DelayCyc_CNT = DelayCyc_CNT -1; if ( DelayCyc_CNT == 0 ) DelayCycSwitch = 3; else DelayCycSwitch = 2; end else if ( DelayCycSwitch == 2 ) begin RDY_temp = 1'b0; READ_BURST_DATA(BurstAddr,BurstSec); DelayCyc_CNT = DelayCyc_CNT -1; if ( DelayCyc_CNT == 0 ) DelayCycSwitch = 3; end else if ( DelayCycSwitch == 3 ) begin RDY_temp = ~CONF_REG_8; READ_BURST_DATA(BurstAddr,BurstSec); NEXT_ADDR(BurstAddr,BurstSec,SecSi); CHECK_END(RdCnt,RD_MODE==LINEAR_NO_WRAP,BURST_END); DelayCycSwitch = 4; end else //DelayCycSwitch == 4 begin INITIAL_ACCESS = 1'b0; DelayCycSwitch = 0; RDY_temp = 1'b1; READ_BURST_DATA(BurstAddr,BurstSec); CHECK_END(RdCnt,RD_MODE==LINEAR_NO_WRAP,BURST_END); if (~ BURST_END ) RDY_temp = 1'b1; else RDY_temp = CONF_REG_8; if ( (BurstAddr % 8'h80) == 8'h7F ) begin if ( HI_FREQ == 1'b1 ) RDY_temp = CONF_REG_8; else NEXT_ADDR(BurstAddr,BurstSec,SecSi); INITIAL_ACCESS = 1'b0; BOUNDARY_CROSS = 1'b1; BoundarySwitch = 0; end else begin NEXT_ADDR(BurstAddr,BurstSec,SecSi); end end end else RDY_temp = ~ CONF_REG_8; IN_W_ELAPSED = 1'b1; end else if ( BURST_END ) begin RDY_temp = 1'b0; DOut_burst = 16'bz; end else if ( BOUNDARY_CROSS ) begin if ( BoundarySwitch == 0 ) begin if ( HI_FREQ == 1'b1 ) begin RDY_temp = ~ CONF_REG_8; READ_BURST_DATA(BurstAddr,BurstSec); NEXT_ADDR(BurstAddr,BurstSec,SecSi); BoundarySwitch = 1; end else begin RDY_temp = 1'b1; Sector_switch_check(BurstAddr,BurstSec,NO_PROGRESS); if ( NO_PROGRESS ) READ_SINGLE_SYNC_DATA(BurstAddr, BurstSec); else begin READ_BURST_DATA(BurstAddr,BurstSec); NEXT_ADDR(BurstAddr,BurstSec,SecSi); CHECK_END(RdCnt,RD_MODE==LINEAR_NO_WRAP ,BURST_END); end BOUNDARY_CROSS = 1'b0; end end else // Boundary switch==1 begin RDY_temp = 1'b1; Sector_switch_check(BurstAddr,BurstSec,NO_PROGRESS); if ( NO_PROGRESS ) READ_SINGLE_SYNC_DATA(BurstAddr,BurstSec); else begin READ_BURST_DATA(BurstAddr,BurstSec); NEXT_ADDR(BurstAddr,BurstSec,SecSi); CHECK_END(RdCnt,RD_MODE==LINEAR_NO_WRAP,BURST_END); end BOUNDARY_CROSS = 1'b0; end if (BURST_END ) RDY_temp = CONF_REG_8; end else if ( NO_PROGRESS ) begin RDY_temp = 1'b1; READ_SINGLE_SYNC_DATA(BurstAddr,BurstSec); end else begin READ_BURST_DATA(BurstAddr,BurstSec); // check boundary crossing && sector switch CHECK_END(RdCnt,RD_MODE==LINEAR_NO_WRAP,BURST_END); if (~ BURST_END ) RDY_temp = 1'b1; else RDY_temp = CONF_REG_8; if ( (BurstAddr % 8'h80) == 8'h7F ) begin if ( HI_FREQ == 1'b1 ) RDY_temp = CONF_REG_8; else NEXT_ADDR(BurstAddr,BurstSec,SecSi); BOUNDARY_CROSS = 1'b1; BoundarySwitch = 0; end else begin NEXT_ADDR(BurstAddr,BurstSec,SecSi); end end end else if (RD_MODE==SINGLE_RD) begin if ( INITIAL_WAIT ) begin WS_CNT = WS_CNT - 1; RDY_temp = 1'b0; if ( WS_CNT <= 2 ) begin INITIAL_WAIT = 1'b0; INITIAL_ACCESS= 1'b1; CLK_PATH_EN = 1'b1; if ( ~CONF_REG_8 ) begin RDY_temp = 1'b1; end end end else // INITIAL ACCESS begin if ( IACC_out ) begin RDY_temp = 1'b1; READ_SINGLE_SYNC_DATA(BurstAddr,BurstSec); end else RDY_temp = ~ CONF_REG_8; IN_W_ELAPSED = 1'b1; end end end end //Burst data setup always @( OENeg or DOut_burst) begin if (~OENeg && SYN ) DOut_zd = DOut_burst; end //unknown data on outputs always @(DOut_zd) begin if( ~OENeg && ~ AVDNeg) DOut_zd = 16'bx; end always @(posedge burst_rd) begin rising_edge_burst_rd = 1'b1; #1 rising_edge_burst_rd = 1'b0; end always @(posedge write) begin rising_edge_write = 1'b1; #1 rising_edge_write = 1'b0; end always @(negedge write) begin falling_edge_write = 1'b1; #1 falling_edge_write = 1'b0; end always @(negedge RST) begin falling_edge_RST = 1'b1; #1 falling_edge_RST = 1'b0; end always @(posedge AVDNeg) begin rising_edge_AVDNeg = 1'b1; #1 rising_edge_AVDNeg = 1'b0; end always @(negedge AVDNeg) begin falling_edge_AVDNeg = 1'b1; #1 falling_edge_AVDNeg = 1'b0; end always @(posedge CLK) begin rising_edge_CLK = 1'b1; #1 rising_edge_CLK = 1'b0; end always @(posedge OENeg) begin rising_edge_OENeg = 1'b1; #1 rising_edge_OENeg = 1'b0; end always @(posedge IACC_out) begin rising_edge_IACC_out = 1'b1; #1 rising_edge_IACC_out = 1'b0; end always @(posedge RESETNeg) begin rising_edge_RESETNeg = 1'b1; #1 rising_edge_RESETNeg = 1'b0; end always @(negedge RESETNeg) begin falling_edge_RESETNeg = 1'b1; #1 falling_edge_RESETNeg = 1'b0; end always @(posedge reseted) begin rising_edge_reseted = 1'b1; #1 rising_edge_reseted = 1'b0; end always @(negedge reseted) begin falling_edge_reseted = 1'b1; #1 falling_edge_reseted = 1'b0; end always @(PPBP_out) begin if (PPBP_out === 1'b1) begin rising_edge_PPBP_out = 1'b1; #1 rising_edge_PPBP_out = 1'b0; end end always @(PPBE_out) begin if (PPBE_out === 1'b1) begin rising_edge_PPBE_out = 1'b1; #1 rising_edge_PPBE_out = 1'b0; end end always @(SET_out) begin if (SET_out === 1'b1) begin rising_edge_SET_out = 1'b1; #1 rising_edge_SET_out = 1'b0; end end always @(START_out) begin if (START_out === 1'b1) begin rising_edge_START_out = 1'b1; #1 rising_edge_START_out = 1'b0; end end always @(posedge PUT_out) begin rising_edge_PUT_out = 1'b1; #1 rising_edge_PUT_out = 1'b0; end always @(posedge HWResetStart) begin rising_edge_HWResetStart = 1'b1; #1 rising_edge_HWResetStart = 1'b0; end always @(posedge HWResetGlitch) begin rising_edge_HWResetGlitch = 1'b1; #1 rising_edge_HWResetGlitch = 1'b0; end always @(A) begin A_event = 1'b1; #1 A_event = 1'b0; end always @(negedge gWE_n) begin falling_edge_gWE_n = 1'b1; #1 falling_edge_gWE_n = 1'b0; end always @(negedge gCE_n) begin falling_edge_gCE_n = 1'b1; #1 falling_edge_gCE_n = 1'b0; end always @(posedge gWE_n) begin rising_edge_gWE_n = 1'b1; #1 rising_edge_gWE_n = 1'b0; end always @(posedge gCE_n) begin rising_edge_gCE_n = 1'b1; #1 rising_edge_gCE_n = 1'b0; end always @(posedge read) begin ->oe_event; end always @(posedge burst_rd) begin ->oe_event; end always @(oe_event) begin oe = 1'b1; #1 oe = 1'b0; end always @(oe_event) begin rising_edge_oe = 1'b1; #1 rising_edge_oe = 1'b0; end always @(posedge PSUSP) begin rising_edge_PSUSP = 1'b1; #1 rising_edge_PSUSP = 1'b0; end always @(posedge PRES) begin rising_edge_PRES = 1'b1; #1 rising_edge_PRES = 1'b0; end always @(posedge PSTART) begin rising_edge_PSTART = 1'b1; #1 rising_edge_PSTART = 1'b0; end always @(posedge reseted) begin rising_edge_reseted = 1'b1; #1 rising_edge_reseted = 1'b0; end always @(posedge ESUSP) begin rising_edge_ESUSP = 1'b1; #1 rising_edge_ESUSP = 1'b0; end always @(negedge ESUSP) begin falling_edge_ESUSP = 1'b1; #1 falling_edge_ESUSP = 1'b0; end always @(posedge ERES) begin rising_edge_ERES = 1'b1; #1 rising_edge_ERES = 1'b0; end always @(negedge ERES) begin falling_edge_ERES = 1'b1; #1 falling_edge_ERES = 1'b0; end always @(posedge ESTART) begin rising_edge_ESTART = 1'b1; #1 rising_edge_ESTART = 1'b0; end always @(negedge ESTART) begin falling_edge_ESTART = 1'b1; #1 falling_edge_ESTART = 1'b0; end always @(posedge EERR) begin rising_edge_EERR = 1'b1; #1 rising_edge_EERR = 1'b0; end always @(negedge EERR) begin falling_edge_EERR = 1'b1; #1 falling_edge_EERR = 1'b0; end always @(posedge PERR) begin rising_edge_PERR = 1'b1; #1 rising_edge_PERR = 1'b0; end always @(negedge PERR) begin falling_edge_PERR = 1'b1; #1 falling_edge_PERR = 1'b0; end always @(posedge EDONE) begin rising_edge_EDONE = 1'b1; #1 rising_edge_EDONE = 1'b0; end always @(negedge EDONE) begin falling_edge_EDONE = 1'b1; #1 falling_edge_EDONE = 1'b0; end always @(posedge PDONE) begin rising_edge_PDONE = 1'b1; #1 rising_edge_PDONE = 1'b0; end always @(negedge PDONE) begin falling_edge_PDONE = 1'b1; #1 falling_edge_PDONE = 1'b0; end always @(posedge SET_out) begin rising_edge_SET_out = 1'b1; #1 rising_edge_SET_out = 1'b0; end always @(negedge SET_out) begin falling_edge_SET_out = 1'b1; #1 falling_edge_SET_out = 1'b0; end always @(posedge START_out) begin rising_edge_START_out = 1'b1; #1 rising_edge_START_out = 1'b0; end always @(negedge START_out) begin falling_edge_START_out = 1'b1; #1 falling_edge_START_out = 1'b0; end always @(~oe) begin if (~oe) FlagOE = 1'b1; end always @(~oe) begin if (~oe) FlagOE2 = 1'b1; end always @(~rising_edge_PUT_out) begin if (~rising_edge_PUT_out) FlagPUT_out = 1'b1; end always @(~falling_edge_write) begin if (~falling_edge_write) FlagWrite = 1'b1; end always @(~rising_edge_PPBP_out) begin if (~rising_edge_PPBP_out) FlagPPBP_out = 1'b1; end always @(~rising_edge_PPBE_out) begin if (~rising_edge_PPBE_out) FlagPPBE_out = 1'b1; end always @(~rising_edge_PDONE) begin if (~rising_edge_PDONE) FlagPDONErising = 1'b1; end always @(~falling_edge_PDONE) begin if (~falling_edge_PDONE) FlagPDONEfalling = 1'b1; end always @(~falling_edge_EDONE) begin if (~falling_edge_EDONE) FlagEDONEfalling = 1'b1; end always @(~rising_edge_EDONE) begin if (~rising_edge_EDONE) FlagEDONErising = 1'b1; end always @(~rising_edge_SET_out) begin if (~rising_edge_SET_out) FlagSET_out = 1'b1; end always @(~rising_edge_START_out) begin if (~rising_edge_START_out) FlagSTART_out = 1'b1; end task ADDRESS_GENERATE; input[HiAddrBit:0] A; output integer Addr; output integer AddrC; output integer SAddr; output integer BAddr; output integer BPAddr; output integer AP; reg[HiAddrBit:0] tmp; begin Addr = -1; AddrC = 0; SAddr = -1; BAddr = -1; BPAddr= -1; AP = 0; AP = A[1:0]; Addr = A[HiAddrBit:0]; AddrC = A[11:0]; tmp[SecBit64-1:0]= A[HiAddrBit:(HiAddrBit-SecBit64+1)]; SAddr = tmp[(SecBit64-1):0]; BAddr = A[HiAddrBit:(HiAddrBit-BankBit+1)]; BPAddr= A[HiAddrBit:5]; end endtask task READ_ARRAY_DATA; input integer Addr; input integer Bank; input integer Sec; input SS; output mode; begin if ( (~SS || (Sec!==0)) && (Addr >= 0 )) begin if ( Mem[Addr]!== -1 ) DOut_zd = Mem[Addr]; else DOut_zd = 16'bx; end else if (( Addr>=8'h00) && (Addr < 12'h100)) begin if ( SecSiMem[Addr] !== -1 ) DOut_zd = SecSiMem[Addr]; else DOut_zd = 16'bx; end else begin DOut_zd = 16'bz; // SecSi Address out of range $display("Address out of SecSi range."); end end endtask task Sector_switch_check; input integer BAddr; input integer BSec; output Switch; integer Bank; reg SW; reg Switch_out; begin SW = 1'b0; Switch_out = 1'b0; SW = ((BAddr % (SecSize64+1)) === 0); if ( SW ) begin Bank = (BAddr / (BankSize+1)); if (current_state==SERS|| current_state==ESPS || current_state==SERS_EXEC ) begin if ( ERS_QUEUE_B[Bank] ) Switch_out = 1'b1; end else if (current_state==ESP) begin if ( ERS_QUEUE[BSec] ) Switch_out = 1'b1; end else if (current_state==PGMS || current_state==PGSPS || current_state==WR2BUFF_AB) begin if ( (Bank == PrgBank) || (ESP_ACT && ERS_QUEUE[BSec]) ) Switch_out = 1'b1; end else if (current_state==PGS) begin if ( (BSec == WrBuffSec) || (ESP_ACT && ERS_QUEUE[BSec]) ) Switch_out = 1'b1; end else if (current_state==PREL_LR) begin if ( Bank == 0 ) Switch_out = 1'b1; end else if (current_state==PREL_PASS ) begin if ( Bank == 0 ) Switch_out = 1'b1; end else if (current_state==PREL_DYB) begin if ( (Bank == BankDYBAddr) || (ESP_ACT && ERS_QUEUE[BSec]) || (PSP_ACT && BSec == WrBuffSec)) Switch_out = 1'b1; end else if (current_state==PREL_PPBLCK) begin if ( Bank == BankPPBLAddr ) Switch_out = 1'b1; end else if (current_state==AS) begin if ( (Bank == BankASAddr) || (ESP_ACT && ERS_QUEUE[BSec]) || (PSP_ACT && BSec == WrBuffSec)) Switch_out = 1'b1; end else if (current_state==CFI) begin if ( (Bank == BankCFIAddr) || (ESP_ACT && ERS_QUEUE[BSec]) || (PSP_ACT && BSec == WrBuffSec)) Switch_out = 1'b1; end if ( SecSi && (BSec ==0) ) Switch_out = 1'b1; Switch = Switch_out; end end endtask task NEXT_ADDR; inout integer BAddr; inout integer BSec; input SS; begin if ( BAddr == MaxAddr ) begin BAddr = 0; BSec = 0; end else if (SS && (BAddr == 255)) BAddr = 0; else begin BAddr = BAddr+1; if ((BAddr % (SecSize64+1)) == 0) BSec= BSec + 1; end end endtask task NEXT_ADDR_LIN; inout integer BAddr; input integer Length; begin BAddr = BAddr + 1; if ( (BAddr % Length) == 0 ) BAddr= BAddr - Length; end endtask task CHECK_END; inout integer CNT; input Enable; output BEnd; begin if ( Enable ) begin CNT=CNT-1; if ( CNT == 0 ) BEnd = 1'b1; else BEnd = 1'b0; end else BEnd = 1'b0; end endtask task READ_BURST_DATA; input integer BAddr; input integer BSec ; begin if (~SecSi || BSec!=0) begin DOut_burst = 16'bx; if ( Mem[BAddr]!==-1 ) DOut_burst = Mem[BAddr]; end else begin DOut_burst = 16'bx; if ( SecSiMem[BAddr]!==-1 ) DOut_burst = SecSiMem[BAddr]; end end endtask task READ_SINGLE_SYNC_DATA; input integer Addr; input integer Sec; integer Bank; begin Bank = (Addr / (BankSize+1)); DOut_burst = 16'bz; if (read_rise_state == CFI) begin if ( Bank == BankCFIAddr ) if (((Addr % (BankSize+1) >= 8'h10) && (Addr % (BankSize+1) <= 8'h3C)) || ((Addr % (BankSize+1) >= 8'h40) && (Addr % (BankSize+1) <= 8'h67))) DOut_burst = CFIMem[Addr % (BankSize+1)]; else DOut_burst = 16'bz; else begin DOut_burst[7:0] = status; DOut_burst[15:8] = 8'bz; end end else if (read_rise_state==ERS || read_rise_state==SERS || read_rise_state==SERS_EXEC || read_rise_state==ESP || read_rise_state==PGS || read_rise_state==WR2BUFF_AB || read_rise_state==ESPS) begin DOut_burst[7:0] = status; DOut_burst[15:8] = 8'bz; end else if (read_rise_state==PPB_PGMS || read_rise_state==PPB_ERS) begin if (BankAddr == 0) begin DOut_burst[7:0] = status; DOut_burst[15:8] = 8'bz; end end else if (read_rise_state==PGMS || read_rise_state==PGSPS) begin DOut_burst[7:0] = status; if ( Sec == WrBuffSec || PASS_ACT || LOCK_ACT ) DOut_burst[7] = status[7]; else DOut_burst[7] = ~(status[7]); DOut_burst[15:8] = 8'bz; end else if(read_rise_state==RD_CONF) begin if ( Addr == 12'h000 ) DOut_burst = CONF_REG0; else if ( Addr == 12'h001 ) DOut_burst = CONF_REG1; end else if (read_rise_state==PREL_LR) begin if (Addr == 0) DOut_burst = LOCK_REG; end else if (read_rise_state==PREL_PASS) begin if (LOCK_REG[2]) DOut_burst = Password[Addr % 4]; else DOut_burst = MaxData; end else if (read_rise_state==PREL_PPBLCK) begin DOut_burst = 16'b0; DOut_burst[0] = PPB_LOCK; end else if (read_rise_state==PREL_DYB) begin if ( Bank == BankDYBAddr ) begin DOut_burst = 16'b0; DOut_burst[0] = DYB[Sec]; end else begin DOut_burst[7:0] = status; DOut_burst[15:8]= 8'bz; end end else if (read_rise_state==AS) begin if ( Bank == BankASAddr ) case (Addr % (BankSize+1)) 8'h00 : DOut_burst= 16'h0001; 8'h01 : DOut_burst= 16'h307E; 8'h03 : DOut_burst= 16'h0000; 8'h07 : DOut_burst= 16'h0088; 8'h0E : DOut_burst= 16'h307E; 8'h0F : DOut_burst= 16'h2200; default : if (( Addr % 12'h100) == 12'h02) begin DOut_burst[15:1] = 15'b0; DOut_burst[0] = ~(PPB[SecAddr]); end else DOut_burst = 16'bz; endcase else begin DOut_burst[7:0] = status; DOut_burst[15:8] = 8'bz; end end if (SecSi && (Sec == 0) ) begin if (( Addr>=8'h00) && (Addr < 12'h100)) begin DOut_burst = 16'bx; if ( SecSiMem[Addr] !== -1 ) DOut_burst = SecSiMem[Addr]; end end if ( PSP_ACT && (Sec == WrBuffSec )) DOut_burst = 16'bz; end endtask reg BuffInOE, BuffInCE, BuffInADDR; wire BuffOutOE, BuffOutCE, BuffOutADDR; BUFFER BUFOE (BuffOutOE , BuffInOE); BUFFER BUFCE (BuffOutCE , BuffInCE); BUFFER BUFADDR (BuffOutADDR, BuffInADDR); initial begin BuffInOE = 1'b1; BuffInCE = 1'b1; BuffInADDR = 1'b1; end always @(posedge BuffOutOE) begin OEDQ_01 = $time; end always @(posedge BuffOutCE) begin CEDQ_01 = $time; end always @(posedge BuffOutADDR) begin ADDRDQ_01 = $time; end endmodule module BUFFER (OUT,IN); input IN; output OUT; buf ( OUT, IN); endmodule