////////////////////////////////////////////////////////////////////////////// // File name : s29vs032k.v ////////////////////////////////////////////////////////////////////////////// // Copyright (C) 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: | mod date: | changes made: // V1.0 D.Randjelovic 06 Apr 28 Initial Release // V1.1 D.Cirovic 07 Jan 15 Updated to Datasheet Rev.9.4: // command definitions completly changed, // buffer programming added, // no single word programming, // no RDY output, // small top/bottom boot sectors added, // merging of AS and CFI modes, // lock range feature added, // many other changes // V1.2 R.Miodragovic 07 May 31 Updated to Adv. Datasheet 13March2007 ////////////////////////////////////////////////////////////////////////////// // PART DESCRIPTION: // // Library: FLASH // Technology: Flash Memory // Part: s29vs032k // // Description: 32Mbit (2M x16-Bit) Simultaneous operation, Burst mode // NOR Flash Memory // ////////////////////////////////////////////////////////////////////////////// // Known Bugs: // ////////////////////////////////////////////////////////////////////////////// // Comments : // For correct simulation, simulator resolution should be set to 1ps // 16th character in TimingModel determines whether top or bottom boot // architecture is used ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // MODULE DECLARATION // ////////////////////////////////////////////////////////////////////////////// `timescale 1 ps/1 ps module s29vs032k ( A20 , A19 , A18 , A17 , A16 , DQ15 , DQ14 , DQ13 , DQ12 , DQ11 , DQ10 , DQ9 , DQ8 , DQ7 , DQ6 , DQ5 , DQ4 , DQ3 , DQ2 , DQ1 , DQ0 , CENeg , AVDNeg , OENeg , WENeg , RESETNeg , CLK , TEST , VPP); //////////////////////////////////////////////////////////////////////// // Port / Part Pin Declarations //////////////////////////////////////////////////////////////////////// input A20 ; input A19 ; input A18 ; input A17 ; input A16 ; inout DQ15 ; inout DQ14 ; inout DQ13 ; inout DQ12 ; inout DQ11 ; inout DQ10 ; inout DQ9 ; inout DQ8 ; inout DQ7 ; inout DQ6 ; inout DQ5 ; inout DQ4 ; inout DQ3 ; inout DQ2 ; inout DQ1 ; inout DQ0 ; input CENeg ; input AVDNeg ; input OENeg ; input WENeg ; input RESETNeg ; input CLK ; input VPP ; input TEST ; // interconnect path delay signals wire A20_ipd ; wire A19_ipd ; wire A18_ipd ; wire A17_ipd ; wire A16_ipd ; wire DQ15_ipd ; wire DQ14_ipd ; wire DQ13_ipd ; wire DQ12_ipd ; wire DQ11_ipd ; wire DQ10_ipd ; wire DQ9_ipd ; wire DQ8_ipd ; wire DQ7_ipd ; wire DQ6_ipd ; wire DQ5_ipd ; wire DQ4_ipd ; wire DQ3_ipd ; wire DQ2_ipd ; wire DQ1_ipd ; wire DQ0_ipd ; wire [20 : 0] A; assign A = { A20_ipd, A19_ipd, A18_ipd, A17_ipd, A16_ipd, DQ15_ipd, DQ14_ipd, DQ13_ipd, DQ12_ipd, DQ11_ipd, DQ10_ipd, DQ9_ipd, DQ8_ipd, DQ7_ipd, DQ6_ipd, DQ5_ipd, DQ4_ipd, DQ3_ipd, DQ2_ipd, DQ1_ipd, DQ0_ipd }; wire [15 : 0 ] Din; assign Din = {DQ15_ipd, DQ14_ipd, DQ13_ipd, DQ12_ipd, DQ11_ipd, DQ10_ipd, DQ9_ipd, DQ8_ipd, DQ7_ipd, DQ6_ipd, DQ5_ipd, DQ4_ipd, DQ3_ipd, DQ2_ipd, DQ1_ipd, DQ0_ipd }; wire [15 : 0 ] Dout; assign Dout = {DQ15, DQ14, DQ13, DQ12, DQ11, DQ10, DQ9, DQ8, DQ7, DQ6, DQ5, DQ4, DQ3, DQ2, DQ1, DQ0 }; wire CENeg_ipd ; wire AVDNeg_ipd ; wire OENeg_ipd ; wire WENeg_ipd ; wire RESETNeg_ipd ; wire CLK_ipd ; wire VPP_ipd ; wire TEST_ipd ; wire DQ15_zd ; wire DQ14_zd ; wire DQ13_zd ; wire DQ12_zd ; wire DQ11_zd ; wire DQ10_zd ; wire DQ9_zd ; wire DQ8_zd ; wire DQ7_zd ; wire DQ6_zd ; wire DQ5_zd ; wire DQ4_zd ; wire DQ3_zd ; wire DQ2_zd ; wire DQ1_zd ; wire DQ0_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_zd; assign {DQ15_zd, DQ14_zd, DQ13_zd, DQ12_zd, DQ11_zd, DQ10_zd, DQ9_zd, DQ8_zd, DQ7_zd, DQ6_zd, DQ5_zd, DQ4_zd, DQ3_zd, DQ2_zd, DQ1_zd, DQ0_zd } = Dout_zd; 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; parameter UserPreload = 1'b0; parameter mem_file_name = "none"; parameter secsi_file_name = "none"; parameter TimingModel = "DefaultTimingModel"; parameter PartID = "s29vs032k"; parameter MaxData = 16'hffff; parameter MemSize = 30'h1fffff; parameter SecNum = 66; parameter BankNum = 3; parameter SecGroupNum = 1; parameter SecSize64 = 16'h7fff; parameter SecSize16 = 16'h1fff; parameter BankSize = 30'h7ffff; parameter HiAddrBit = 20; parameter WrBuffLength = 31; parameter WrBuffPgNum = 30'hffff; parameter TBD = 16'h0000; parameter Reserved = 0; //varaibles to resolve if bottom or top architecture is used reg [20*8-1:0] tmp_timing;//stores copy of TimingModel reg [7:0] tmp_char;//stores "t" or "b" character integer found = 1'b0; // If speedsimulation is needed uncomment following line // `define SPEEDSIM; parameter SYNCR = 4'd0; parameter NOSYNC = 4'd1; parameter LINEAR = 4'd2; // FSM states parameter IDLE_RST = 8'd0; parameter ERASE_ENTRY = 8'd1; parameter SL_ENTRY = 8'd2; parameter LR_ENTRY = 8'd3; parameter SecSi_ENTRY = 8'd4; parameter CR_ENTRY = 8'd5; parameter W2B_ENTRY = 8'd6; parameter AS_CFI_ENTRY= 8'd7; parameter CERS = 8'd8; parameter SERS = 8'd9; parameter SL_Change = 8'd10; parameter W2B_WC = 8'd11; parameter SERS_SL = 8'd12; parameter LOCK_RANGE = 8'd13; parameter W2BUF_PG = 8'd14; parameter WB_LOADED = 8'd15; parameter SERS_SUS = 8'd16; parameter PGM = 8'd17; parameter PGM_SL = 8'd18; parameter PGM_SUS = 8'd19; // states reg [9:0] current_state = IDLE_RST; reg [9:0] next_state = IDLE_RST; reg [7:0] RD_MODE = SYNCR; reg PoweredUp = 0; reg ASYN = 1; // asynchronous mode // If speedsimulation is needed uncomment following line `define SPEEDSIM; // FSM control signals reg ESP_ACT = 0; reg LOCK_ACT = 0; reg CR_ACT = 0; reg SecSi = 0; reg abc =1'b0; reg PDONE = 1; // Programming done reg PSTART = 0; // Start programming reg PSUSP = 0; // suspend programming reg PRES = 0; // Resume Programming reg EDONE = 1; // Erase Done reg ESTART = 0; // Start Erase reg ESUSP = 0; // Suspend Erase reg ERES = 0; // Resume Erase reg CEDONE = 1; // Chip Erase Done reg WRITE = 1; reg READ = 1; reg BURST = 1; reg ReadINIT = 1; reg [15:0] OutputD, DOut_burst; // internal delays reg IACC_in = 0; // Initial access delay reg IACC_out = 0; reg START_in = 0; // Program/Erase suspend reg START_out = 0; // Timeout // Access time variables reg FROMCE = 0; reg FROMOE = 0; reg FROMADDR = 0; reg [SecNum : 0] SLA_SMALL = 0; reg [SecNum : 0] SLA_SMALL_tmp = 0; integer OEDQ_01; integer CEDQ_01; integer ADDRDQIN_01; integer ADDRDQPAGE_01; time OEDQ_t = 0; time CEDQ_t = 0; time ADDRDQ_t = 0; time ADDR_event = 0; reg[15:0] TempData; integer Addr, SecAddr, BankID, BurstSec; integer PrevAddr; // Write page buffer address integer BuffPageAddr; integer sgsaT [0:SecGroupNum]; integer sgsaB [0:SecGroupNum]; // Data integer D_tmp, BA_ERS, BA_PGM, SA_ERS, SA_LR, SA_SecSi,SA_CR; integer SA_PGM, SA_SR, SA_AS_CFI, PA_PGM; integer SL_REG = -2; // glitch protection reg gWE_n = 1; reg gCE_n = 1; reg gOE_n = 1; reg gAVD_n = 1; reg AddrREF = 0; reg CLKMerge = 0; reg IN_W_ELAPSED; reg DATA_DELAY; reg RST = 0; reg reseted = 0; integer SecSiMem [0 : 255]; integer CFIMem [16 : 127]; integer Mem [0:MemSize]; reg [15:0] ConfReg = 16'b1111111101001010; reg [15:0] LOCK_REG = 16'b1111111111111111; reg [15:0] ConfRegtemp; // write buffer signals integer WrBuffData [0 : WrBuffLength]; integer WrBuffAddr [0 : WrBuffLength]; integer WrBuffCnt, WC, BurstDelay, WS_Initial; reg Check_freq; reg deq; //Sectors selected for erasure reg STAT_ACT = 0; reg D_pass = 1; reg Viol, BurstStarted; integer DelayCycSwitch, BurstAddr,RDCnt,WS_Boundary,WS_Latency; integer tmpaddr, tmpdata; /////////////////////////////////////////////////////////////////////////////// //Interconnect Path Delay Section /////////////////////////////////////////////////////////////////////////////// buf (A20_ipd, A20); buf (A19_ipd, A19); buf (A18_ipd, A18); buf (A17_ipd, A17); buf (A16_ipd, A16); buf (DQ15_ipd, DQ15); buf (DQ14_ipd, DQ14); buf (DQ13_ipd, DQ13); buf (DQ12_ipd, DQ12); buf (DQ11_ipd, DQ11); buf (DQ10_ipd, DQ10); buf (DQ9_ipd , DQ9 ); buf (DQ8_ipd , DQ8 ); buf (DQ7_ipd , DQ7 ); buf (DQ6_ipd , DQ6 ); buf (DQ5_ipd , DQ5 ); buf (DQ4_ipd , DQ4 ); buf (DQ3_ipd , DQ3 ); buf (DQ2_ipd , DQ2 ); buf (DQ1_ipd , DQ1 ); buf (DQ0_ipd , DQ0 ); buf (CENeg_ipd , CENeg ); buf (AVDNeg_ipd , AVDNeg ); buf (OENeg_ipd , OENeg ); buf (WENeg_ipd , WENeg ); buf (RESETNeg_ipd , RESETNeg ); buf (CLK_ipd , CLK ); buf (VPP_ipd , VPP ); buf (TEST_ipd ,TEST ); /////////////////////////////////////////////////////////////////////////////// // Propagation delay Section /////////////////////////////////////////////////////////////////////////////// nmos (DQ15, DQ15_Pass , 1); nmos (DQ14, DQ14_Pass , 1); nmos (DQ13, DQ13_Pass , 1); nmos (DQ12, DQ12_Pass , 1); nmos (DQ11, DQ11_Pass , 1); nmos (DQ10, DQ10_Pass , 1); nmos (DQ9 , DQ9_Pass , 1); nmos (DQ8 , DQ8_Pass , 1); nmos (DQ7 , DQ7_Pass , 1); nmos (DQ6 , DQ6_Pass , 1); nmos (DQ5 , DQ5_Pass , 1); nmos (DQ4 , DQ4_Pass , 1); nmos (DQ3 , DQ3_Pass , 1); nmos (DQ2 , DQ2_Pass , 1); nmos (DQ1 , DQ1_Pass , 1); nmos (DQ0 , DQ0_Pass , 1); wire deg; // Needed for TimingChecks // VHDL CheckEnable Equivalent wire CENeg_CLK_check; assign CENeg_CLK_check = ~ConfReg[15] && ~AVDNeg ; wire A0_CLK_check; assign A0_CLK_check = ~ConfReg[15] && ~AVDNeg && ~CENeg; wire AVDNeg_CLK_check; assign AVDNeg_CLK_check = ~ConfReg[15] && ~CENeg; wire CENeg_low1; assign CENeg_low1 = ~CENeg ; wire CENeg_low; assign CENeg_low = ~CENeg && deg; wire CLK_check; assign CLK_check = ~ConfReg[15]; wire DQ0_CENeg_check; assign DQ0_CENeg_check = ~WENeg && deg; wire A0_CENeg_check; assign A0_CENeg_check = ~WENeg && OENeg && ~AVDNeg; specify // tipd delays: interconnect path delays , mapped to input port delays. // In Verilog is not necessary to declare any tipd_ delay variables, // they can be taken from SDF file // With all the other delays real delays would be taken from SDF file // tpd delays specparam tpd_RESETNeg_DQ0 = 1; // specparam tpd_A16_DQ0 = 1; // tacc specparam tpd_CENeg_DQ0 = 1; // tce, tcez specparam tpd_OENeg_DQ0 = 1; // toe, toez specparam tpd_CLK_DQ0 = 1; // tbacc // tsetup values specparam tsetup_CENeg_CLK = 1; // tces edge / specparam tsetup_A0_CLK = 1; // tacs edge / specparam tsetup_A0_AVDNeg = 1; // tas edge / specparam tsetup_AVDNeg_CLK = 1; // tavc edge / specparam tsetup_AVDNeg_OENeg = 1; // tawes edge \ specparam tsetup_AVDNeg_WENeg = 1; // tvlwh edge / specparam tsetup_DQ0_WENeg = 1; // tds edge / specparam tsetup_WENeg_AVDNeg = 1; // twea edge \ specparam tsetup_OENeg_WENeg = 1; // tweh edge \ specparam tsetup_CENeg_WENeg = 1; // tcs edge \ specparam tsetup_RESETNeg_CENeg = 1; // trh edge \ specparam tsetup_RESETNeg_OENeg = 1; specparam tsetup_CENeg_AVDNeg = 1; specparam tsetup_WENeg_CENeg = 1; specparam tsetup_WENeg_OENeg = 1; specparam tsetup_DQ0_CENeg = 1; specparam tsetup_A0_CENeg = 1; // thold values specparam thold_CENeg_RESETNeg = 1; // trph edge \ specparam thold_A0_CLK = 1; // tach edge / specparam thold_A0_AVDNeg = 1; // taavdh edge / specparam thold_AVDNeg_CLK = 1; // tavd edge / specparam thold_OENeg_RESETNeg = 1; // tpw values: pulse width specparam tpw_RESETNeg_negedge = 1; // trp specparam tpw_AVDNeg_negedge = 1; // tavdp specparam tpw_WENeg_negedge = 1; // twp specparam tpw_WENeg_posedge = 1; // twph specparam tpw_CLK_negedge = 1; // tcl specparam tpw_CLK_posedge = 1; // tch specparam tpw_CENeg_negedge = 1; specparam tpw_CENeg_posedge = 1; // tperiod values specparam tperiod_WENeg_posedge = 1; // twc specparam tperiod_WENeg_negedge = 1; specparam tperiod_CENeg_posedge = 1; specparam tperiod_CENeg_negedge = 1; specparam tperiod_CLK = 1; // tclk // tdevice values: values for internal delays `ifdef SPEEDSIM specparam tdevice_WRBO = 5000000; // Write Buffer Program // Sector Erase Operation specparam tdevice_SEO64 = 400000; // 64 Kword sector specparam tdevice_SEO16 = 350000; // 16 Kword sector specparam tdevice_IACC = 75000; // Initial access delay tIA // Program/Erase Suspend Timeout tESL, tPSL specparam tdevice_START = 20000000; `else specparam tdevice_WRBO = 5000000; // Write Buffer Program // Sector Erase Operation specparam tdevice_SEO64 = 400000000; // 64 Kword sector specparam tdevice_SEO16 = 350000000; // 16 Kword sector specparam tdevice_IACC = 75000; // Initial access delay tIA // Program/Erase Suspend Timeout tESL, tPSL specparam tdevice_START = 20000000; `endif /////////////////////////////////////////////////////////////////////////////// // Input Port Delays don't require Verilog description /////////////////////////////////////////////////////////////////////////////// // Path delays // /////////////////////////////////////////////////////////////////////////////// // Data ouptut paths if (~RESETNeg) ( RESETNeg => DQ0 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ1 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ2 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ3 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ4 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ5 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ6 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ7 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ8 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ9 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ10 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ11 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ12 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ13 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ14 ) = tpd_RESETNeg_DQ0; if (~RESETNeg) ( RESETNeg => DQ15 ) = tpd_RESETNeg_DQ0; if (FROMOE) (OENeg => DQ0) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ1) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ2) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ3) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ4) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ5) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ6) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ7) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ8) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ9) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ10) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ11) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ12) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ13) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ14) = tpd_OENeg_DQ0; if (FROMOE) (OENeg => DQ15) = tpd_OENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ0) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ1) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ2) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ3) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ4) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ5) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ6) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ7) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ8) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ9) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ10) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ11) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ12) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ13) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ14) = tpd_CENeg_DQ0; if (FROMCE || D_pass) (CENeg => DQ15) = tpd_CENeg_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ0) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ1) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ2) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ3) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ4) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ5) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ6) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ7) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ8) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ9) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ10) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ11) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ12) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ13) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ14) = tpd_CLK_DQ0; if (~CENeg && ~ConfReg[15] && IN_W_ELAPSED && CLK && RD_MODE == LINEAR) (CLK => DQ15) = tpd_CLK_DQ0; //////////////////////////////////////////////////////////////////////////// // Timing Violation // //////////////////////////////////////////////////////////////////////////// $setup (CENeg, posedge CLK &&& CENeg_CLK_check,tsetup_CENeg_CLK); $setup (DQ0, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ1, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ2, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ3, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ4, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ5, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ6, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ7, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ8, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ9, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ10, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ11, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ12, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ13, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ14, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (DQ15, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (A16, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (A17, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (A18, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (A19, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (A20, posedge CLK &&& A0_CLK_check, tsetup_A0_CLK); $setup (AVDNeg, posedge CLK &&& AVDNeg_CLK_check, tsetup_AVDNeg_CLK); $setup (DQ0, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ1, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ2, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ3, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ4, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ5, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ6, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ7, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ8, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ9, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ10, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ11, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ12, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ13, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ14, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ15, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (A16, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (A17, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (A18, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (A19, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (A20, posedge AVDNeg &&& CENeg_low1, tsetup_A0_AVDNeg); $setup (DQ0, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ1, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ2, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ3, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ4, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ5, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ6, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ7, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ8, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ9, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ10, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ11, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ12, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ13, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ14, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ15, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (A16, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (A17, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (A18, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (A19, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (A20, negedge CENeg &&& A0_CENeg_check, tsetup_A0_CENeg); $setup (DQ0, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ1, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ2, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ3, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ4, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ5, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ6, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ7, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ8, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ9, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ10, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ11, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ12, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ13, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ14, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ15, posedge WENeg &&& CENeg_low, tsetup_DQ0_WENeg); $setup (DQ0, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ1, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ2, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ3, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ4, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ5, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ6, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ7, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ8, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ9, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ10, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ11, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ12, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ13, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ14, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (DQ15, posedge CENeg &&& DQ0_CENeg_check, tsetup_DQ0_CENeg); $setup (WENeg, negedge OENeg, tsetup_WENeg_OENeg); $setup (AVDNeg, negedge OENeg, tsetup_AVDNeg_OENeg); $setup (AVDNeg, posedge WENeg &&& CENeg_low1, tsetup_AVDNeg_WENeg); $setup (CENeg, negedge WENeg, tsetup_CENeg_WENeg); $setup (WENeg, negedge CENeg, tsetup_WENeg_CENeg); $setup (OENeg, negedge WENeg &&& CENeg_low1, tsetup_OENeg_WENeg); $setup (CENeg, posedge AVDNeg &&& CENeg_low1, tsetup_CENeg_AVDNeg); $setup (WENeg, posedge AVDNeg, tsetup_WENeg_AVDNeg); $setup (RESETNeg, negedge OENeg, tsetup_RESETNeg_OENeg); $setup (RESETNeg, negedge CENeg, tsetup_RESETNeg_CENeg); $hold (negedge RESETNeg, OENeg, thold_OENeg_RESETNeg); $hold (negedge RESETNeg, CENeg, thold_CENeg_RESETNeg); $hold (posedge AVDNeg &&& CENeg_low1, DQ0, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ1, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ2, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ3, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ4, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ5, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ6, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ7, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ8, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ9, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ10, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ11, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ12, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ13, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ14, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, DQ15, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, A16, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, A17, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, A18, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, A19, thold_A0_AVDNeg, Viol); $hold (posedge AVDNeg &&& CENeg_low1, A20, thold_A0_AVDNeg, Viol); $hold (posedge CLK &&& AVDNeg_CLK_check, AVDNeg, thold_AVDNeg_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ0, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ1, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ2, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ3, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ4, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ5, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ6, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ7, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ8, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ9, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ10, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ11, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ12, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ13, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ14, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, DQ15, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, A16, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, A17, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, A18, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, A19, thold_A0_CLK, Viol); $hold (posedge CLK &&& A0_CLK_check, A20, thold_A0_CLK, Viol); $width (negedge AVDNeg, tpw_AVDNeg_negedge); $width (negedge RESETNeg, tpw_RESETNeg_negedge); $width (posedge WENeg, tpw_WENeg_posedge); $width (negedge WENeg, tpw_WENeg_negedge); $width (posedge CENeg, tpw_CENeg_posedge); $width (negedge CENeg, tpw_CENeg_negedge); $width (posedge CLK &&& CLK_check, tpw_CLK_posedge); $width (negedge CLK &&& CLK_check, tpw_CLK_negedge); $period(posedge WENeg, tperiod_WENeg_posedge); $period(posedge CENeg, tperiod_CENeg_posedge); $period(posedge CLK &&& CLK_check, tperiod_CLK); endspecify //tdevice parameters aligned to model timescale //32bits exceeded time tdevice_SEO64_ts = tdevice_SEO64 * 1000; time tdevice_SEO16_ts = tdevice_SEO16 * 1000; //////////////////////////////////////////////////////////////////////////////// // Main Behavior Block // //////////////////////////////////////////////////////////////////////////////// integer AddressLatched, WrAddressLatched; reg READCYCLE, LATCHED, AVDLATCHED, AsynWrAddLatch; time elapsed, duration, start, wrbo, seo16, seo64; integer i, Data, DataLo, AddrCom, j, new_int; reg [16:0] new_bit; reg BURST_TR, SYNCREAD; reg [15:0] Status = 16'b0000000010000000; reg oe = 0; reg ER_FLAG = 0; reg BURST_END; integer BurstLength, DelayCyc_CNT, LatencyAddr; integer old_int, old_bit; reg INITIAL = 0; reg rising_edge_AVDNeg, falling_edge_AVDNeg; reg rising_edge_gWE_n, falling_edge_gWE_n; reg rising_edge_gCE_n, falling_edge_gCE_n; reg rising_edge_CENeg, falling_edge_CENeg; reg rising_edge_CLK, falling_edge_OENeg, A_event; reg rising_edge_RESETNeg, falling_edge_RESETNeg; reg rising_edge_START_in, rising_edge_READ, falling_edge_READ; reg rising_edge_reseted, rising_edge_PSTART; reg rising_edge_PSUSP, rising_edge_PRES; reg rising_edge_ESTART, rising_edge_ESUSP, rising_edge_ERES; reg falling_edge_WRITE, rising_edge_CEDONE; reg rising_edge_EDONE, rising_edge_PDONE; reg rising_edge_START_out, falling_edge_RST; reg falling_edge_BURST, rising_edge_OENeg; reg rising_edge_CLKMerge; reg next_state_event, falling_edge_ReadINIT; time OENeg_event = 0; time CENeg_event = 0; reg LockRangeDone = 0; reg LockRange = 0; reg A6Lock = 0; reg PR_FLAG = 0; integer SLA_Lo = -1; integer SLA_Hi = -1; integer SLA_temp, BoundarySwitch; parameter Mem_T = 4'd0; parameter SS_T = 4'd1; parameter AS_CFI_T = 4'd2; reg [7:0] ReadTarget; // Power Up time tVCS is 30 us initial begin : PowerupTime PoweredUp = 1'b0; #30000000 PoweredUp = 1'b1; sgsaT[0] = 30'h000000; sgsaT[1] = 30'h1F8000; sgsaB[0] = 30'h000000; sgsaB[1] = 30'h008000; end // initialize memory and load preoload files if any initial begin: InitMemory integer i,j; integer secsi[0:8'hFF]; tmp_timing = TimingModel; i = 19; while ((i >= 0) && (found != 1'b1))//search for first non null character begin //i keeps position of first non null character j = 7; while ((j >= 0) && (found != 1'b1)) begin if (tmp_timing[i*8+j] != 1'd0) found = 1'b1; else j = j-1; end i = i - 1; end if (found)//if non null character is found begin for (j=0;j<=7;j=j+1) begin tmp_char[j] = tmp_timing[(i-14)*8+j]; end end for (i=0;i<=8'hFF;i=i+1) begin secsi[i]=MaxData; end for (i=0;i<=MemSize;i=i+1) begin Mem[i]=MaxData; end if (UserPreload && !(mem_file_name == "none")) begin $readmemh(mem_file_name,Mem); end if (UserPreload && !(secsi_file_name == "none")) begin $readmemh(secsi_file_name,secsi); end //SecSi Preload for (i=0;i<=8'hFF;i=i+1) begin SecSiMem[i] = secsi[i]; end end //////////////////////////////////////////////////////////////////////////// //// obtain 'LAST_EVENT information //////////////////////////////////////////////////////////////////////////// always @(negedge OENeg) begin OENeg_event = $time; end always @(negedge CENeg) begin CENeg_event = $time; end ////////////////////////////////////////////////////////// // Output Data Gen ////////////////////////////////////////////////////////// always @(Dout_zd) begin : OutputGen if (Dout_zd[0] !== 1'bz) begin abc = 1'b1; abc <= #1 1'b0; CEDQ_t = CENeg_event + CEDQ_01; OEDQ_t = OENeg_event + OEDQ_01; ADDRDQ_t = ADDR_event + ADDRDQIN_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; #( ADDRDQ_t - $time ) Dout_pass = TempData; end else if ((OEDQ_t < $time && CEDQ_t < $time ) && (ADDRDQ_t > $time )) begin TempData = Dout_zd; #( ADDRDQ_t - $time ) Dout_pass = TempData; end else begin Dout_pass = Dout_zd; end end end always @(Dout_zd) begin if (Dout_zd[0] === 1'bz) begin disable OutputGen; FROMCE = 1'b1; FROMOE = 1'b1; Dout_pass = Dout_zd; end end always @(Dout_pass) begin if (Dout_pass[0] != 1 && Dout_pass[0] != 0 && Dout_pass[0] !== 1'bz) D_pass = 1; else D_pass = 0; end // check when data is generated from model to avoid setuphold check in // those occasion always @(Din, Dout) begin if (Din==Dout) deq=1'b1; else deq=1'b0; end assign deg=deq; always @(falling_edge_RESETNeg ) begin: RSTtiming #(50000-1) RST = 0; end always @(rising_edge_RESETNeg) begin disable RSTtiming; #1 RST = 1; end // sequential process for reset control and FSM state transition always @(next_state_event, RST, PoweredUp) begin: StateTransition if (PoweredUp) begin if (RESETNeg) begin if (next_state_event) current_state = next_state; reseted = 1; end else if (~RESETNeg && ~RST) begin // no state transition while RESETNeg is low current_state = IDLE_RST; reseted = 0; end end else begin current_state = IDLE_RST; reseted = 0; end end //////////////////////////////////////////////////////////////////////////// // Glitch Protection: Inertial Delay does not propagate pulses <2ns //////////////////////////////////////////////////////////////////////////// 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 // Clock active edge -> CLKMerge rising edge, needed for burst sequences always @(rising_edge_CLK) begin: CLKGen if (rising_edge_CLK) begin CLKMerge = 1; #1 CLKMerge = 0; end end always @(rising_edge_START_in) begin : Start_time if (rising_edge_START_in) begin START_out = 0; START_out <= #(tdevice_START) 1; end else START_out = 0; end always @(IACC_in) begin : TIACCB if (~IACC_in) IACC_out = 0; else #(tdevice_IACC - 1) IACC_out = 1; end // Address Latch and Bus Cycle Decode always @(falling_edge_gWE_n, falling_edge_gCE_n, falling_edge_AVDNeg, rising_edge_gWE_n , rising_edge_gCE_n, rising_edge_AVDNeg, falling_edge_CENeg, rising_edge_CENeg, rising_edge_CLK, A_event, falling_edge_OENeg) begin : BusCycleDecode // Write address latch if (falling_edge_AVDNeg && ~WENeg) AsynWrAddLatch = 1; if (rising_edge_AVDNeg && ~CENeg && OENeg && AsynWrAddLatch) begin WrAddressLatched = A; AsynWrAddLatch = 0; end if (RESETNeg && ((rising_edge_gWE_n && ~gCE_n) || (rising_edge_gWE_n && rising_edge_gCE_n)) && OENeg) begin // write operation SecAddr = ReturnSectorID(WrAddressLatched); BankID = ReturnBank(WrAddressLatched); Addr = WrAddressLatched; BuffPageAddr = ReturnBuffPage(WrAddressLatched); D_tmp = Din; WRITE = 0; WRITE <= #1 1; end if (reseted && ConfReg[15]) begin // Asynchronous Mode address latch if ((falling_edge_AVDNeg || (A_event && ~AVDNeg)) && WENeg) begin // tACC count AddrREF = ~AddrREF; ADDR_event = $time; end if (rising_edge_AVDNeg && ~CENeg && WENeg) begin AddressLatched = A; end if ((falling_edge_OENeg || falling_edge_CENeg || (A_event && ~AVDNeg)) && WENeg && ~CENeg && ~OENeg) begin // Initiate Read SecAddr = ReturnSectorID(AddressLatched); BankID = ReturnBank(AddressLatched); BuffPageAddr = ReturnBuffPage(AddressLatched); Addr = AddressLatched; READ = 1'b0; #1 READ = 1'b1; end end else if (reseted && ~ConfReg[15]) begin if (falling_edge_AVDNeg) begin LATCHED = 0; AVDLATCHED = 0; READCYCLE = 0; end // Initiate READ (Burst mode) if (rising_edge_CLK && READCYCLE) begin READCYCLE = 0; IACC_in <= #1 1; BURST = 0; BURST <= #1 1; if (AVDLATCHED) begin // tACC count AddrREF = ~AddrREF; ADDR_event = $time; end Check_freq = 1; end // Synchronous CLK active edge address latch if (rising_edge_CLK && WENeg && ~CENeg && ~AVDNeg && ~LATCHED) begin READCYCLE = 1; LATCHED = 1; AddressLatched = A; SecAddr = ReturnSectorID(AddressLatched); BankID = ReturnBank(AddressLatched); BuffPageAddr = ReturnBuffPage(AddressLatched); Addr = AddressLatched; BurstDelay = 0; ADDR_event = $time; IACC_in = 0; IACC_in <= #1 1; AddrREF = ~AddrREF; end // Synchronous AVD# rising edge address latch if (rising_edge_AVDNeg && WENeg && ~CENeg && ~LATCHED) begin READCYCLE = 1; LATCHED = 1; AVDLATCHED = 1; AddressLatched = A; SecAddr = ReturnSectorID(AddressLatched); BankID = ReturnBank(AddressLatched); BuffPageAddr = ReturnBuffPage(AddressLatched); Addr = AddressLatched; BurstDelay = 1; IACC_in = 0; end if ((falling_edge_gWE_n || falling_edge_gCE_n) && ~gCE_n && ~gWE_n && gOE_n) begin READCYCLE = 0; end // Initiate READ, Synchronous mode if (falling_edge_OENeg && WENeg && ~CENeg) begin // Initiate read SecAddr = ReturnSectorID(AddressLatched); BankID = ReturnBank(AddressLatched); BuffPageAddr = ReturnBuffPage(AddressLatched); Addr = AddressLatched; READ = 0; #1 READ = 1; end end end event pdone_event, edone_event; // Timing control for the Write Buffer Program Operation // start/ suspend/ resume always @(rising_edge_reseted, rising_edge_PSTART, rising_edge_PSUSP, rising_edge_PRES) begin : ProgTime wrbo = tdevice_WRBO; if (rising_edge_reseted) PDONE = 1; // reset done, programing terminated else if (reseted) begin if (rising_edge_PSTART && PDONE) begin start = $time; elapsed = 0; duration = (WrBuffCnt + 1) * wrbo; PDONE = 0; -> pdone_event; end else if (rising_edge_PSUSP && ~PDONE) begin elapsed = $time - start; duration = duration - elapsed; disable pdone_process; PDONE = 0; end else if (rising_edge_PRES && ~PDONE) begin start = $time; PDONE = 0; -> pdone_event; end end end always @(pdone_event) begin : pdone_process #(duration) PDONE = 1; end // Timing control for the Erase Operations always @(rising_edge_ESTART, rising_edge_reseted, rising_edge_ESUSP, rising_edge_ERES) begin : ErsTime seo16 = tdevice_SEO16_ts; seo64 = tdevice_SEO64_ts; if (rising_edge_reseted) EDONE = 1; // reset done, ERASE terminated else if (reseted) begin if (rising_edge_ESTART && EDONE) begin start = $time; elapsed = 0; if ((SA_ERS<=3 && tmp_char == "1" ) || (SA_ERS >= (SecNum -3) && tmp_char == "0" )) duration = seo16; else duration = seo64; elapsed = 0; EDONE = 0; -> edone_event; start = $time; end else if (rising_edge_ESUSP && ~EDONE) begin elapsed = $time - start; duration = duration - elapsed; disable edone_process; EDONE = 0; end else if (rising_edge_ERES && ~EDONE) begin start = $time; EDONE = 0; -> edone_event; end end end always @(edone_event) begin : edone_process #(duration) EDONE = 1; end time CLK_PER = 0; time LAST_CLK = 0; // Process that determines clock frequency always @(rising_edge_CLK) begin : CLK_FREQ if (rising_edge_CLK) begin CLK_PER = $time - LAST_CLK; LAST_CLK = $time; #1; if (~ConfReg[15] && Check_freq) begin if ((CLK_PER < 37037 && WS_Initial < 4) || (CLK_PER < 25000 && WS_Initial < 5) || (CLK_PER < 18518 && WS_Initial < 6) || (CLK_PER < 15151 && WS_Initial < 7) || (CLK_PER < 12048 && WS_Initial < 8) || (CLK_PER < 10526 && WS_Initial < 9) || (CLK_PER < 9615 && WS_Initial < 10)) begin $display ("More wait states are required for"); $display ("this clock frequency value"); end end Check_freq = 0; end end ///////////////////////////////////////////////////////////////////// // Main Behavior Process // combinational process for next state generation ///////////////////////////////////////////////////////////////////// always @(falling_edge_WRITE, reseted, rising_edge_CEDONE, rising_edge_EDONE, rising_edge_START_out, rising_edge_PDONE) begin : StateGen if (falling_edge_WRITE) begin Data = D_tmp; DataLo = D_tmp % 12'h100; AddrCom = Addr % 16'h1000; end if (reseted != 1) next_state = current_state; else begin case (current_state) IDLE_RST: begin if (falling_edge_WRITE) begin if (AddrCom == 12'h555 && DataLo == 8'h80) next_state = ERASE_ENTRY; else if (((AddrCom % 12'h100) == 12'h55) && ((DataLo == 8'h90) || (DataLo == 8'h98))) next_state = AS_CFI_ENTRY; else if (AddrCom == 12'h555 && DataLo == 8'h60) next_state = SL_ENTRY; else if (AddrCom == 16'h555 && DataLo == 16'h40 && ((tmp_char == "1" && SecAddr==SecNum) || (tmp_char == "0" && SecAddr==0))) next_state = LR_ENTRY; else if (AddrCom == 12'h555 && DataLo == 8'h88) next_state = SecSi_ENTRY; else if (AddrCom == 12'h555 && DataLo == 8'hD0) next_state = CR_ENTRY; else if (AddrCom == 12'h555 && DataLo == 8'h25) next_state = W2B_ENTRY; else next_state = IDLE_RST; end end ERASE_ENTRY: begin if (falling_edge_WRITE) begin if (AddrCom == 12'h2AA && DataLo == 8'h10 && SecAddr == SA_ERS && (SL_REG == 0 || SL_REG == -2) && VPP != 0 && ~LockRangeDone) next_state = CERS; else if (AddrCom == 12'h2AA && DataLo == 8'h30 && SecAddr == SA_ERS && (SecAddr == SL_REG || SL_REG == -2) && VPP != 0) next_state = SERS; else if ((DataLo % 8'h10) == 8'hC) begin end else next_state = IDLE_RST; end end SL_ENTRY: begin if (falling_edge_WRITE) begin if (AddrCom == 12'h555 && DataLo == 8'h60) next_state = SL_Change; else if ((DataLo % 8'h10) == 8'hC) begin end else if (ESP_ACT) next_state = SERS_SUS; else next_state = IDLE_RST; end end LR_ENTRY: begin if (falling_edge_WRITE) begin if (AddrCom == 12'h555 && DataLo == 8'h25 && SecAddr == SA_LR) next_state = W2B_ENTRY; else if (DataLo == 8'hf0) next_state = IDLE_RST; end end SecSi_ENTRY: begin if (falling_edge_WRITE) begin if (AddrCom == 12'h555 && DataLo == 8'h25 && SecAddr == SA_SecSi) next_state = W2B_ENTRY; else if (DataLo == 8'hf0) next_state = IDLE_RST; end end CR_ENTRY: begin if (falling_edge_WRITE) begin if (AddrCom == 12'h555 && DataLo == 8'h25 && SecAddr == SA_CR) next_state = W2B_ENTRY; else if (DataLo == 8'hf0) next_state = IDLE_RST; end end W2B_ENTRY: begin if (falling_edge_WRITE) begin if (AddrCom == 12'h2AA && SecAddr == SA_PGM && (((SecAddr == SL_REG || SL_REG == -2) && VPP != 0) || (SecSi && VPP != 0) || LOCK_ACT || CR_ACT) && !(SecSi && LOCK_REG[0] == 0) && !(LOCK_ACT && DataLo >0) && !(CR_ACT && DataLo >0) && !(ESP_ACT && SecAddr == SA_ERS)) next_state = W2B_WC; else if ((DataLo % 8'h10) == 8'hC) begin end else if (ESP_ACT) next_state = SERS_SUS; else if (LOCK_ACT) next_state = LR_ENTRY; else if (CR_ACT) next_state = CR_ENTRY; else if (SecSi) next_state = SecSi_ENTRY; else begin next_state = IDLE_RST; end end end AS_CFI_ENTRY: begin if (falling_edge_WRITE) begin if (DataLo == 8'hf0) next_state = IDLE_RST; end end CERS: begin if (rising_edge_CEDONE) begin next_state = IDLE_RST; end end SERS: begin if (rising_edge_EDONE) next_state = IDLE_RST; else if (falling_edge_WRITE) begin if (DataLo == 8'hB0) next_state = SERS_SL; end end SL_Change: begin if (falling_edge_WRITE) begin if (DataLo == 8'h61) next_state = LOCK_RANGE; else if ((DataLo % 8'h10) == 8'hC) begin end else if (ESP_ACT) next_state = SERS_SUS; else next_state = IDLE_RST; end end W2B_WC: begin if (falling_edge_WRITE) begin if (SecAddr == SA_PGM && !(SecSi && (ReturnAddr(Addr, SA_SecSi) < 64 || ReturnAddr(Addr,SA_SecSi) > 127)) && !(LOCK_ACT && ((AddrCom % 12'h100) != 0)) && !(CR_ACT && ((AddrCom % 12'h100) > 2)) && WC == 0) next_state = WB_LOADED; else if (SecAddr == SA_PGM && !(SecSi && (ReturnAddr(Addr,SA_SecSi) < 64 || ReturnAddr(Addr,SA_SecSi) > 127)) && !((Addr+WC) / (WrBuffLength+1)> Addr / (WrBuffLength+1)) && ~LOCK_ACT && ~CR_ACT) next_state = W2BUF_PG; else if ((DataLo % 8'h10) == 8'hC) begin end else if (ESP_ACT) next_state = SERS_SUS; else if (LOCK_ACT) next_state = LR_ENTRY; else if (CR_ACT) next_state = CR_ENTRY; else if (SecSi) next_state = SecSi_ENTRY; else next_state = IDLE_RST; end end SERS_SL : begin if (rising_edge_START_out) next_state = SERS_SUS; end LOCK_RANGE: begin if (falling_edge_WRITE) begin if ((DataLo % 8'h10) == 8'hC) begin end else if (ESP_ACT) next_state = SERS_SUS; else next_state = IDLE_RST; end end W2BUF_PG: begin if (falling_edge_WRITE) begin if (!(Addr > PrevAddr)) begin if (ESP_ACT) next_state = SERS_SUS; else if (SecSi) next_state = SecSi_ENTRY; else next_state = IDLE_RST; end else if (WC == 0) next_state = WB_LOADED; end end WB_LOADED: begin if (falling_edge_WRITE) begin if (AddrCom == 12'h555 && DataLo == 8'h29 && ((WrBuffAddr[WrBuffCnt]/32) == (WrBuffAddr[0]/32)) && SecAddr == SA_PGM) next_state = PGM; else if ((DataLo % 8'h10) == 8'hC) begin end else if (ESP_ACT) next_state = SERS_SUS; else if (LOCK_ACT) next_state = LR_ENTRY; else if (CR_ACT) next_state = CR_ENTRY; else if (SecSi) next_state = SecSi_ENTRY; else next_state = IDLE_RST; end end SERS_SUS: begin if (falling_edge_WRITE) begin if (DataLo == 8'h30) next_state = SERS; else if (AddrCom == 12'h555 && DataLo == 8'h60) next_state = SL_ENTRY; else if (AddrCom == 12'h555 && DataLo == 8'h25) next_state = W2B_ENTRY; end end PGM: begin if (rising_edge_PDONE) begin if (ESP_ACT) next_state = SERS_SUS; else if (LOCK_ACT) next_state = LR_ENTRY; else if (CR_ACT) next_state = CR_ENTRY; else if (SecSi) next_state = SecSi_ENTRY; else next_state = IDLE_RST; end else if (falling_edge_WRITE) if (DataLo == 8'h51) next_state = PGM_SL; end PGM_SL: begin if (rising_edge_START_out) next_state = PGM_SUS; end PGM_SUS: begin if (falling_edge_WRITE) if (DataLo == 8'h50) next_state = PGM; end endcase end end ///////////////////////////////////////////////////////////////////////// // Main Behavior Process // combinational process for Read Mode Generation ///////////////////////////////////////////////////////////////////////// always @(falling_edge_RST, falling_edge_BURST, rising_edge_gCE_n, falling_edge_AVDNeg, falling_edge_gWE_n, BURST_TR, SYNCREAD) begin : ReadModeGen BURST_TR = 0; SYNCREAD = 0; if (falling_edge_RST && ~RESETNeg) RD_MODE = NOSYNC; if (reseted) begin case (current_state) IDLE_RST: begin if (falling_edge_BURST) begin if (STAT_ACT && SecAddr == SA_SR) SYNCREAD = 1; else BURST_TR = 1; end end ERASE_ENTRY: begin if (falling_edge_BURST) BURST_TR = 1; end SL_ENTRY: begin if (falling_edge_BURST) begin if (ESP_ACT && SecAddr == SA_ERS) SYNCREAD = 1; else BURST_TR = 1; end end LR_ENTRY: begin if (falling_edge_BURST) begin if (SecAddr == SA_LR) SYNCREAD = 1; else BURST_TR = 1; end end SecSi_ENTRY: begin if (falling_edge_BURST) begin if (SecAddr == SA_SecSi && ReturnAddr(Addr,SA_SecSi) > 8'hff) SYNCREAD = 1; else BURST_TR = 1; end end CR_ENTRY: begin if (falling_edge_BURST) begin if (SecAddr == SA_CR) SYNCREAD = 1; else BURST_TR = 1; end end W2B_ENTRY: begin if (falling_edge_BURST) begin if ((ESP_ACT && SecAddr == SA_ERS) || (LOCK_ACT && SecAddr == SA_LR) || (CR_ACT && SecAddr == SA_CR) || (SecSi && SecAddr == SA_SecSi && Addr > 8'hFF)) SYNCREAD = 1; else BURST_TR = 1; end end AS_CFI_ENTRY: begin if (falling_edge_BURST) begin if (SecAddr == SA_AS_CFI && (ReturnAddr(Addr,SA_AS_CFI) > 8'h7F)) SYNCREAD = 1; else BURST_TR = 1; end end CERS: begin if (falling_edge_BURST) SYNCREAD = 1; end SERS: begin if (falling_edge_BURST) begin if (BankID == BA_ERS || (STAT_ACT && SecAddr == SA_SR)) SYNCREAD = 1; else BURST_TR = 1; end end SL_Change: begin if (falling_edge_BURST) begin if (ESP_ACT && SecAddr == SA_ERS) SYNCREAD = 1; else BURST_TR = 1; end end W2B_WC: begin if (falling_edge_BURST) begin if ((ESP_ACT && SecAddr == SA_ERS) || (LOCK_ACT && SecAddr == SA_LR) || (CR_ACT && SecAddr == SA_CR) || (SecSi && SecAddr == SA_SecSi && Addr > 8'hFF)) SYNCREAD = 1; else BURST_TR = 1; end end SERS_SL: begin if (falling_edge_BURST) begin if (BankID == BA_ERS || (STAT_ACT && SecAddr == SA_SR)) SYNCREAD = 1; else BURST_TR = 1; end end LOCK_RANGE: begin if (falling_edge_BURST) begin if (ESP_ACT && SecAddr == SA_ERS) SYNCREAD = 1; else BURST_TR = 1; end end W2BUF_PG: begin if (falling_edge_BURST) begin if ((ESP_ACT && SecAddr == SA_ERS) || (SecSi && SecAddr == SA_SecSi && Addr > 8'hFF)) SYNCREAD = 1; else BURST_TR = 1; end end WB_LOADED: begin if (falling_edge_BURST) begin if ((ESP_ACT && SecAddr == SA_ERS) || (LOCK_ACT && SecAddr == SA_LR) || (CR_ACT && SecAddr == SA_CR) || (SecSi && SecAddr == SA_SecSi && Addr > 8'hFF)) SYNCREAD = 1; else BURST_TR = 1; end end SERS_SUS: begin if (falling_edge_BURST) begin if (SecAddr == SA_ERS || (STAT_ACT && SecAddr == SA_SR)) SYNCREAD =1; else BURST_TR = 1; end end PGM: begin if (falling_edge_BURST) begin if (BankID == BA_PGM || (ESP_ACT && SecAddr == SA_ERS) || (STAT_ACT && SecAddr == SA_SR)) SYNCREAD = 1; else BURST_TR = 1; end end PGM_SL: begin if (falling_edge_BURST) begin if (BankID == BA_PGM || (ESP_ACT && SecAddr == SA_ERS) || (STAT_ACT && SecAddr == SA_SR)) SYNCREAD = 1; else BURST_TR = 1; end end PGM_SUS: begin if (falling_edge_BURST) begin if (BuffPageAddr == PA_PGM || (ESP_ACT && SecAddr == SA_ERS) || (LOCK_ACT && SecAddr == SA_LR) || (CR_ACT && SecAddr == SA_CR) || (SecSi && SecAddr == SA_SecSi && Addr > 8'hFF) || (STAT_ACT && SecAddr == SA_SR)) SYNCREAD = 1; else BURST_TR = 1; end end endcase if ((rising_edge_gCE_n || falling_edge_AVDNeg || falling_edge_gWE_n) && (RD_MODE != NOSYNC)) begin RD_MODE = NOSYNC; end if (BURST_TR) begin RD_MODE = LINEAR; ReadINIT = 0; ReadINIT <= #1 1; end else if (SYNCREAD) begin RD_MODE = SYNCR; ReadINIT = 0; ReadINIT <= #1 1; end end end /////////////////////////////////////////////////////////////////////// // FSM Output generation and general funcionality /////////////////////////////////////////////////////////////////////// always @(falling_edge_WRITE, rising_edge_EDONE, rising_edge_CEDONE, ER_FLAG, falling_edge_AVDNeg, falling_edge_RST, falling_edge_READ, rising_edge_CENeg, rising_edge_OENeg, rising_edge_PDONE, rising_edge_START_out, rising_edge_CLKMerge, falling_edge_OENeg, falling_edge_ReadINIT) begin : Functional if (falling_edge_WRITE) begin Data = D_tmp; DataLo = D_tmp % 12'h100; AddrCom = Addr % 16'h1000; end oe = falling_edge_READ; if (falling_edge_RST && ~RESETNeg) begin LockRangeDone = 0; ESP_ACT = 0; LOCK_ACT = 0; CR_ACT = 0; SecSi = 0; ConfReg = 16'b1111111101001010; START_in = 0; CEDONE = 1; STAT_ACT = 0; Status[7:0] = 8'b10000000; end if (falling_edge_ReadINIT) begin INITIAL = 1; BurstAddr = Addr; BurstSec = SecAddr; if (ConfReg[2:0] == 2) BurstLength = 8; else if (ConfReg[2:0] == 3) BurstLength = 16; else BurstLength = 0; RDCnt = BurstLength; BurstDelay = BurstDelay + WS_Initial - 1; IN_W_ELAPSED = 0; DATA_DELAY = 0; BURST_END = 0; if (current_state == AS_CFI_ENTRY && BurstSec == SA_AS_CFI) ReadTarget = AS_CFI_T; else if (SecSi && BurstSec == SA_SecSi) ReadTarget = SS_T; else ReadTarget = Mem_T; end if (reseted) begin case (current_state) IDLE_RST: begin if (falling_edge_WRITE) begin if (AddrCom == 16'h555 && DataLo == 16'h80) begin SA_ERS = SecAddr; BA_ERS = BankID; STAT_ACT = 0; end else if (AddrCom == 16'h555 && DataLo == 16'h40 && ((tmp_char == "1" && SecAddr==SecNum) || (tmp_char == "0" && SecAddr==0))) begin SA_LR = SecAddr; LOCK_ACT = 1; STAT_ACT = 0; end else if (AddrCom == 16'h555 && DataLo == 16'h88) begin SA_SecSi = SecAddr; SecSi = 1; STAT_ACT = 0; end else if (AddrCom == 16'h555 && DataLo == 16'hD0) begin SA_CR = SecAddr; ConfRegtemp = ConfReg; CR_ACT = 1; STAT_ACT = 0; end else if (AddrCom == 16'h555 && DataLo == 16'h25) begin SA_PGM = SecAddr; BA_PGM = BankID; STAT_ACT = 0; end else if ((AddrCom % 16'h100 == 16'h55) && ((DataLo == 16'h98) || (DataLo == 16'h90))) begin SA_AS_CFI = SecAddr; STAT_ACT = 0; end else if (AddrCom == 16'h555 && DataLo == 16'h70 && ~STAT_ACT) begin SA_SR = SecAddr; STAT_ACT = 1; end else if (AddrCom == 16'h555 && DataLo == 16'h71) begin Status[7:0] = 8'b10000000; STAT_ACT = 0; end else STAT_ACT = 0; end if (oe) begin if (STAT_ACT && SecAddr == SA_SR) begin Status[0] = 0; Dout_zd = Status; STAT_ACT = 0; end else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end ERASE_ENTRY: begin if (falling_edge_WRITE) begin if (AddrCom == 16'h2AA && DataLo == 16'h10) begin if (SecAddr == SA_ERS && (SL_REG == 0 || SL_REG == -2) && VPP != 0 && ~LockRangeDone) begin CEDONE = 0; CEDONE <= #((SecNum-3)*tdevice_SEO64_ts + 4*tdevice_SEO16_ts) 1; Status[7] = 0; Status[5] = 0; Status[1] = 0; ER_FLAG = 0; end else begin Status[5] = 1; if (SecAddr == SA_ERS) Status[1] = 1; else Status[1] = 0; end end else if (AddrCom == 16'h2AA && DataLo== 16'h30) begin if (SecAddr == SA_ERS && VPP != 0 && (SecAddr == SL_REG || SL_REG == -2)) begin ESTART = 1; ESTART <= #1 0; Status[7] = 0; Status[5] = 0; Status[1] = 0; ER_FLAG = 0; end else begin Status[5] = 1; if (SecAddr == SA_ERS) Status[1] = 1; else Status[1] = 0; end end else if ((DataLo % 8'h10) == 8'hC) begin end else Status[5] = 1; end if (oe) begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end SL_ENTRY: begin if (oe) begin if (ESP_ACT && SecAddr == SA_ERS) Dout_zd = 16'b0; else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end LR_ENTRY: begin if (falling_edge_WRITE) begin if (AddrCom == 16'h555 && DataLo == 16'h25 && SecAddr == SA_LR) begin SA_PGM = SecAddr; BA_PGM = BankID; end else if (DataLo == 8'hF0) LOCK_ACT = 0; end if (oe) begin if (SecAddr == SA_LR) Dout_zd = LOCK_REG; else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end SecSi_ENTRY: begin if (falling_edge_WRITE) begin if (AddrCom == 16'h555 && DataLo == 16'h25 && SecAddr == SA_SecSi) begin SA_PGM = SecAddr; BA_PGM = BankID; end else if (DataLo == 8'hF0) SecSi = 0; end if (oe) begin if (SecAddr == SA_SecSi) begin READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); Dout_zd = OutputD; end else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end CR_ENTRY: begin if (falling_edge_WRITE) begin if (AddrCom == 16'h555 && DataLo == 16'h25 && SecAddr == SA_CR) begin SA_PGM = SecAddr; BA_PGM = BankID; end else if (DataLo == 16'hF0) begin ConfReg = ConfRegtemp; WS_Initial = ConfReg[13:11] +2; CR_ACT = 0; end end if (oe) begin if (SecAddr == SA_CR) begin if (Addr % 16'h100 == 0) Dout_zd = ConfReg; else Dout_zd = 16'b0; end else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end W2B_ENTRY: begin if (falling_edge_WRITE) begin if (AddrCom == 16'h2AA) begin if (SecAddr == SA_PGM && (((SecAddr == SL_REG || SL_REG == -2) && VPP != 0) || (SecSi && VPP != 0) || LOCK_ACT || CR_ACT) && !(SecSi && LOCK_REG[0] == 0) && !(LOCK_ACT && DataLo>0) && !(CR_ACT && DataLo>0) && !(ESP_ACT && SecAddr == SA_ERS)) begin WC = DataLo % (WrBuffLength+1); WrBuffCnt = DataLo % (WrBuffLength+1); end else begin Status[4] = 1; if ((SecAddr == SA_PGM) && ~LOCK_ACT && ~CR_ACT && !(ESP_ACT && SecAddr == SA_ERS)) Status[1] = 1; else Status[1] = 0; end end else if ((DataLo % 8'h10) == 8'hC) begin end else Status[4] = 1; end if (oe) begin if (ESP_ACT && SecAddr == SA_ERS) Dout_zd = 16'b0; else if (LOCK_ACT && SecAddr == SA_LR) Dout_zd = LOCK_REG; else if (CR_ACT && SecAddr == SA_CR) begin if ((Addr % 12'h100) == 0) Dout_zd = ConfReg; else Dout_zd = 16'b0; end else if (SecSi && SecAddr == SA_SecSi) begin READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); Dout_zd = OutputD; end else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end AS_CFI_ENTRY: begin if (oe) begin if (SecAddr == SA_AS_CFI) begin tmpaddr = ReturnAddr(Addr,SecAddr); READMEM(tmpaddr,SecAddr,AS_CFI_T); Dout_zd = OutputD; end else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end CERS: begin if (~ER_FLAG) begin ER_FLAG = 1; for (i=0; i<= MemSize; i=i+1) Mem[i] = -1; end if (rising_edge_CEDONE) begin for (i=0; i<= MemSize; i=i+1) Mem[i] = MaxData; Status[7] = 1; STAT_ACT = 0; end if (falling_edge_WRITE) begin if (AddrCom == 16'h555 && DataLo == 16'h70 && ~STAT_ACT) begin SA_SR = SecAddr; STAT_ACT = 1; end else STAT_ACT = 0; end if (oe) begin if (STAT_ACT && SecAddr == SA_SR) begin Status[0] = 0; Dout_zd = Status; STAT_ACT = 0; end else Dout_zd = 16'b0; end end SERS: begin if (~ER_FLAG) begin ER_FLAG = 1; if (SA_ERS <= 3 && tmp_char=="1") begin for (j=SA_ERS*(SecSize16+1)+sgsaB[0]; j<=SA_ERS*(SecSize16+1)+sgsaB[0]+SecSize16; j=j+1) Mem[j] = -1; end else if (tmp_char == "1") begin for (j=(SA_ERS-4)*(SecSize64+1)+sgsaB[1]; j<= (SA_ERS-4)*(SecSize64+1)+sgsaB[1]+SecSize64; j=j+1) Mem[j] = -1; end else if (SA_ERS < (SecNum-3) && tmp_char == "0" ) begin for (j=SA_ERS*(SecSize64+1)+sgsaT[0]; j<= SA_ERS*(SecSize64+1)+sgsaT[0]+SecSize64; j=j+1) Mem[j] = -1; end else begin for (j=(SA_ERS-(SecNum-3))*(SecSize16+1)+sgsaT[1]; j<= (SA_ERS-(SecNum-3))*(SecSize16+1)+sgsaT[1]+ +SecSize16; j=j+1) Mem[j] = -1; end end if (rising_edge_EDONE) begin if (SA_ERS <= 3 && tmp_char=="1" ) begin for (j=SA_ERS*(SecSize16+1)+sgsaB[0]; j<=SA_ERS*(SecSize16+1)+sgsaB[0]+SecSize16; j=j+1) Mem[j] = MaxData; end else if (tmp_char == "1") begin for (j=(SA_ERS-4)*(SecSize64+1)+sgsaB[1]; j<= (SA_ERS-4)*(SecSize64+1)+sgsaB[1]+SecSize64; j=j+1) Mem[j] = MaxData; end else if (SA_ERS < (SecNum-3) && tmp_char == "0" ) begin for (j=SA_ERS*(SecSize64+1)+sgsaT[0]; j<= SA_ERS*(SecSize64+1)+sgsaT[0]+SecSize64; j=j+1) Mem[j] = MaxData; end else begin for (j=(SA_ERS-(SecNum-3))*(SecSize16+1)+sgsaT[1]; j<= (SA_ERS-(SecNum-3))*(SecSize16+1)+sgsaT[1]+ SecSize16; j=j+1) Mem[j] = MaxData; end Status[7] = 1; STAT_ACT = 0; end if (falling_edge_WRITE) begin if (DataLo == 16'hB0) begin ESUSP = 1; ESUSP <= #1 0; START_in = 1; STAT_ACT = 0; end else if (AddrCom == 16'h555 && DataLo == 16'h70 && ~STAT_ACT) begin SA_SR = SecAddr; STAT_ACT = 1; end else STAT_ACT = 0; end if (oe) begin if (STAT_ACT && SecAddr == SA_SR) begin if (BankID == BA_ERS) Status[0] = 0; else Status[0] = 1; Dout_zd = Status; STAT_ACT = 0; end else if (BankID == BA_ERS) Dout_zd = 16'b0; else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end SL_Change: begin if (falling_edge_WRITE) begin if (DataLo == 16'h60 && (Addr % 16'h80)/16'h40 == 0 && (SecAddr == SL_REG || SL_REG == -2)) SL_REG = -1; else if (DataLo == 16'h60 && (Addr % 16'h80)/16'h40 == 1 && SL_REG == -1 && (SecAddr < SLA_Lo || SecAddr > SLA_Hi)) begin if ((tmp_char == "1") && (SecAddr <= 3) && (SLA_SMALL[SecAddr] == 0)) SL_REG = SecAddr; else if ((tmp_char == "1") && (SecAddr > 3)) SL_REG = SecAddr; else if ((tmp_char == "0") && (SecAddr > SecNum-4) && (SLA_SMALL[SecNum - SecAddr] == 0)) SL_REG = SecAddr; else if ((tmp_char == "0") && (SecAddr <= SecNum-4)) SL_REG = SecAddr; end else if (DataLo == 16'h61 && ~LockRangeDone) begin SLA_SMALL_tmp [3:0] = Addr % 8'h10; LockRange = 1; SLA_temp = SecAddr; A6Lock = ((Addr % 16'h80)/16'h40 == 0); end else if (DataLo == 16'h61) LockRange = 0; end if (oe) begin if (ESP_ACT && SecAddr == SA_ERS) Dout_zd = 16'h0; else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end W2B_WC: begin if (falling_edge_WRITE) begin if (SecAddr == SA_PGM && !(SecSi && (ReturnAddr(Addr, SA_SecSi) < 64 || ReturnAddr(Addr,SA_SecSi) > 127)) && !(LOCK_ACT && ((AddrCom % 12'h100) != 0)) && !(CR_ACT && ((AddrCom % 12'h100) > 2)) && WC == 0) begin PrevAddr <= #1 Addr; WrBuffAddr[0] = Addr; WrBuffData[0] = Data; PA_PGM = BuffPageAddr; end else if (SecAddr == SA_PGM && !(SecSi && (ReturnAddr(Addr,SA_SecSi) < 64 || ReturnAddr(Addr,SA_SecSi) > 127)) && !((Addr+WC) / (WrBuffLength+1)> Addr / (WrBuffLength+1)) && ~LOCK_ACT && ~CR_ACT) begin PrevAddr <= #1 Addr; WrBuffAddr[WC] = Addr; WrBuffData[WC] = Data; WC = WC -1; PA_PGM = BuffPageAddr; end else if ((DataLo % 8'h10) == 8'hC) begin end else Status[4] = 1; end if (oe) begin if (ESP_ACT && SecAddr == SA_ERS) Dout_zd = 16'b0; else if (LOCK_ACT && SecAddr == SA_LR) Dout_zd = LOCK_REG; else if (CR_ACT && SecAddr == SA_CR) begin if (Addr % 16'h100 == 0) Dout_zd = ConfReg; else Dout_zd = 16'b0; end else if (SecSi && SecAddr == SA_SecSi) begin READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); Dout_zd = OutputD; end else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end SERS_SL: begin if (rising_edge_START_out) begin START_in = 0; ESP_ACT = 1; Status[7] = 1; Status[6] = 1; STAT_ACT = 0; end if (falling_edge_WRITE) begin if (AddrCom== 16'h555 && DataLo== 16'h70 && ~STAT_ACT) begin SA_SR = SecAddr; STAT_ACT = 1; end else STAT_ACT = 0; end if (oe) begin if (STAT_ACT && SecAddr == SA_SR) begin if (BankID == BA_ERS) Status[0] = 0; else Status[0] = 1; Dout_zd = Status; STAT_ACT = 0; end else if (BankID == BA_ERS) Dout_zd = 16'b0; else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end LOCK_RANGE: begin if (falling_edge_WRITE) begin if (DataLo == 16'h61 && LockRange && (SecAddr >= SLA_temp) && A6Lock && (Addr % 8'h80)/8'h40 == 0) begin LockRangeDone = 1; SLA_Lo = SLA_temp; SLA_Hi = SecAddr; if (tmp_char=="1" && SLA_Lo < 4) begin SLA_Lo = 0; end else if (tmp_char=="0" && SLA_Lo > SecNum - 4) begin SLA_Lo = SecNum - 3; end if (tmp_char == "1" && SLA_Hi < 4) begin SLA_Hi = 3; end else if (tmp_char == "0" && SLA_Hi > SecNum - 4) begin SLA_Hi = SecNum; end begin if ((tmp_char=="1" && SLA_Lo != 0) || (tmp_char=="0" && SLA_Hi != SecNum)) SLA_SMALL = SLA_SMALL_tmp; end if (SL_REG >= SLA_Lo && SL_REG <= SLA_Hi) SL_REG = -1; end end if (oe) begin if (ESP_ACT && SecAddr == SA_ERS) Dout_zd = 16'b0; else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end W2BUF_PG: begin if (falling_edge_WRITE) begin if (Addr > PrevAddr) begin WrBuffAddr[WC] = Addr; WrBuffData[WC] = Data; PrevAddr <= #1 Addr; if (WC > 0) WC = WC - 1; end else Status[4] = 1; end if (oe) begin if (ESP_ACT && SecAddr == SA_ERS) Dout_zd = 16'b0; else if (SecSi && SecAddr == SA_SecSi) begin READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); Dout_zd = OutputD; end else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end WB_LOADED: begin if (falling_edge_WRITE) begin if (AddrCom == 12'h555 && DataLo == 8'h29 && ((WrBuffAddr[WrBuffCnt]/32) == (WrBuffAddr[0]/32)) && SecAddr == SA_PGM) begin PSTART = 1; PSTART <= #1 0; Status[7] = 0; Status[4] = 0; PR_FLAG = 0; end else if ((DataLo % 8'h10) == 8'hC) begin end else Status[4] = 1; end if (oe) begin if (ESP_ACT && SecAddr == SA_ERS) Dout_zd = 16'b0; else if (LOCK_ACT && SecAddr == SA_LR) Dout_zd = LOCK_REG; else if (CR_ACT && SecAddr == SA_CR) begin if ((Addr % 12'h100) == 0) Dout_zd = ConfReg; else Dout_zd = 16'b0; end else if (SecSi && SecAddr == SA_SecSi) begin READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); Dout_zd = OutputD; end else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end SERS_SUS: begin if (falling_edge_WRITE) begin if (DataLo == 16'h30) begin ERES = 1; ERES <= #1 0; ESP_ACT = 0; STAT_ACT = 0; Status[7] = 0; Status[6] = 0; end else if (AddrCom == 16'h555 && DataLo == 16'h25) begin SA_PGM = SecAddr; BA_PGM = BankID; STAT_ACT = 0; end else if (AddrCom == 16'h555 && DataLo == 16'h70 && ~STAT_ACT) begin SA_SR = SecAddr; STAT_ACT = 1; end else if (AddrCom == 16'h555 && DataLo == 16'h71) begin Status[7] = 1; Status[5:3] = 3'b000; Status[1:0] = 2'b00; STAT_ACT = 0; end else STAT_ACT = 0; end if (oe) begin if (STAT_ACT && SecAddr == SA_SR) begin Status[0] = 0; Dout_zd = Status; STAT_ACT =0; end else if (SecAddr == SA_ERS) Dout_zd = 16'h0; else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end PGM: begin if (~PR_FLAG) begin PR_FLAG = 1; if (~LOCK_ACT && ~CR_ACT) begin for (i=WrBuffCnt; i>=0; i=i-1) begin new_int = WrBuffData[i]; old_int = -1; if (SecSi == 1) begin j = ReturnAddr(WrBuffAddr[i],SA_SecSi); old_int = SecSiMem[j]; end else begin j = WrBuffAddr[i]; old_int = Mem[j]; end WrBuffData[i] = -1; if (new_int > -1) begin new_bit = new_int; if (old_int > -1) begin old_bit = old_int; for (j=0; j<= 15; j=j+1) begin if (old_bit[j] == 0) new_bit[j] = 0; end new_int = new_bit; end WrBuffData[i] = new_int; end end end if (LOCK_ACT && LOCK_REG[0]==1 && (WrBuffData[0] % 2 == 0)) LOCK_REG[0] = 1'bx; else if (CR_ACT && (WrBuffAddr[0] % 12'h100 == 0)) ConfRegtemp = 16'bx; else begin for (i=WrBuffCnt; i>=0; i=i-1) begin if (SecSi == 1) begin j = ReturnAddr(WrBuffAddr[i],SA_SecSi); SecSiMem[j] = -1; end else begin j = WrBuffAddr[i]; Mem[j] = -1; end end end end if (rising_edge_PDONE) begin if (LOCK_ACT && LOCK_REG[0] === 1'bx) LOCK_REG[0] = 0; else if (CR_ACT && (WrBuffAddr[0] % 12'h100 == 0)) ConfRegtemp = WrBuffData[0]; else begin for (i= WrBuffCnt; i>=0; i=i-1) begin if (SecSi == 1) begin j = ReturnAddr(WrBuffAddr[i],SA_SecSi); SecSiMem[j] = WrBuffData[i]; end else begin tmpaddr = WrBuffAddr[i]; tmpdata = WrBuffData[i]; Mem[tmpaddr] = tmpdata; end WrBuffData[i] = -1; end end Status[7] = 1; STAT_ACT = 0; end if (falling_edge_WRITE) begin if (DataLo == 16'h51) begin PSUSP = 1; #1 PSUSP = 0; START_in = 1; STAT_ACT = 0; end else if (AddrCom == 16'h555 && DataLo == 16'h70 && ~STAT_ACT) begin SA_SR = SecAddr; STAT_ACT = 1; end else STAT_ACT = 0; end if (oe) begin if (STAT_ACT && SecAddr == SA_SR) begin if (BankID == BA_PGM) Status[0] = 0; else Status[0] = 1; Dout_zd = Status; STAT_ACT = 0; end else if (BankID == BA_PGM || (ESP_ACT && SecAddr == SA_ERS)) Dout_zd = 16'h0; else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end PGM_SL: begin if (rising_edge_START_out) begin START_in = 0; Status[7] = 1; Status[2] = 1; STAT_ACT = 0; end if (falling_edge_WRITE) begin if (AddrCom == 16'h555 && DataLo == 16'h70 && ~STAT_ACT) begin SA_SR = SecAddr; STAT_ACT = 1; end else STAT_ACT = 0; end if (oe) begin if (STAT_ACT && SecAddr == SA_SR) begin if (BankID == BA_PGM) Status[0] = 0; else Status[0] = 1; Dout_zd = Status; STAT_ACT = 0; end else if (BankID == BA_PGM || (ESP_ACT && SecAddr == SA_ERS)) Dout_zd = 16'h0; else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end PGM_SUS: begin if (falling_edge_WRITE) begin if (DataLo == 16'h50) begin PRES = 1; #1 PRES = 0; STAT_ACT = 0; Status[7] = 0; Status[2] = 0; end else if (AddrCom == 16'h555 && DataLo == 16'h70 && ~STAT_ACT) begin SA_SR = SecAddr; STAT_ACT = 1; end else if (AddrCom == 16'h555 && DataLo == 16'h71) begin Status[7] = 1; Status[5:3] = 3'b000; Status[1:0] = 2'b00; STAT_ACT = 0; end else STAT_ACT = 0; end if (oe) begin if (STAT_ACT && SecAddr == SA_SR) begin Status[0] = 0; Dout_zd = Status; STAT_ACT = 0; end else if (BuffPageAddr == PA_PGM || (ESP_ACT && SecAddr == SA_ERS) || (LOCK_ACT && SecAddr == SA_LR) || (CR_ACT && SecAddr == SA_CR)) Dout_zd = 16'h0; else if (SecSi && SecAddr == SA_SecSi) begin READMEM(ReturnAddr(Addr,SecAddr),SecAddr,SS_T); Dout_zd = OutputD; end else begin READMEM(Addr,SecAddr,Mem_T); Dout_zd = OutputD; end end end endcase end // Burst functionality case (RD_MODE) LINEAR: begin // linear mode only implemented if (rising_edge_CLKMerge || falling_edge_ReadINIT) begin if (BurstDelay > 0 ) BurstDelay = BurstDelay - 1; if (BurstDelay == 0) begin if (IACC_out == 1 || ~IN_W_ELAPSED) begin if (~BURST_END) begin READ_BURST_DATA(BurstAddr,BurstSec,ReadTarget); NEXT_ADDR_LIN(BurstAddr, BurstLength); CHECK_END(RDCnt, BURST_END); end end else begin if (~OENeg) $display("More wait states should be programmed"); end if (IN_W_ELAPSED) begin DATA_DELAY = 1; end IN_W_ELAPSED = 1; end end end SYNCR: begin if (rising_edge_CLKMerge) begin if (BurstDelay > 0) BurstDelay = BurstDelay - 1; end end NOSYNC: begin end endcase if (RD_MODE != NOSYNC && IN_W_ELAPSED && ~OENeg) Dout_zd = DOut_burst; // Output Disable Control if (rising_edge_CENeg || (falling_edge_RST && ~RESETNeg) || (rising_edge_OENeg && (RD_MODE == NOSYNC || RD_MODE == SYNCR || INITIAL))) Dout_zd = 16'bz; end ////////////////////////////////////////////////////////////////// // CFI Preload Process ////////////////////////////////////////////////////////////////// initial begin : CFIPreload for (i=16; i<= 127; i=i+1) CFIMem[i] = 0; // CFI Query Identification String CFIMem[8'h10] = 16'h0051; CFIMem[8'h11] = 16'h0052; CFIMem[8'h12] = 16'h0059; CFIMem[8'h13] = 16'h0002; CFIMem[8'h14] = 16'h0000; CFIMem[8'h15] = 16'h0040; CFIMem[8'h16] = 16'h0000; CFIMem[8'h17] = 16'h0000; CFIMem[8'h18] = 16'h0000; CFIMem[8'h19] = 16'h0000; CFIMem[8'h1A] = 16'h0000; // System Interface String CFIMem[8'h1B] = 16'h0017; CFIMem[8'h1C] = 16'h0019; CFIMem[8'h1D] = 16'h0000; CFIMem[8'h1E] = 16'h0000; CFIMem[8'h1F] = 16'h0005; CFIMem[8'h20] = 16'h0008; CFIMem[8'h21] = 16'h000A; CFIMem[8'h22] = 16'h000F; CFIMem[8'h23] = 16'h0003; CFIMem[8'h24] = 16'h0003; CFIMem[8'h25] = 16'h0003; CFIMem[8'h26] = 16'h0003; // Device Geometry Definition CFIMem[8'h27] = 16'h0016; CFIMem[8'h28] = 16'h0001; CFIMem[8'h29] = 16'h0000; CFIMem[8'h2A] = 16'h0006; CFIMem[8'h2B] = 16'h0000; CFIMem[8'h2C] = 16'h0002; CFIMem[8'h2E] = 16'h0000; CFIMem[8'h32] = 16'h0000; //Primary Algorithm-Specific Extended Query CFIMem[8'h40] = 16'h0050; CFIMem[8'h41] = 16'h0052; CFIMem[8'h42] = 16'h0049; CFIMem[8'h43] = 16'h0031; CFIMem[8'h44] = 16'h0034; CFIMem[8'h45] = 16'h0014; CFIMem[8'h46] = 16'h0002; CFIMem[8'h47] = 16'h0001; CFIMem[8'h48] = 16'h0000; CFIMem[8'h49] = 16'h0009; CFIMem[8'h4A] = 16'h0030; CFIMem[8'h4B] = 16'h0001; CFIMem[8'h4C] = 16'h0000; CFIMem[8'h4D] = 16'h0000; CFIMem[8'h4E] = 16'h0000; CFIMem[8'h50] = 16'h0001; CFIMem[8'h51] = 16'h0000; CFIMem[8'h52] = 16'h0007; CFIMem[8'h53] = 16'h000E; CFIMem[8'h54] = 16'h000E; CFIMem[8'h55] = 16'h0008; CFIMem[8'h56] = 16'h0008; CFIMem[8'h57] = 16'h0004; CFIMem[8'h59] = 16'h0010; CFIMem[8'h5A] = 16'h0010; if (tmp_char == "0") begin CFIMem[8'h33] = 16'h0040; CFIMem[8'h34] = 16'h0000; CFIMem[8'h30] = 16'h0001; CFIMem[8'h31] = 16'h0003; CFIMem[8'h2F] = 16'h0000; CFIMem[8'h2D] = 16'h003E; CFIMem[8'h4F] = 16'h0003; CFIMem[8'h58] = 16'h0010; CFIMem[8'h5B] = 16'h0013; end else if (tmp_char == "1") begin CFIMem[8'h33] = 16'h0000; CFIMem[8'h34] = 16'h0001; CFIMem[8'h30] = 16'h0000; CFIMem[8'h31] = 16'h003E; CFIMem[8'h2F] = 16'h0040; CFIMem[8'h2D] = 16'h0003; CFIMem[8'h4F] = 16'h0002; CFIMem[8'h58] = 16'h0013; CFIMem[8'h5B] = 16'h0010; end end task READMEM; input integer Address; input integer SecAddr; input reg[8:0] Targ; reg [15:0] ReadData; begin case (Targ) Mem_T : begin if (Mem[Address] != -1) ReadData = Mem[Address]; else ReadData = 16'bx; end SS_T: begin if (Address <= 16'hFF) begin if (SecSiMem[Address] != -1) ReadData = SecSiMem[Address]; else ReadData = 16'bx; end else ReadData = 16'b0; end AS_CFI_T: begin if (Address >= 16'h10 && Address <= 16'h5B) ReadData = CFIMem[Address]; else if (Address == 16'h00) ReadData = 16'h0001; else if (Address == 16'h01) ReadData = 16'h357E; else if (Address == 16'h02) ReadData = 16'h00FF; else if (Address == 16'h03) ReadData = 16'h00FF; else if (Address == 16'h04) ReadData = 16'h00FF; else if (Address == 16'h05) ReadData = 16'h00FF; else if (Address == 16'h06) ReadData = 16'h10; else if (Address == 16'h07) ReadData = 16'h00FF; else if (Address == 16'h08) ReadData = 16'h00FF; else if (Address == 16'h09) ReadData = 16'h00FF; else if (Address == 16'h0A) ReadData = 16'h00FF; else if (Address == 16'h0B) ReadData = 16'h00FF; else if (Address == 16'h0C) ReadData = 16'h05; else if (Address == 16'h0D) ReadData = 16'h00FF; else if (Address == 16'h0E) ReadData = 16'h3519; else if (Address == 16'h0F) begin if (tmp_char == "0") ReadData = 16'h3503; else if (tmp_char == "1") ReadData = 16'h3504; end else if (Address < 16'h10) for (i=0; i<=15; i=i+1) ReadData[i] = Reserved; else for (i=0; i<=15; i=i+1) ReadData[i] = 0; end endcase OutputD = ReadData; end endtask task READ_BURST_DATA; input integer BAddr; input integer BSec; input reg[7:0] Targ; integer m; begin case (Targ) Mem_T: begin DOut_burst = 16'bx; if (Mem[BAddr] != -1) DOut_burst = Mem[BAddr]; end SS_T: begin DOut_burst = 16'bx; m= ReturnAddr(BAddr, SA_SecSi); if (SecSiMem[m] != -1) DOut_burst = SecSiMem[m]; end AS_CFI_T: begin m = ReturnAddr(BAddr,SA_AS_CFI); if (m >= 16'h10 && m <= 16'h5B) DOut_burst = CFIMem[m]; else if (m == 16'h00) DOut_burst = 16'h0001; else if (m == 16'h01) DOut_burst = 16'h357E; else if (m == 16'h02) DOut_burst = 16'h00FF; else if (m == 16'h03) DOut_burst = 16'h00FF; else if (m == 16'h04) DOut_burst = 16'h00FF; else if (m == 16'h05) DOut_burst = 16'h00FF; else if (m == 16'h06) DOut_burst = 16'h10; else if (m == 16'h07) DOut_burst = 16'h00FF; else if (m == 16'h08) DOut_burst = 16'h00FF; else if (m == 16'h09) DOut_burst = 16'h00FF; else if (m == 16'h0A) DOut_burst = 16'h00FF; else if (m == 16'h0B) DOut_burst = 16'h00FF; else if (m == 16'h0C) DOut_burst = 16'h05; else if (m == 16'h0D) DOut_burst = 16'h00FF; else if (m == 16'h0E) DOut_burst = 16'h3519; else if (m == 16'h0F) begin if (tmp_char == "0") DOut_burst = 16'h3503; else if (tmp_char == "1") DOut_burst = 16'h3504; end else if (m < 16'h10) for (i=0; i<=15; i=i+1) DOut_burst[i] = Reserved; else for (i=0; i<=15; i=i+1) DOut_burst[i] = 0; end endcase 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; output BEnd; begin CNT = CNT - 1; if (CNT == 0) BEnd = 1; else BEnd = 0; end endtask function integer ReturnAddr; input integer ADDR; input integer SADDR; begin if (SADDR <= 3 && tmp_char == "1" ) ReturnAddr = ADDR % (SecSize16+1); else if (tmp_char == "1") ReturnAddr = ADDR % (SecSize64+1); else if (SADDR < (SecNum-3) && tmp_char=="0" ) ReturnAddr = ADDR % (SecSize64+1); else ReturnAddr = ADDR % (SecSize16+1); end endfunction function integer ReturnSectorID; input integer ADDR; integer conv; begin conv = ADDR / (SecSize64+1); if (conv == 0 && tmp_char == "1" ) ReturnSectorID = (ADDR - sgsaB[0]) / (SecSize16+1); else if (tmp_char == "1") ReturnSectorID = 3+conv; else if (conv == (SecNum-3) && tmp_char=="0" ) ReturnSectorID = SecNum - 3 + (ADDR - sgsaT[1])/(SecSize16+1); else ReturnSectorID = conv; end endfunction function integer ReturnBuffPage; input integer ADDR; begin ReturnBuffPage = ADDR / (WrBuffLength+1); end endfunction function integer ReturnBank; input integer ADDR; begin ReturnBank = ADDR / (BankSize+1); end endfunction always @(negedge AVDNeg) begin falling_edge_AVDNeg = 1; #1 falling_edge_AVDNeg = 0; end always @(posedge AVDNeg) begin rising_edge_AVDNeg = 1; #1 rising_edge_AVDNeg = 0; end always @(posedge gWE_n) begin rising_edge_gWE_n = 1; #1 rising_edge_gWE_n = 0; end always @(negedge gWE_n) begin falling_edge_gWE_n = 1; #1 falling_edge_gWE_n = 0; end always @(posedge gCE_n) begin rising_edge_gCE_n = 1; #1 rising_edge_gCE_n = 0; end always @(negedge gCE_n) begin falling_edge_gCE_n = 1; #1 falling_edge_gCE_n = 0; end always @(posedge CENeg) begin rising_edge_CENeg = 1; #1 rising_edge_CENeg = 0; end always @(negedge CENeg) begin falling_edge_CENeg = 1; #1 falling_edge_CENeg = 0; end always @(posedge CLK) begin rising_edge_CLK = 1; #1 rising_edge_CLK = 0; end always @(negedge OENeg) begin falling_edge_OENeg = 1; #1 falling_edge_OENeg = 0; end always @(A) begin A_event = 1; #1 A_event = 0; end always @(posedge RESETNeg) begin rising_edge_RESETNeg = 1; #1 rising_edge_RESETNeg = 0; end always @(negedge RESETNeg) begin falling_edge_RESETNeg = 1; #1 falling_edge_RESETNeg = 0; end always @(posedge START_in) begin rising_edge_START_in = 1; #1 rising_edge_START_in = 0; end always @(posedge READ) begin rising_edge_READ =1; #1 rising_edge_READ = 0; end always @(negedge READ) begin falling_edge_READ =1; #1 falling_edge_READ = 0; end always @(posedge reseted) begin rising_edge_reseted = 1; #1 rising_edge_reseted = 0; end always @(posedge PSTART) begin rising_edge_PSTART = 1; #1 rising_edge_PSTART = 0; end always @(posedge PSUSP) begin rising_edge_PSUSP = 1; #1 rising_edge_PSUSP = 0; end always @(posedge PRES) begin rising_edge_PRES = 1; #1 rising_edge_PRES = 0; end always @(posedge ESTART) begin rising_edge_ESTART = 1; #1 rising_edge_ESTART = 0; end always @(posedge ESUSP) begin rising_edge_ESUSP = 1; #1 rising_edge_ESUSP = 0; end always @(posedge ERES) begin rising_edge_ERES = 1; #1 rising_edge_ERES = 0; end always @( negedge WRITE) begin falling_edge_WRITE = 1; #1 falling_edge_WRITE = 0; end always @(posedge CEDONE) begin rising_edge_CEDONE = 1; #1 rising_edge_CEDONE = 0; end always @(posedge EDONE) begin rising_edge_EDONE = 1; #1 rising_edge_EDONE = 0; end always @(posedge PDONE) begin rising_edge_PDONE = 1; #1 rising_edge_PDONE = 0; end always @(posedge START_out) begin rising_edge_START_out = 1; #1 rising_edge_START_out = 0; end always @(negedge RST) begin falling_edge_RST = 1; #1 falling_edge_RST = 0; end always @(negedge BURST) begin falling_edge_BURST = 1; #1 falling_edge_BURST = 0; end always @(posedge CLKMerge) begin rising_edge_CLKMerge = 1; #1 rising_edge_CLKMerge = 0; end always @(posedge OENeg) begin rising_edge_OENeg = 1; #1 rising_edge_OENeg = 0; end always @(next_state) begin next_state_event = 1; #1 next_state_event = 0; end always @(negedge ReadINIT) begin falling_edge_ReadINIT = 1; #1 falling_edge_ReadINIT = 0; end reg BuffInOE, BuffInCE, BuffInADDRIN, BuffInADDRPAGE; wire BuffOutOE, BuffOutCE, BuffOutADDRIN; BUFFER BUFOE (BuffOutOE , BuffInOE); BUFFER BUFCE (BuffOutCE , BuffInCE); BUFFER BUFADDRIN (BuffOutADDRIN , BuffInADDRIN); initial begin BuffInOE = 1'b1; BuffInCE = 1'b1; BuffInADDRIN = 1'b1; end always @(posedge BuffOutOE) begin OEDQ_01 = $time; end always @(posedge BuffOutCE) begin CEDQ_01 = $time; end always @(posedge BuffOutADDRIN) begin ADDRDQIN_01 = $time; end endmodule module BUFFER (OUT,IN); input IN; output OUT; buf (OUT, IN); endmodule