//////////////////////////////////////////////////////////////////////////// // File name : s30ms02gr00.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: | mod date: | changes made: // V1.0 D.Vukicevic 06 Apr 25 Initial Release // V1.1 S.Janevski 06 Nov 30 New specification update // V1.2 S.Janevski 07 March 13 RY is low for 200 us // after Power On //////////////////////////////////////////////////////////////////////////// // PART DESCRIPTION: // // Library: FLASH // Technology: FLASH MEMORY // Part: s30ms02gr00 // // Description: 2Gb (256Mx8) NAND interface Flash Memory // //////////////////////////////////////////////////////////////////////////// // Known Bugs: // //////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////// // MODULE DECLARATION // //////////////////////////////////////////////////////////////////////////// `timescale 1 ns/1 ns module s30ms02gr00 ( IO7 , IO6 , IO5 , IO4 , IO3 , IO2 , IO1 , IO0 , CLE , ALE , CENeg , RENeg , WENeg , WPNeg , RY ); //////////////////////////////////////////////////////////////////////// // Port / Part Pin Declarations //////////////////////////////////////////////////////////////////////// inout IO7 ; inout IO6 ; inout IO5 ; inout IO4 ; inout IO3 ; inout IO2 ; inout IO1 ; inout IO0 ; input CLE ; input ALE ; input CENeg ; input RENeg ; input WENeg ; input WPNeg ; output RY ; // interconnect path delay signals wire IO7_ipd ; wire IO6_ipd ; wire IO5_ipd ; wire IO4_ipd ; wire IO3_ipd ; wire IO2_ipd ; wire IO1_ipd ; wire IO0_ipd ; wire [7 : 0] A; assign A = {IO7_ipd, IO6_ipd, IO5_ipd, IO4_ipd, IO3_ipd, IO2_ipd, IO1_ipd, IO0_ipd }; wire [7 : 0 ] DIn; assign DIn = {IO7_ipd, IO6_ipd, IO5_ipd, IO4_ipd, IO3_ipd, IO2_ipd, IO1_ipd, IO0_ipd }; wire [7 : 0 ] DOut; assign DOut = {IO7, IO6, IO5, IO4, IO3, IO2, IO1, IO0 }; wire CLE_ipd ; wire ALE_ipd ; wire CENeg_ipd ; wire RENeg_ipd ; wire WENeg_ipd ; wire WPNeg_ipd ; // internal delays reg PROG_in = 1'b0; reg PROG_out = 1'b0; reg PROG1_in = 1'b0; reg PROG1_out = 1'b0; reg PROG2_in = 1'b0; reg PROG2_out = 1'b0; reg SPROG_in = 1'b0; reg SPROG_out = 1'b0; reg ERS_in = 1'b0; reg ERS_out = 1'b0; reg DBSY_in = 1'b0; reg DBSY_out = 1'b0; reg DBSY1_in = 1'b0; reg DBSY1_out = 1'b0; reg DEF_OTP_in = 1'b0; reg DEF_OTP_out = 1'b0; reg TR_in = 1'b0; reg TR_out = 1'b0; reg TRP_in = 1'b0; reg TRP_out = 1'b0; reg TRT_in = 1'b0; reg TRT_out = 1'b0; reg TPT_in = 1'b0; reg TPT_out = 1'b0; reg ERS_SUSP_in = 1'b0; reg ERS_SUSP_out = 1'b0; reg ERS_PRESUS_in = 1'b0; reg ERS_PRESUS_out = 1'b0; reg WAIT_OTP_in = 1'b0; reg WAIT_OTP_out = 1'b0; reg OTP_in = 1'b0; reg OTP_out = 1'b0; reg TPRE_in = 1'b0; reg TPRE_out = 1'b0; reg [7 : 0] DOut_zd; wire IO7_zd ; wire IO6_zd ; wire IO5_zd ; wire IO4_zd ; wire IO3_zd ; wire IO2_zd ; wire IO1_zd ; wire IO0_zd ; assign {IO7_zd, IO6_zd, IO5_zd, IO4_zd, IO3_zd, IO2_zd, IO1_zd, IO0_zd } = DOut_zd; reg RY_zd = 1'b0; parameter mem_file_name = "none";//"s30ms02gr00.mem" parameter OTP_file_name = "none";//"s30ms02gr00_OTP.mem" parameter protOTP_file_name = "none";//"s30ms02gr00_OTPprot.mem" parameter UserPreload = 1'b0; parameter TimingModel = "DefaultTimingModel"; parameter PartID = "s30ms02gr00"; parameter MaxData = 8'hFF; parameter BlockNum = 2047; parameter BlockSize = 63; parameter PageNum = 17'h1FFFF; parameter PageNumInBl = 64; parameter PageSize = 2111; parameter SegmentNum = 7; // 8 segments within page parameter SegmentSize = 512; parameter SperSegSize = 16; parameter SpareSize = 64; parameter MainSize = 2048; parameter OTPPageNum = 7; parameter MainAreaAddBit = 11; parameter HAddBitPag = 17; parameter HAddBitBl = 28; parameter HAddBitSpareSeg = 5; parameter HAddBitSeg = 10; // If generic Long_Timming is set to 0, you need to uncomment line below //`define SPEEDSIM; // constraint memory preload file parameters parameter preload_line_width = 160; parameter preload_address_width = 8; parameter preload_data_width = 2; // control signals reg ERS_ACT =1'b0; reg PRG_ACT =1'b0; reg RD_ACT =1'b0; reg back_to_xtrem =1'b0; reg RSTSTART =1'b0; reg RSTDONE =1'b0; reg PMOVE =1'b0; // Control signals for read operation reg STAT_ACT =1'b0; reg PGR_ACT =1'b0; // Page read in progress reg PPGR_ACT =1'b0; // Partial page read reg PGD_ACT =1'b0; // Page Duplicate reg PIPR_ACT =1'b0; // Pipeline read // powerup reg PoweredUp =1'b0; reg reseted =1'b0; reg flagWRITE =1'b1; reg flagPROG =1'b1; reg flagPROG1 =1'b1; reg write =1'b0; reg read =1'b0; integer WER_01; reg PDONE ; //Prog. Done reg PSTART ; //Start Programming reg PSUSP ; //Suspend Programming reg PRES ; //Resume Programming reg PERR ; //Protected reg EDONE = 1'b0 ; //Ers. Done reg ESTART ; //Start Erase reg ESUSP ; //Suspend Erase reg ERES ; //Resume Erase //All sectors selected for erasure are protected reg EERR ; reg ESUSP_ACT = 1'b0; reg OTP_STAT_ACT = 1'b0; parameter Removed = 1'b0; parameter Overlaid = 1'b1; reg OTPDefault = Removed; // 8 bit Address integer AddrCom ; // Address within page integer Address ; // 0 - Pagesize // Page Number integer PageAddr = -1; //-1 - PageNum // Partial page number integer PartAddr = 0; // Block Number integer BlockAddr = -1; //-1 - BlockNum integer BlckDup = 0; //Data integer Data ; //-1 - MaxData integer TmpPage; integer TmpSegm ; integer AddrWithinPage; integer PageWithinBlock; integer Segment; reg [23:0] RowAddr; reg [15:0] ColAddr; integer RdPage; integer RdAddr; integer RdSeg; integer RdBlck; integer WrSeg; integer ProgBlck; integer ProgPage; reg OTPOverlay = 1'b0; reg OTPOverlayPIP = 1'b0; reg FirstByte = 1'b1; reg SetDefault = 1'b0; // First pipeline read reg FirstPipe = 1'b1; reg firstFlag = 1'b0; reg WriteProtect = 1'b0; reg Protect = 1'b0; integer mem_data; reg [OTPPageNum:0] ProtStatus; reg [SegmentNum:0] SegProgSt = 0; reg [3:0] Tmp = 0; integer tmp_cnt; //ID control signals integer IDAddr ; // 0 - 4 integer BlockPage ; // RANGE 0 TO BlockSize; integer Pom_Address ; // RANGE 0 TO PageSize; integer PartialPage ; // RANGE 0 TO 3; // program control signals integer CashBuffData[0:PageSize]; //Page chache register integer CWrAddr ; // Cash -1 - Pagesize +1 integer CWrPage ; // Cash 0 - PageNum integer WrBuffData[0:PageSize]; integer WrAddr ; // -1 - Pagesize +1 integer WrPage ; // 0 - PageNum reg [SegmentNum:0] SegForProg; //array [0:SegmentNum] of 0/1 reg [SegmentNum:0] CashSegForProg; integer PDBuffer [0:PageSize]; integer PDBuffer1 [0:PageSize]; // For delayed flags integer PIP_Addr; // RANGE 0 TO PageSize integer PIP_Blck; // RANGE 0 TO BlockNum integer PIP_Page; // RANGE 0 TO PageNum integer Page_pom; integer cnt_addr; integer segment ; // RANGE -1 TO SegmentNum; integer segment1 ; // RANGE -1 TO SegmentNum; integer pom_seg ; // RANGE -1 TO SegmentNum; integer pom_seg1 ; // RANGE -1 TO SegmentNum; integer ssa[0:SegmentNum]; // has to be initialized integer sea[0:SegmentNum]; // has to be initialized // Mem(Page)(Address) integer Mem[0:(PageSize+1)*(PageNum+1)-1]; integer OTP_Area[0:(PageSize+1)*(OTPPageNum+1)-1]; reg [0:(PageNum+1)*(SegmentNum+1)-1] ProgramedFlag; reg [0:(OTPPageNum+1)*(SegmentNum+1)-1] OTPProgramedFlag; // ID Array integer IDArray[0:5]; // timing check violation reg Viol = 1'b0; // initial integer i,j; //Bus Cycle Decode reg[7:0] A_tmp ; reg[7:0] D_tmp ; integer WrBlck ; integer ErsBlck ; integer TmpBlck ; //Functional reg[7:0] Status = 8'hC0; reg oe = 1'b0; integer Page ; // 0 - PageNum integer Blck ; // 0 - BlockNum //TPD_DATA time RENeg_event; time CENeg_event; reg FROMRE; reg FROMCE; time prog_time; time erase_time; time page_prog_time; time seg_prog_time; reg[7:0] TempData; event oe_event; // states reg [5:0] current_state; reg [5:0] next_state; reg rising_edge_PoweredUp = 1'b0; reg rising_edge_reseted = 1'b0; reg rising_edge_RSTDONE = 1'b0; reg rising_edge_RSTSTART = 1'b0; reg falling_edge_write = 1'b0; reg rising_edge_ESTART = 1'b0; reg rising_edge_ESUSP = 1'b0; reg rising_edge_ERES = 1'b0; reg rising_edge_EDONE = 1'b0; reg rising_edge_TR_out = 1'b0; reg rising_edge_TRP_out = 1'b0; reg rising_edge_TPT_out = 1'b0; reg rising_edge_TPRE_out = 1'b0; reg rising_edge_PROG_out = 1'b0; reg rising_edge_PROG1_out = 1'b0; reg rising_edge_PROG2_out = 1'b0; reg rising_edge_DBSY_out = 1'b0; reg rising_edge_DBSY1_out = 1'b0; reg rising_edge_ERS_SUSP_out = 1'b0; reg rising_edge_ERS_PRESUS_out = 1'b0; reg rising_edge_WAIT_OTP_out = 1'b0; reg rising_edge_OTP_out = 1'b0; reg rising_edge_DEF_OTP_out = 1'b0; reg rising_edge_RENeg = 1'b0; reg rising_edge_CENeg = 1'b0; // FSM states parameter IDLE =6'h00; parameter UNKNOWN =6'h01; // wrong command sequneces parameter PREL_RD =6'h02; parameter RESET =6'h03; parameter A0_RD =6'h04; parameter A1_RD =6'h05; parameter A2_RD =6'h06; parameter A3_RD =6'h07; parameter RD_WCMD =6'h08; // waiting for the confirm read command parameter BUFF_TR =6'h09; parameter RD =6'h0A; parameter CAC_PREL =6'h0B; // Coloumn address change parameter A0_CAC =6'h0C; parameter A1_CAC =6'h0D; // Wait for confirm EO command parameter ID_PREL =6'h0E; parameter ID =6'h0F; parameter PREL_PRG =6'h10; parameter PGD_PREL =6'h11; parameter A0_PRG =6'h12; parameter A1_PRG =6'h13; parameter A2_PRG =6'h14; parameter A3_PRG =6'h15; parameter DATA_PRG =6'h16; parameter WFPD =6'h17; // wait for program done parameter WFPPD =6'h18; parameter PGMS_CAC =6'h19; parameter A0_PRG_CAC =6'h1A; parameter PGMS =6'h1B; parameter CBSY =6'h1C; parameter RDY_PRG =6'h1D; parameter PREL_ERS =6'h1E; parameter A1_ERS =6'h20; parameter A2_ERS =6'h21; parameter A3_ERS =6'h22; parameter ERS_EXEC =6'h23; parameter ERS_SUSP =6'h24; parameter A0_PGD =6'h25; parameter A1_PGD =6'h26; parameter A2_PGD =6'h27; parameter A3_PGD =6'h28; parameter PREL_OTP =6'h29; parameter DEF_OVER =6'h2A; parameter DEF_REM =6'h2B; parameter WAIT_STATE =6'h2C; parameter WAIT_STATE_1 =6'h2D; parameter WAIT_STATE_2 =6'h2E; ///////////////////////////////////////////////////////////////////////////// //Interconnect Path Delay Section ///////////////////////////////////////////////////////////////////////////// buf (IO7_ipd , IO7 ); buf (IO6_ipd , IO6 ); buf (IO5_ipd , IO5 ); buf (IO4_ipd , IO4 ); buf (IO3_ipd , IO3 ); buf (IO2_ipd , IO2 ); buf (IO1_ipd , IO1 ); buf (IO0_ipd , IO0 ); buf (CLE_ipd , CLE ); buf (ALE_ipd , ALE ); buf (CENeg_ipd , CENeg ); buf (RENeg_ipd , RENeg ); buf (WENeg_ipd , WENeg ); buf (WPNeg_ipd , WPNeg ); ///////////////////////////////////////////////////////////////////////////// // Propagation delay Section ///////////////////////////////////////////////////////////////////////////// nmos (IO7 , IO7_zd , 1); nmos (IO6 , IO6_zd , 1); nmos (IO5 , IO5_zd , 1); nmos (IO4 , IO4_zd , 1); nmos (IO3 , IO3_zd , 1); nmos (IO2 , IO2_zd , 1); nmos (IO1 , IO1_zd , 1); nmos (IO0 , IO0_zd , 1); nmos (RY , 1'b0 , ~RY_zd); wire deg; // Needed for TimingChecks // VHDL CheckEnable Equivalent wire Check_IO0_WENeg; assign Check_IO0_WENeg = ~CENeg; wire Check_WENeg; assign Check_WENeg = PoweredUp; specify // tipd delays: interconnect path delays , mapped to input port delays. // In Verilog is not necessary to declare any tipd_ delay variables, // they can be taken from SDF file // With all the other delays real delays would be taken from SDF file specparam tpd_CENeg_IO0 = 1;//tcea, tchz specparam tpd_RENeg_IO0 = 1;//trea, trhz specparam tpd_WENeg_RY = 1;//twb //tsetup values specparam tsetup_CLE_WENeg = 1;//tcls edge \ specparam tsetup_CENeg_WENeg = 1;//tcs edge \ specparam tsetup_WENeg_CENeg = 1;//twhc edge \ specparam tsetup_ALE_WENeg = 1;//tals edge \ specparam tsetup_IO0_WENeg = 1;//tds edge / specparam tsetup_ALE_RENeg = 1;//tclr edge \ specparam tsetup_CLE_RENeg = 1;//tar edge \ specparam tsetup_WENeg_RENeg = 1;//twhr edge \ specparam tsetup_RENeg_WENeg = 1;//twhw edge \ specparam tsetup_WPNeg_WENeg = 1;//tww edge / specparam tsetup_CENeg_RENeg = 1;//tcr edge \ //thold values specparam thold_CLE_WENeg = 1;//tclh edge / specparam thold_CENeg_WENeg = 1;//tch edge / specparam thold_ALE_WENeg = 1;//talh edge / specparam thold_IO0_WENeg = 1;//tdh edge / specparam thold_CENeg_RENeg = 1;//tch edge / //tpw values specparam tpw_WENeg_negedge = 1;//twp specparam tpw_WENeg_posedge = 1;//twh specparam tpw_RENeg_negedge = 1;//trp specparam tpw_RENeg_posedge = 1;//treh specparam tperiod_WENeg = 1;//twc specparam tperiod_RENeg = 1;//trc //tdevice values: values for internal delays `ifdef SPEEDSIM // Program Operation specparam tdevice_PROG = 8000; // Segment Program Operation specparam tdevice_SPROG = 2600; // Erase Operation specparam tdevice_ERS = 500000; // Dummy busy time specparam tdevice_DBSY = 400; // Page transfer time specparam tdevice_TR = 5000; // Page transfer time specparam tdevice_TRP = 8000; // Pipeline transfer time specparam tdevice_TPT = 5000; // Time for reset specparam tdevice_RST = 1000; // Time for erase suspend specparam tdevice_SUSP = 15000; // Premble Suspend time specparam tdevice_PRESUS = 1500; // OTP busy time specparam tdevice_OTP = 5000; // OTP default busy time specparam tdevice_OTPD = 150000; // Time for reading buffer after power-up specparam tdevice_TPRE = 9500; `else // not SPEEDSIM // Program Operation specparam tdevice_PROG = 800000; // Segment Program Operation specparam tdevice_SPROG = 260000; // Erase Operation specparam tdevice_ERS = 50000000; // Dummy busy time specparam tdevice_DBSY = 400; // Page transfer time specparam tdevice_TR = 25000; // Page transfer time specparam tdevice_TRP = 8000; // Pipeline transfer time specparam tdevice_TPT = 25000; // Time for reset specparam tdevice_RST = 1000; // Time for erase suspend specparam tdevice_SUSP = 15000; // Premble Suspend time specparam tdevice_PRESUS = 1500; // OTP busy time specparam tdevice_OTP = 5000; // OTP default busy time specparam tdevice_OTPD = 150000; // Time for reading buffer after power-up specparam tdevice_TPRE = 190000; `endif // SPEEDSIM ///////////////////////////////////////////////////////////////////////////// // Input Port Delays don't require Verilog description ///////////////////////////////////////////////////////////////////////////// // Path delays // ///////////////////////////////////////////////////////////////////////////// // specify transport delay for Data output paths specparam PATHPULSE$CENeg$IO0 = (0); specparam PATHPULSE$CENeg$IO1 = (0); specparam PATHPULSE$CENeg$IO2 = (0); specparam PATHPULSE$CENeg$IO3 = (0); specparam PATHPULSE$CENeg$IO4 = (0); specparam PATHPULSE$CENeg$IO5 = (0); specparam PATHPULSE$CENeg$IO6 = (0); specparam PATHPULSE$CENeg$IO7 = (0); specparam PATHPULSE$RENeg$IO0 = (0); specparam PATHPULSE$RENeg$IO1 = (0); specparam PATHPULSE$RENeg$IO2 = (0); specparam PATHPULSE$RENeg$IO3 = (0); specparam PATHPULSE$RENeg$IO4 = (0); specparam PATHPULSE$RENeg$IO5 = (0); specparam PATHPULSE$RENeg$IO6 = (0); specparam PATHPULSE$RENeg$IO7 = (0); // Data output paths ( CENeg => IO0 ) = tpd_CENeg_IO0; ( CENeg => IO1 ) = tpd_CENeg_IO0; ( CENeg => IO2 ) = tpd_CENeg_IO0; ( CENeg => IO3 ) = tpd_CENeg_IO0; ( CENeg => IO4 ) = tpd_CENeg_IO0; ( CENeg => IO5 ) = tpd_CENeg_IO0; ( CENeg => IO6 ) = tpd_CENeg_IO0; ( CENeg => IO7 ) = tpd_CENeg_IO0; ( RENeg => IO0 ) = tpd_RENeg_IO0; ( RENeg => IO1 ) = tpd_RENeg_IO0; ( RENeg => IO2 ) = tpd_RENeg_IO0; ( RENeg => IO3 ) = tpd_RENeg_IO0; ( RENeg => IO4 ) = tpd_RENeg_IO0; ( RENeg => IO5 ) = tpd_RENeg_IO0; ( RENeg => IO6 ) = tpd_RENeg_IO0; ( RENeg => IO7 ) = tpd_RENeg_IO0; // R output path (WENeg => RY) = tpd_WENeg_RY; ////////////////////////////////////////////////////////////////////////////// // Timing Violation // ////////////////////////////////////////////////////////////////////////////// $setup ( IO0 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO1 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO2 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO3 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO4 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO5 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO6 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO7 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO0 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO1 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO2 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO3 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO4 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO5 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO6 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO7 ,thold_IO0_WENeg, Viol); $setup ( CLE ,negedge WENeg ,tsetup_CLE_WENeg , Viol); $setup ( ALE ,negedge WENeg ,tsetup_ALE_WENeg , Viol); $setup ( CENeg ,negedge WENeg ,tsetup_CENeg_WENeg , Viol); $setup ( WENeg ,negedge CENeg ,tsetup_WENeg_CENeg , Viol); $setup ( CLE ,negedge RENeg ,tsetup_CLE_RENeg , Viol); $setup ( ALE ,negedge RENeg ,tsetup_ALE_RENeg , Viol); $setup ( WENeg ,negedge RENeg ,tsetup_WENeg_RENeg , Viol); $setup ( CENeg ,negedge RENeg ,tsetup_CENeg_RENeg , Viol); $setup ( RENeg ,negedge WENeg ,tsetup_RENeg_WENeg , Viol); $setup ( WPNeg ,negedge WENeg ,tsetup_WPNeg_WENeg , Viol); $hold ( posedge WENeg &&& Check_WENeg, CLE,thold_CLE_WENeg, Viol); $hold ( posedge WENeg &&& Check_WENeg,ALE,thold_ALE_WENeg, Viol); $hold ( posedge WENeg &&& Check_WENeg,CENeg,thold_CENeg_WENeg,Viol); $hold ( posedge RENeg &&& Check_WENeg,CENeg,thold_CENeg_RENeg,Viol); $width (posedge WENeg , tpw_WENeg_posedge); $width (negedge WENeg , tpw_WENeg_negedge); $period(negedge WENeg , tperiod_WENeg); $period(posedge WENeg , tperiod_WENeg); $width (posedge RENeg , tpw_RENeg_posedge); $width (negedge RENeg , tpw_RENeg_negedge); $period(negedge RENeg , tperiod_RENeg); $period(posedge RENeg , tperiod_RENeg); endspecify time poweredupT = 10000; // 10 us //////////////////////////////////////////////////////////////////////////////// // Main Behavior Block // //////////////////////////////////////////////////////////////////////////////// reg deq; ////////////////////////////////////////////////////////// // Output Data Gen ////////////////////////////////////////////////////////// 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 occasion assign deg=deq; //varaibles to resolve if model has ECC reg [20*8-1:0] tmp_timing;//stores copy of TimingModel reg [7:0] tmp_char;//stores "h" or "l" character integer found = 1'b0; initial begin ////////////////////////////////////////////////////////////////// //ID array data / S30MS02GR00 DEVICE SPECIFIC ////////////////////////////////////////////////////////////////// IDArray[4'd0] = 8'h01; IDArray[4'd1] = 8'hAA; IDArray[4'd2] = 8'h01; IDArray[4'd3] = 8'h00; IDArray[4'd4] = 8'h22; IDArray[4'd5] = 8'h00; end // ------------------------------------------------------------------------- // preload section modified for embedded memory management routines // ------------------------------------------------------------------------- // preload dedicated declarations reg [preload_line_width*8 : 1] scanf_str; reg [8:1] fetch_char; integer preload_iter; integer preload_file; integer scanf_address; integer scanf_data; // initialize memory and load preoload files if any initial begin: InitMemory integer i,j,k; integer prot_stat[0:OTPPageNum]; for (i=0;i<= PageNum;i=i+1) begin for (j=0;j<= PageSize;j=j+1) begin Mem[i*(PageSize+1)+j]=MaxData; end end for (i=0;i<= OTPPageNum;i=i+1) begin for (j=0;j<= PageSize;j=j+1) begin OTP_Area[i*(PageSize+1)+j]=MaxData; end end //page segment start address offset ssa[0] =12'h000; ssa[1] =12'h200; ssa[2] =12'h400; ssa[3] =12'h600; ssa[4] =12'h800; ssa[5] =12'h810; ssa[6] =12'h820; ssa[7] =12'h830; //page segment end address offset sea[0] =12'h1FF; sea[1] =12'h3FF; sea[2] =12'h5FF; sea[3] =12'h7FF; sea[4] =12'h80F; sea[5] =12'h81F; sea[6] =12'h82F; sea[7] =12'h83F; if (UserPreload && !(mem_file_name == "none")) begin // s30ms02gr00 memory preload file // / - comment // @aaaaaaaa - stands for page address and address within // first 2112 bytes of a page // 7FFFFFFF - max value ! // dd -
is Byte to be written at Mem(page)(offset++) // page is div 2112 // offset is mod 2112 // offset is incremented on every write for (i=0;i<(PageNum+1)*(SegmentNum+1);i=i+1) ProgramedFlag[i] = 1'b0; for (i=0;i<(OTPPageNum+1)*(SegmentNum+1);i=i+1) OTPProgramedFlag[i] = 1'b0; ProtStatus = 8'hFF; scanf_address = 0; preload_file = $fopen(mem_file_name, "r"); while($fgets(scanf_str, preload_file)) begin fetch_char = scanf_str [preload_line_width*8 : preload_line_width*8 - 7]; while (!fetch_char) begin scanf_str = scanf_str << 8; fetch_char = scanf_str [preload_line_width * 8 : preload_line_width * 8 - 7]; end if ((fetch_char == "/") || (fetch_char == "\n")) begin // empty lines and comments not processed end else begin if (fetch_char == "@") begin scanf_address = 0; for(preload_iter = 0; preload_iter < preload_address_width; preload_iter = preload_iter + 1) begin scanf_str = scanf_str << 8; fetch_char = scanf_str[ preload_line_width * 8 : preload_line_width * 8 - 7 ]; scanf_address = scanf_address * 16; if ((fetch_char >= "0")&&(fetch_char <= "9")) scanf_address = scanf_address + (fetch_char - "0"); else if ((fetch_char >= "A")&&(fetch_char <= "F")) scanf_address = scanf_address + (fetch_char - "A") + 10; else if ((fetch_char >= "a")&&(fetch_char <= "f")) scanf_address = scanf_address + (fetch_char - "a") + 10; end end else begin scanf_data = 0; for(preload_iter = 0; preload_iter < preload_data_width; preload_iter = preload_iter + 1) begin scanf_data = scanf_data * 16; if ((fetch_char >= "0") && (fetch_char <= "9")) scanf_data = scanf_data + (fetch_char - "0"); else if ((fetch_char >= "A")&&(fetch_char <= "F")) scanf_data = scanf_data + (fetch_char - "A") + 10; else if ((fetch_char >= "a")&&(fetch_char <= "f")) scanf_data = scanf_data + (fetch_char - "a") + 10; scanf_str = scanf_str << 8; fetch_char = scanf_str[ preload_line_width * 8 : preload_line_width * 8-7 ]; end if (scanf_address < ((PageNum + 1) * (PageSize + 1))) begin Mem[scanf_address] = scanf_data; ProgramedFlag[scanf_address/SegmentSize] = 1'b1; end else $display("Memory address out of range."); scanf_address = scanf_address + 1; end end end end if (UserPreload && !(OTP_file_name == "none")) begin $readmemh(OTP_file_name, OTP_Area); for (i=0;i<= OTPPageNum;i=i+1) begin for (j=0;j<= PageSize;j=j+1) begin if (OTP_Area[i*(PageSize+1)+j]!==MaxData) begin getSegment(j,segment); OTPProgramedFlag[i*(SegmentNum+1)+segment] = 1'b1; j = sea[segment]; // jump to segment end addr. end end end end if (UserPreload && !(protOTP_file_name == "none")) begin $readmemh(protOTP_file_name, prot_stat); for (i=0;i<= OTPPageNum; i=i+1) ProtStatus[i] = !prot_stat[i]; end end initial begin ERS_ACT =1'b0; PRG_ACT =1'b0; RD_ACT =1'b0; RSTSTART =1'b0; RSTDONE =1'b0; ESUSP =1'b0; ESUSP_ACT = 1'b0; OTP_STAT_ACT = 1'b0; write =1'b0; read =1'b0; OTPDefault =1'b0;// default - removed for(j=0;j<=PageSize;j=j+1) begin WrBuffData[j] = -1; end for(j=0;j<=SegmentNum;j=j+1) begin SegForProg[i]=1'b0; end WrAddr = -1; WrPage = -1; CWrAddr = -1; CWrPage = -1; current_state = IDLE; next_state = IDLE; Status = 8'b01100100; PROG_in = 1'b0; PROG_out = 1'b0; DBSY_in = 1'b0; DBSY_out = 1'b0; TR_in = 1'b0; TR_out = 1'b0; TRP_in = 1'b0; TRP_out = 1'b0; ERS_SUSP_in = 1'b0; ERS_SUSP_out = 1'b0; PROG1_in = 1'b0; PROG1_out = 1'b0; PROG2_in = 1'b0; PROG2_out = 1'b0; DBSY1_in = 1'b0; DBSY1_out = 1'b0; FirstPipe = 1'b1; firstFlag = 1'b0; flagWRITE =1'b1; end //Power Up time 10 us; initial begin PoweredUp = 1'b0; #poweredupT PoweredUp = 1'b1; end //////////////////////////////////////////////////////////////////////////// //// obtain 'LAST_EVENT information //////////////////////////////////////////////////////////////////////////// always @(RENeg) begin RENeg_event = $time; end always @(CENeg) begin CENeg_event = $time; end //////////////////////////////////////////////////////////////////////////// // process for reset control and FSM state transition //////////////////////////////////////////////////////////////////////////// always @(rising_edge_PoweredUp or next_state) begin if (rising_edge_PoweredUp) begin reseted <= 1'b1; current_state <= BUFF_TR; page_prog_time = tdevice_PROG; seg_prog_time = tdevice_SPROG; erase_time = tdevice_ERS; end else if (PoweredUp) begin current_state <= next_state; end else begin current_state <= IDLE; reseted <= 1'b0; end end ////////////////////////////////////////////////////////////////////////// //process for generating the write and read signals ////////////////////////////////////////////////////////////////////////// always @ (WENeg, CENeg, RENeg) begin if (~WENeg && ~CENeg && RENeg) write = 1'b1; else if (WENeg && ~CENeg && RENeg) write = 1'b0; else write = 1'b0; if (WENeg && ~CENeg && ~RENeg ) read = 1'b1; else if (WENeg && ~CENeg && RENeg ) read = 1'b0; else read = 1'b0; end ////////////////////////////////////////////////////////////////////////// //Latches 8 bit address on rising edge of WE# //Latches data on rising edge of WE# ////////////////////////////////////////////////////////////////////////// always @ (posedge WENeg) begin // latch 8 bit read address if (WENeg && ALE && ~CENeg && ~CLE) AddrCom = A[7:0]; // latch data if (WENeg && ~ALE && RENeg) Data = DIn[7:0]; end //////////////////////////////////////////////////////////////////////////// // Timing control for the Reset Operation //////////////////////////////////////////////////////////////////////////// time duration_rst; always @(rising_edge_RSTSTART or rising_edge_reseted) begin if (rising_edge_reseted) RSTDONE <= 1'b1; // reset done else if (reseted) begin if (rising_edge_RSTSTART && RSTDONE) begin if (PGR_ACT || PRG_ACT) duration_rst = tdevice_RST; else duration_rst = tdevice_RST + WER_01; RSTDONE <= 1'b0; RSTDONE <= #duration_rst 1'b1; end end end time duration_ers; time elapsed_ers; time start_ers; always @ (rising_edge_reseted) begin if (rising_edge_reseted) EDONE <= 1'b1; // reset done, Erase terminated end always @ (rising_edge_ESTART) begin : edone_started if (reseted) begin if (rising_edge_ESTART && EDONE) begin elapsed_ers = 0; duration_ers = erase_time + WER_01; start_ers = $time; EDONE = 1'b0; #duration_ers EDONE = 1'b1; end end end always @ (rising_edge_ESUSP) begin if (reseted) begin if (rising_edge_ESUSP && !EDONE) begin disable edone_started; elapsed_ers = $time - start_ers; duration_ers = duration_ers - elapsed_ers; EDONE = 1'b0; end end end always @ (rising_edge_ERES) begin if (reseted) begin if (rising_edge_ERES && !EDONE) begin start_ers = $time; EDONE = 1'b0; #duration_ers EDONE = 1'b1; end end end //////////////////////////////////////////////////////////////////////////// // Main Behavior Process // combinational process for next state generation //////////////////////////////////////////////////////////////////////////// //WRITE CYCLE TRANSITIONS always @(falling_edge_write or rising_edge_reseted or rising_edge_TR_out or rising_edge_TRP_out or rising_edge_TPT_out or rising_edge_TPRE_out or rising_edge_PROG1_out or rising_edge_PROG_out or rising_edge_DBSY_out or rising_edge_DBSY1_out or rising_edge_ERS_SUSP_out or rising_edge_WAIT_OTP_out or rising_edge_DEF_OTP_out or rising_edge_PROG2_out or RSTDONE or rising_edge_OTP_out or rising_edge_EDONE) begin if (reseted != 1'b1 ) next_state <= current_state; else if (rising_edge_reseted) next_state <= BUFF_TR; else case (current_state) IDLE : begin if (falling_edge_write) begin if (CLE && !ALE && (Data==16'h00)) next_state <= PREL_RD; else if (CLE && !ALE && (Data==16'h90)) next_state <= ID_PREL; else if (CLE && !ALE && (Data==16'h80)) next_state <= PREL_PRG; else if (CLE && !ALE && (Data==16'h60)) next_state <= PREL_ERS; else if (CLE && !ALE && (Data==16'h70)) next_state <= IDLE; else if (CLE && !ALE && (Data==16'hB0)) if (!ESUSP_ACT) next_state <= PREL_OTP; else next_state <= IDLE; else next_state <= IDLE; end end UNKNOWN: begin if (falling_edge_write && CLE && !ALE && (Data==16'hFF)) next_state <= RESET; end RESET: begin if (RSTDONE) next_state <= IDLE; end PREL_RD: begin if (falling_edge_write) begin if (ALE) next_state <= A0_RD; else next_state <= IDLE; end end A0_RD: begin if (falling_edge_write) begin if (ALE) next_state <= A1_RD; else next_state <= IDLE; end end A1_RD: begin if (falling_edge_write) begin if (ALE) next_state <= A2_RD; else next_state <= IDLE; end end A2_RD: begin if (falling_edge_write) begin if (ALE) next_state <= A3_RD; else next_state <= IDLE; end end A3_RD: begin if (falling_edge_write) begin if (ALE) next_state <= RD_WCMD; else if (CLE && (Data == 16'h30)) begin if (ESUSP_ACT && (TmpBlck == ErsBlck)) next_state <= IDLE; else next_state <= BUFF_TR; end else if (CLE && (Data == 16'h31)) begin if (ESUSP_ACT && (TmpBlck == ErsBlck)) next_state <= IDLE; else next_state <= BUFF_TR; end else if (CLE && (Data == 16'h32)) begin if (!ESUSP_ACT) next_state <= BUFF_TR; else next_state <= IDLE; end else if (CLE && (Data == 16'h33)) begin if (!ESUSP_ACT) next_state <= BUFF_TR; else next_state <= IDLE; end else if (CLE && (Data == 16'h35)) begin if (ESUSP_ACT && (TmpBlck == ErsBlck)) next_state <= IDLE; else next_state <= BUFF_TR; end else next_state <= IDLE; end end RD_WCMD: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'h30)) begin if (ESUSP_ACT && (TmpBlck == ErsBlck)) next_state <= IDLE; else next_state <= BUFF_TR; end else if (CLE && !ALE && (Data == 16'h31)) begin if (ESUSP_ACT && (TmpBlck == ErsBlck)) next_state <= IDLE; else next_state <= BUFF_TR; end else if (CLE && !ALE && (Data == 16'h32)) begin if (!ESUSP_ACT) next_state <= BUFF_TR; else next_state <= IDLE; end else if (CLE && !ALE && (Data == 16'h33)) begin if (!ESUSP_ACT) next_state <= BUFF_TR; else next_state <= IDLE; end else if (CLE && !ALE && (Data == 16'h35)) begin if (ESUSP_ACT && (TmpBlck == ErsBlck)) next_state <= IDLE; else next_state <= BUFF_TR; end else if (CLE) next_state <= IDLE; end end BUFF_TR: begin if (rising_edge_TR_out) next_state <= RD; else if (rising_edge_TRP_out) next_state <= RD; else if (rising_edge_TPT_out) next_state <= RD; else if (rising_edge_TPRE_out) next_state <= RD; end RD: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'h00)) begin if (STAT_ACT) next_state <= RD; else next_state <= PREL_RD; end else if (CLE && !ALE && (Data == 16'h80) && !PGD_ACT && !PIPR_ACT) next_state <= PREL_PRG; else if (CLE && !ALE && (Data == 16'h90) && !PGD_ACT && !PIPR_ACT) next_state <= ID_PREL; else if (CLE && !ALE && (Data == 16'h70)) next_state <= RD; else if (CLE && (Data == 16'h60) && !ALE && !PGD_ACT && !PIPR_ACT) next_state <= PREL_ERS; else if (CLE && !ALE && (Data == 16'h85) && PGD_ACT) next_state <= PGD_PREL; else if (CLE && !ALE && (Data == 16'h05) && !PGD_ACT && !PIPR_ACT) next_state <= CAC_PREL; else if (CLE && !ALE && (Data == 16'hB0) && !PGD_ACT && !PIPR_ACT) begin if (!ESUSP_ACT) next_state <= PREL_OTP; else next_state <= IDLE; end else next_state <= IDLE; end end CAC_PREL: begin if (falling_edge_write) begin if (ALE) next_state <= A0_CAC; else next_state <= IDLE; end end A0_CAC: begin if (falling_edge_write) begin if (ALE) next_state <= A1_CAC; else next_state <= IDLE; end end A1_CAC: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hE0)) next_state <= RD; else next_state <= IDLE; end end ID_PREL: begin if (falling_edge_write) begin if (ALE && (AddrCom == 16'h00)) next_state <= ID; else next_state <= IDLE; end end ID: begin if (falling_edge_write) begin if (CLE && !ALE && (Data==8'h00)) next_state <= PREL_RD; else if (CLE && !ALE && (Data==8'h90)) next_state <= ID_PREL; else if (CLE && !ALE && (Data==8'h80)) next_state <= PREL_PRG; else if (CLE && !ALE && (Data==8'h60)) next_state <= PREL_ERS; else if (CLE && !ALE && (Data==8'h70)) next_state <= IDLE; else if (CLE && !ALE && (Data==8'hB0)) if (!ESUSP_ACT) next_state <= PREL_OTP; else next_state <= IDLE; else next_state <= IDLE; end end PREL_PRG: begin if (falling_edge_write) begin if (ALE) next_state <= A0_PRG; else next_state <= IDLE; end end A0_PRG: begin if (falling_edge_write) begin if (ALE) next_state <= A1_PRG; else next_state <= IDLE; end end A1_PRG: begin if (falling_edge_write) begin if (ALE) next_state <= A2_PRG; else next_state <= IDLE; end end A2_PRG: begin if (falling_edge_write) begin if (ALE) next_state <= A3_PRG; else next_state <= IDLE; end end A3_PRG: begin if (falling_edge_write) begin if (ALE) next_state <= DATA_PRG; else if (!ALE && !CLE) next_state <= DATA_PRG; else if (CLE && (Data == 8'h10)) begin if (ESUSP_ACT && (WrBlck == ErsBlck)) next_state <= IDLE; else begin if (PRG_ACT) next_state <= WFPPD; else next_state <= PGMS; end end else if (CLE && !PGD_ACT && (Data == 16'h15)) begin if (!ESUSP_ACT) begin if (PRG_ACT) next_state <= WFPD;//Waiting for programm. done else next_state <= CBSY; end else next_state <= IDLE; end else next_state <= IDLE; end end DATA_PRG: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 8'h10)) begin if (ESUSP_ACT && (WrBlck == ErsBlck)) next_state <= IDLE; else begin if (PRG_ACT) next_state <= WFPPD;// Waiting for program. done else next_state <= PGMS; end end else if (CLE && !ALE && !PGD_ACT && (Data == 16'h15)) begin if (!ESUSP_ACT) begin if (PRG_ACT) next_state <= WFPD;//Waiting for programing done else next_state <= CBSY; end else next_state <= IDLE; end else if (CLE && !ALE && (Data == 16'h85)) next_state <= PGMS_CAC; else if (CLE) next_state <= UNKNOWN; else if (!ALE && !CLE) next_state <= DATA_PRG; end end WFPD: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hFF)) next_state <= RESET; // reset end else if (rising_edge_PROG1_out) next_state <= CBSY; // programming done end WFPPD: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hFF)) next_state <= RESET; // reset end else if (rising_edge_PROG1_out) next_state <= PGMS; // next start programing end PGMS_CAC: begin if (falling_edge_write) begin if (ALE) next_state <= A0_PRG_CAC; else next_state <= IDLE; end end A0_PRG_CAC: begin if (falling_edge_write) begin if (ALE) next_state <= DATA_PRG; else next_state <= IDLE; end end PGMS: begin if (rising_edge_PROG_out) next_state <= IDLE; // programming done else if (rising_edge_PROG2_out) next_state <= IDLE; // programming done else if (rising_edge_DEF_OTP_out) next_state <= IDLE; // otp page protect done end CBSY: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hFF)) next_state <= RESET; // reset end else if (rising_edge_DBSY_out) next_state <= RDY_PRG; else if (rising_edge_DBSY1_out) next_state <= RDY_PRG; end RDY_PRG: begin if (falling_edge_write) begin if (CLE && !ALE && (Data==16'h80)) next_state <= PREL_PRG; else if (CLE && !ALE && (Data == 16'hFF)) next_state <= RESET; else if (CLE && !ALE && (Data == 16'h70)) next_state <= RDY_PRG; else next_state <= IDLE; end else if (rising_edge_PROG1_out) next_state <= IDLE; end PREL_ERS: begin if (falling_edge_write) begin if (ALE) next_state <= A1_ERS; else next_state <= IDLE; end end A1_ERS: begin if (falling_edge_write) begin if (ALE) next_state <= A2_ERS; else next_state <= IDLE; end end A2_ERS: begin if (falling_edge_write) begin if (ALE) next_state <= A3_ERS; else if (CLE && (Data == 16'hD0) && (WPNeg !=1'b0) && !WriteProtect) next_state <= ERS_EXEC; else next_state <= IDLE; end end A3_ERS: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hD0) && (WPNeg != 1'b0) && !WriteProtect) next_state <= ERS_EXEC; else if (CLE) next_state <= IDLE; end end ERS_EXEC: begin if (falling_edge_write) begin if (CLE && !ALE && (Data==8'hFF) && !ERS_PRESUS_in) begin next_state <= ERS_SUSP;// wait for erase suspend end end else if (rising_edge_EDONE) next_state <= IDLE; end ERS_SUSP: begin if (falling_edge_write) begin if (CLE && !ALE && (Data==8'hFF)) next_state <= RESET; end else if (rising_edge_ERS_SUSP_out) next_state <= IDLE; // erase suspend end PGD_PREL: begin if (falling_edge_write) begin if (ALE) next_state <= A0_PGD; else next_state <= IDLE; end end A0_PGD: begin if (falling_edge_write) begin if (ALE) next_state <= A1_PGD; else next_state <= IDLE; end end A1_PGD: begin if (falling_edge_write) begin if (ALE) next_state <= A2_PGD; else next_state <= IDLE; end end A2_PGD: begin if (falling_edge_write) begin if (ALE) next_state <= A3_PGD; else next_state <= IDLE; end end A3_PGD: begin if (falling_edge_write) begin if (!ALE && !CLE) next_state <= DATA_PRG; else if (!ALE && CLE && (Data == 16'h10)) begin if (ESUSP_ACT && (WrBlck == ErsBlck)) next_state <= IDLE; else next_state <= PGMS; end else if (!ALE && CLE && (Data == 16'h85)) next_state <= PGMS_CAC; else if (CLE) next_state <= IDLE; end end PREL_OTP: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'h00)) next_state <= WAIT_STATE_2; else if (CLE && !ALE && (Data == 16'h01)) next_state <= WAIT_STATE_2; else if (CLE && !ALE && (Data == 16'h02)) next_state <= WAIT_STATE; else if (CLE && !ALE && (Data == 16'h03)) next_state <= DEF_OVER; else if (CLE && !ALE && (Data == 16'h04)) next_state <= DEF_REM; else if (CLE && !ALE && (Data == 16'h05)) next_state <= WAIT_STATE_1; else if (CLE && !ALE && (Data == 16'hFF)) next_state <= RESET; else next_state <= IDLE; end end WAIT_STATE: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hFF)) next_state <= RESET; else next_state <= IDLE; end else if (rising_edge_WAIT_OTP_out) next_state <= IDLE; end WAIT_STATE_1: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hFF)) next_state <= RESET; else next_state <= IDLE; end else if (rising_edge_WAIT_OTP_out) next_state <= IDLE; end WAIT_STATE_2: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hFF)) next_state <= RESET; else next_state <= IDLE; end else if (rising_edge_OTP_out) next_state <= IDLE; end DEF_OVER: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hFF)) next_state <= RESET; else next_state <= IDLE; end else if (rising_edge_DEF_OTP_out) next_state <= IDLE; end DEF_REM: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hFF)) next_state <= RESET; else next_state <= IDLE; end else if (rising_edge_DEF_OTP_out) next_state <= IDLE; end endcase case (current_state) IDLE, PREL_RD, A0_RD, A1_RD, A2_RD, A3_RD, RD_WCMD, RD, CAC_PREL, A0_CAC, A1_CAC, ID_PREL, ID, PREL_PRG, PGD_PREL, A0_PRG, A1_PRG, A2_PRG, A3_PRG, DATA_PRG, PGMS_CAC, A0_PRG_CAC, PGMS, PREL_ERS, A1_ERS, A2_ERS, A3_ERS, A0_PGD, A1_PGD, A2_PGD, A3_PGD: begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hFF)) if (!ESUSP_ACT) next_state <= RESET; else next_state <= current_state; end end BUFF_TR : begin if (falling_edge_write) begin if (CLE && !ALE && (Data == 16'hFF) && !TPRE_in) if (!ESUSP_ACT) next_state <= RESET; else next_state <= current_state; end end endcase end /////////////////////////////////////////////////////////////////////////// //FSM Output generation and general funcionality /////////////////////////////////////////////////////////////////////////// always @(posedge read) begin ->oe_event; end always @(oe_event) begin oe = 1'b1; #1 oe = 1'b0; end always @(oe or falling_edge_write or rising_edge_reseted or current_state or rising_edge_RENeg or rising_edge_CENeg or rising_edge_TR_out or rising_edge_TRP_out or rising_edge_TPT_out or rising_edge_TPRE_out or rising_edge_PROG1_out or rising_edge_PROG_out or rising_edge_PROG2_out or rising_edge_DBSY_out or rising_edge_DBSY1_out or rising_edge_ERS_SUSP_out or rising_edge_WAIT_OTP_out or rising_edge_ERS_PRESUS_out or rising_edge_OTP_out or rising_edge_DEF_OTP_out or rising_edge_EDONE or WPNeg or PRG_ACT or ALE or CLE or AddrCom or Data or RSTDONE) begin: Functional Status[7] = WPNeg; if (!reseted) RY_zd <= 1'b0; else if (rising_edge_reseted) begin TPRE_in <= 1'b1; if (OTPDefault)// Overlaid OTPOverlay <= 1'b1; else OTPOverlay <= 1'b0; end else case (current_state) IDLE: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'h70)) STAT_ACT <= 1'b1; else if (CLE && !ALE && (Data == 16'h00)) STAT_ACT <= 1'b0; else if (CLE && !ALE && (Data == 16'h90)) STAT_ACT <= 1'b0; else if (CLE && !ALE && (Data == 16'hB0)) STAT_ACT <= 1'b0; else if (CLE && !ALE && (Data == 16'h80)) begin STAT_ACT <= 1'b0; if (WPNeg) WriteProtect = 1'b0; else WriteProtect = 1'b1; end else if (CLE && !ALE && (Data==16'h60)) begin STAT_ACT <= 1'b0; if (WPNeg) WriteProtect = 1'b0; else WriteProtect = 1'b1; end else if (CLE && !ALE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; OTP_STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; end else STAT_ACT <= 1'b0; end if ((rising_edge_PROG_out && flagPROG) || rising_edge_PROG1_out || rising_edge_PROG2_out ) EndProgramming; if (oe && STAT_ACT) DOut_zd <= Status; end UNKNOWN: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF)) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; ERS_ACT <= 1'b0; PGD_ACT <= 1'b0; RD_ACT <= 1'b0; PIPR_ACT <= 1'b0; PGR_ACT <= 1'b0; PRG_ACT <= 1'b0; Status[5] = 1'b1; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; end end end RESET: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'h70)) STAT_ACT <= 1'b1; end if (RSTDONE) begin RY_zd <= 1'b1; Status[6:5] = 2'b11; Status[1:0] = 2'b00; OTP_STAT_ACT <= 1'b0; PRG_ACT <= 1'b0; ERS_ACT <= 1'b0; RD_ACT <= 1'b0; PGD_ACT <= 1'b0; PIPR_ACT <= 1'b0; PGR_ACT <= 1'b0; Protect = 1'b0; if (OTPDefault == Overlaid) OTPOverlay <= 1'b1; else OTPOverlay <= 1'b0; end if (oe) begin if (STAT_ACT) DOut_zd <= Status; end end PREL_RD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) ColAddr[7:0] = AddrCom; else if (CLE && !ALE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A0_RD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) ColAddr[15:8] = AddrCom; else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A1_RD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) RowAddr[7:0] = AddrCom; else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A2_RD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) begin RowAddr[15:8] = AddrCom; RowAddr[23:16] = 8'h00; getPage(RowAddr); getAddress(ColAddr); end else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A3_RD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) begin RowAddr[23:16] = AddrCom; getPage(RowAddr); getAddress(ColAddr); end else if (CLE && (Data == 16'h30) && ((ESUSP_ACT && (TmpBlck != ErsBlck)) || !ESUSP_ACT)) begin PGR_ACT <= 1'b1; PIPR_ACT <= 1'b0; FirstPipe = 1'b1; RdPage = TmpPage; RdBlck = TmpBlck; RdAddr = AddrWithinPage; RdSeg = TmpSegm; TR_in <= 1'b1; RY_zd <= 1'b0; Status[6:5] = 2'b00; end else if (CLE && (Data == 16'h31) && ((ESUSP_ACT && (TmpBlck != ErsBlck)) || !ESUSP_ACT)) begin PPGR_ACT <= 1'b1; PGR_ACT <= 1'b1; RdPage = TmpPage; RdBlck = TmpBlck; RdAddr = AddrWithinPage; RdSeg = TmpSegm; TRP_in <= 1'b1; RY_zd <= 1'b0; Status[6:5] = 2'b00; end else if (CLE && (Data == 16'h32) && !ESUSP_ACT) begin PIPR_ACT <= 1'b1; if (FirstPipe) FirstPipe = 1'b0; else begin RdPage = PIP_Page; RdBlck = PIP_Blck; RdAddr = PIP_Addr; end PGR_ACT <= 1'b1; PIP_Page = TmpPage; PIP_Blck = TmpBlck; PIP_Addr = AddrWithinPage; TPT_in <= 1'b1; // Time for pipeline read RY_zd <= 1'b0; Status[6:5] = 2'b00; OTPOverlay = OTPOverlayPIP; end else if (CLE && (Data == 16'h33) && !ESUSP_ACT) begin TPT_in <= 1'b1; // Time for pipeline read PIPR_ACT <= 1'b0; FirstPipe = 1'b1; PGR_ACT <= 1'b1; RdAddr = PIP_Addr; RdPage = PIP_Page; RdBlck = PIP_Blck; RY_zd <= 1'b0; Status[6:5] = 2'b00; OTPOverlay = OTPOverlayPIP; end else if (CLE && (Data == 16'h35) && ((ESUSP_ACT && (TmpBlck != ErsBlck)) || !ESUSP_ACT)) begin PGD_ACT <= 1'b1; PGR_ACT <= 1'b1; TR_in <= 1'b1; RY_zd <= 1'b0; Status[6:5] = 2'b00; RdPage = TmpPage; RdBlck = TmpBlck; RdAddr = AddrWithinPage; for (i=0; i<=PageSize; i=i+1) PDBuffer[i] = -1; end else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end RD_WCMD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'h30) && ((ESUSP_ACT && (TmpBlck != ErsBlck)) || !ESUSP_ACT)) begin PGR_ACT <= 1'b1; PIPR_ACT <= 1'b0; FirstPipe = 1'b1; RdPage = TmpPage; RdBlck = TmpBlck; RdAddr = AddrWithinPage; RdSeg = TmpSegm; TR_in <= 1'b1; RY_zd <= 1'b0; Status[6:5] = 2'b00; end else if (CLE && !ALE && (Data == 16'h31) && ((ESUSP_ACT && (TmpBlck != ErsBlck)) || !ESUSP_ACT)) begin PPGR_ACT <= 1'b1; PGR_ACT <= 1'b1; RdPage = TmpPage; RdBlck = TmpBlck; RdAddr = AddrWithinPage; RdSeg = TmpSegm; TRP_in <= 1'b1; RY_zd <= 1'b0; Status[6:5] = 2'b00; end else if (CLE && !ALE && (Data == 16'h32) && !ESUSP_ACT) begin PIPR_ACT <= 1'b1; if (FirstPipe) FirstPipe = 1'b0; else begin RdPage = PIP_Page; RdBlck = PIP_Blck; RdAddr = PIP_Addr; end PGR_ACT <= 1'b1; PIP_Page = TmpPage; PIP_Blck = TmpBlck; PIP_Addr = AddrWithinPage; TPT_in <= 1'b1; //Time for pipeline read RY_zd <= 1'b0; Status[6:5] = 2'b00; OTPOverlay = OTPOverlayPIP; end else if (CLE && !ALE && (Data == 16'h33) && !ESUSP_ACT) begin TPT_in <= 1'b1; // Time for pipeline read PIPR_ACT <= 1'b0; FirstPipe = 1'b1; PGR_ACT <= 1'b1; RdAddr = PIP_Addr; RdPage = PIP_Page; RdBlck = PIP_Blck; RY_zd <= 1'b0; Status[6:5] = 2'b00; OTPOverlay = OTPOverlayPIP; end else if (CLE && !ALE && (Data == 16'h35) && ((ESUSP_ACT && (TmpBlck != ErsBlck)) || !ESUSP_ACT)) begin PGD_ACT <= 1'b1; PGR_ACT <= 1'b1; TR_in <= 1'b1; RY_zd <= 1'b0; Status[6:5] = 2'b00; getPage(RowAddr); getAddress(ColAddr); RdPage = TmpPage; RdBlck = TmpBlck; RdAddr = AddrWithinPage; for (i=0; i<=PageSize; i=i+1) PDBuffer[i] = -1; end else if (CLE && !ALE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end BUFF_TR: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF) && !TPRE_in && !ESUSP_ACT) begin TR_in <= 1'b0; TRP_in <= 1'b0; TPT_in <= 1'b0; DBSY_in <= 1'b0; STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end else if (CLE && !ALE && (Data == 16'h70)) STAT_ACT <= 1'b1; end else if (rising_edge_TR_out) begin PGR_ACT <= 1'b0; RY_zd <= 1'b1; Status[6:5]= 2'b11; TR_in <= 1'b0; if (PGD_ACT) begin if (OTPOverlay && (RdBlck == 0)) begin if (RdPage <= 7) for (i=0; i<=PageSize; i=i+1) PDBuffer[i] = OTP_Area[RdPage*(PageSize+1) + i]; else for (i=0; i<=PageSize; i=i+1) PDBuffer[i] = 16'hFF; end else for (i=0; i<=PageSize; i=i+1) PDBuffer[i] = Mem[RdPage*(PageSize+1)+i]; end end else if (rising_edge_TRP_out) begin PGR_ACT <= 1'b0; RY_zd <= 1'b1; Status[6:5] = 2'b11; TRP_in <= 1'b0; end else if (rising_edge_TPT_out) begin PGR_ACT <= 1'b0; RY_zd <= 1'b1; Status[6:5] = 2'b11; TPT_in <= 1'b0; end else if (rising_edge_TPRE_out) begin PGR_ACT <= 1'b0; RY_zd <= 1'b1; Status[6:5] = 2'b11; TPRE_in <= 1'b0; RdPage = 0; RdBlck = 0; RdAddr = 0; RdSeg = 0; end if (oe) begin if (PIPR_ACT) begin if (OTPOverlay && (RdBlck == 0)) Read_OTP(RdPage, RdAddr); else Read_Data(RdPage, RdAddr); end else if (STAT_ACT) DOut_zd <= Status; end end RD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'h00)) begin if (STAT_ACT) STAT_ACT <= 1'b0; else begin PPGR_ACT <= 1'b0; PGD_ACT <= 1'b0; OTPOverlayPIP = OTPOverlay; if (OTPDefault == Overlaid) OTPOverlay <= 1'b1; else OTPOverlay <= 1'b0; end end else if (CLE && !ALE && (Data == 16'h70)) begin STAT_ACT <= 1'b1; end else if (CLE && !ALE && (Data == 16'h90) && !PGD_ACT && !PIPR_ACT) begin STAT_ACT <= 1'b0; PPGR_ACT <= 1'b0; if (OTPDefault == Overlaid) OTPOverlay <= 1'b1; else OTPOverlay <= 1'b0; end else if (CLE && !ALE && (Data == 16'h80) && !PGD_ACT && !PIPR_ACT) begin STAT_ACT <= 1'b0; PPGR_ACT <= 1'b0; if (OTPDefault == Overlaid ) OTPOverlay <= 1'b1; else OTPOverlay <= 1'b0; if (WPNeg) WriteProtect = 1'b0; else WriteProtect = 1'b1; end else if (CLE && !ALE && (Data == 16'h60) && !PGD_ACT && !PIPR_ACT) begin STAT_ACT <= 1'b0; PPGR_ACT <= 1'b0; if (OTPDefault == Overlaid) OTPOverlay <= 1'b1; else OTPOverlay <= 1'b0; if (WPNeg) WriteProtect = 1'b0; else WriteProtect = 1'b1; end else if (CLE && !ALE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end else if (CLE && !ALE && (Data == 16'h85) && PGD_ACT) begin PPGR_ACT <= 1'b0; STAT_ACT <= 1'b0; end else if (CLE && !ALE && (Data == 16'h05) && !PGD_ACT && !PIPR_ACT) STAT_ACT <= 1'b0; else if (CLE && !ALE && (Data == 16'hB0) && !PGD_ACT && !PIPR_ACT) begin if (OTPDefault == Overlaid ) OTPOverlay <= 1'b1; else OTPOverlay <= 1'b0; PPGR_ACT <= 1'b0; STAT_ACT <= 1'b0; end else begin STAT_ACT <= 1'b0; PGD_ACT <= 1'b0; PIPR_ACT <= 1'b0; end end if (oe) begin if (!PGD_ACT && !STAT_ACT && !OTP_STAT_ACT) begin if (OTPOverlay && (RdBlck == 0)) Read_OTP(RdPage, RdAddr); else Read_Data(RdPage, RdAddr); end else if (OTP_STAT_ACT && (RdBlck == 0)) begin if (FirstByte) begin DOut_zd <= ProtStatus; FirstByte = 1'b0; end else begin if (OTPDefault == Overlaid) DOut_zd <= 8'h00; else DOut_zd <= 8'h01; OTP_STAT_ACT <= 1'b0; end end else if (STAT_ACT) DOut_zd <= Status; end end CAC_PREL: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) ColAddr[7:0] = AddrCom; else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A0_CAC: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) ColAddr[15:8] = AddrCom; else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A1_CAC: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hE0)) begin getAddress(ColAddr); getSegment(AddrWithinPage, pom_seg); if ((pom_seg % 4) == RdSeg) RdAddr = AddrWithinPage; else begin $display("Changed address is not "); $display("in same partial page"); end end else if (CLE && !ALE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end end end ID_PREL: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE && (AddrCom == 0)) IDAddr <= 0; else if (CLE && !ALE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end ID: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end else if (CLE && !ALE && (Data == 16'h80)) begin if (WPNeg) WriteProtect = 1'b0; else WriteProtect = 1'b1; end else if (CLE && !ALE && (Data == 16'h60)) begin if (WPNeg) WriteProtect = 1'b0; else WriteProtect = 1'b1; end else if (CLE && !ALE && (Data == 16'h70) ) begin STAT_ACT <= 1'b1; if (OTPDefault == Overlaid ) OTPOverlay <= 1'b1; else OTPOverlay <= 1'b0; end else if (CLE && !ALE && (Data == 16'h00)) STAT_ACT <= 1'b0; end if (oe) begin if (IDAddr < 6) begin DOut_zd <= IDArray[IDAddr]; IDAddr <= IDAddr+1; end else DOut_zd <= 8'bZ; end end PREL_PRG: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) ColAddr[7:0] = AddrCom; else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; PRG_ACT <= 1'b0; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end else if (rising_edge_PROG_out || rising_edge_PROG1_out || rising_edge_PROG2_out) EndProgramming; end A0_PRG: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) begin ColAddr[15:8] = AddrCom; getAddress(ColAddr); WrAddr = AddrWithinPage; WrSeg = TmpSegm; end else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end end else if (rising_edge_PROG_out || rising_edge_PROG1_out || rising_edge_PROG2_out ) EndProgramming; end A1_PRG: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) RowAddr[7 : 0] = AddrCom; else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end end else if (rising_edge_PROG_out || rising_edge_PROG1_out || rising_edge_PROG2_out) EndProgramming; end A2_PRG: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) begin RowAddr[15 : 8] = AddrCom; RowAddr[23 : 16]= 8'b0; getPage(RowAddr); WrPage = TmpPage; WrBlck = TmpBlck; for (j=0; j<=PageSize; j=j+1) CashBuffData[j] = -1; if (OTPOverlay && (WrBlck == 0)) begin if (WrPage <= 7) for (j=0; j<=SegmentNum; j=j+1) SegForProg[j] = OTPProgramedFlag[WrPage* (SegmentNum+1)+j]; end else for (j=0; j<=SegmentNum; j=j+1) SegForProg[j] = ProgramedFlag[WrPage* (SegmentNum+1)+j]; SegProgSt = 8'b0; end else if (CLE && (Data == 16'hFF)&& !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end else if (rising_edge_PROG_out || rising_edge_PROG1_out || rising_edge_PROG2_out) EndProgramming; end A3_PRG: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) begin RowAddr[23:16] = AddrCom; getPage(RowAddr); WrPage = TmpPage; WrBlck = TmpBlck; for (j=0; j<=PageSize; j=j+1) CashBuffData[j] = -1; if (OTPOverlay && (WrBlck == 0) ) begin if (WrPage <= 7 ) for (j=0; j<=SegmentNum; j=j+1) SegForProg[j] = OTPProgramedFlag[WrPage* (SegmentNum+1)+j]; end else for (j=0; j<=SegmentNum; j=j+1) SegForProg[j] = ProgramedFlag[WrPage* (SegmentNum+1)+j]; SegProgSt = 8'b0; end else if (!CLE && (WrAddr <= PageSize)) begin getSegment(WrAddr,WrSeg); if (OTPOverlay && (WrBlck == 0)) begin if (WrPage <= 7 ) begin if (ProtStatus[WrPage] && OTPProgramedFlag [WrPage*(SegmentNum+1)+WrSeg]==1'b0) begin CashBuffData[WrAddr] = Data; SegForProg[WrSeg] = 1'b1; SegProgSt[WrSeg] = 1'b1; end end end else begin if (ProgramedFlag[WrPage*(SegmentNum+1) +WrSeg]==1'b0) begin CashBuffData[WrAddr] = Data; SegForProg[WrSeg] = 1'b1; SegProgSt[WrSeg] = 1'b1; end end WrAddr = WrAddr + 1; end else if (CLE && (Data == 16'h10) && ((ESUSP_ACT && (WrBlck != ErsBlck)) || !ESUSP_ACT) ) begin if (!PRG_ACT) begin prog_time = 1; if (!Protect) begin PRG_ACT <= 1'b1; PROG_in <= 1'b1; end else DEF_OTP_in <= 1'b1; end RY_zd <= 1'b0; Status[5] = 1'b0; firstFlag = 1'b1; end else if (CLE && !ALE && !PGD_ACT && (Data == 16'h15) && !ESUSP_ACT) begin if (!PRG_ACT) DBSY_in <= 1'b1; RY_zd <= 1'b0; Status[6] = 1'b0; firstFlag = 1'b1; end else if (CLE && (Data==16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end end else if (rising_edge_PROG_out || rising_edge_PROG1_out || rising_edge_PROG2_out ) EndProgramming; end DATA_PRG: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 8'hFF) && !ESUSP_ACT) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end else if (!ALE && !CLE && (WrAddr <= PageSize)) begin getSegment(WrAddr,WrSeg); if (OTPOverlay && (WrBlck == 0)) begin if (WrPage <= 7 ) begin if (ProtStatus[WrPage] && OTPProgramedFlag [WrPage*(SegmentNum+1)+WrSeg]==1'b0) begin CashBuffData[WrAddr] = Data; SegForProg[WrSeg] = 1'b1; SegProgSt[WrSeg] = 1'b1; end end end else begin if (ProgramedFlag[WrPage*(SegmentNum+1) +WrSeg]==1'b0) begin CashBuffData[WrAddr] = Data; SegForProg[WrSeg] = 1'b1; SegProgSt[WrSeg] = 1'b1; end end WrAddr = WrAddr+1; end else if (CLE && !ALE && (Data==16'h10) && ((ESUSP_ACT && (WrBlck != ErsBlck)) || !ESUSP_ACT) ) begin if (!PRG_ACT) begin Tmp = SegProgSt[3:0] | SegProgSt[7:4]; tmp_cnt = 0; for (i=0; i<=3; i=i+1) begin if (Tmp[i]) tmp_cnt = tmp_cnt + 1; end if (tmp_cnt == 4) prog_time = page_prog_time + WER_01; else if (tmp_cnt == 0 ) prog_time = 1; else prog_time = tmp_cnt*seg_prog_time + WER_01; if (!Protect) begin PRG_ACT <= 1'b1; PROG_in <= 1'b1; end else DEF_OTP_in <= 1'b1; end RY_zd <= 1'b0; Status[5] = 1'b0; firstFlag = 1'b1; end else if (CLE && !ALE && !PGD_ACT && (Data == 16'h15) && !ESUSP_ACT) begin if (!PRG_ACT) DBSY_in <= 1'b1; RY_zd <= 1'b0; Status[6] = 1'b0; firstFlag = 1'b1; end end else if (rising_edge_PROG_out || rising_edge_PROG1_out || rising_edge_PROG2_out) EndProgramming; end PGMS_CAC: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) ColAddr[7 : 0] = AddrCom; else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A0_PRG_CAC: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) begin ColAddr[15:8] = AddrCom; getAddress(ColAddr); WrAddr = AddrWithinPage; WrSeg = TmpSegm; end else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end WFPD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF)) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end else if (CLE && !ALE && (Data == 16'h70)) STAT_ACT <= 1'b1; end else if (rising_edge_PROG1_out) begin DBSY1_in <= 1'b1; Status[5] = 1'b1; end if (rising_edge_PROG_out || rising_edge_PROG1_out || rising_edge_PROG2_out ) EndProgramming; if (oe) if (STAT_ACT) DOut_zd <= Status; end WFPPD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF)) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; PROG1_in <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end else if (CLE && !ALE && (Data == 16'h70)) STAT_ACT <= 1'b1; end else if (rising_edge_PROG1_out) begin flagPROG1 = 1'b0; Status[5] = 1'b0; PROG2_in <= 1'b1; PROG1_in <= 1'b0; Status[1:0] = 2'b00; Tmp = SegProgSt[3:0] | SegProgSt[7:4]; tmp_cnt = 0; for (i=0; i<=3; i=i+1) begin if (Tmp[i]) tmp_cnt = tmp_cnt + 1; end if (tmp_cnt == 4 ) prog_time = page_prog_time; else if (tmp_cnt == 0 ) prog_time = 1; else prog_time = tmp_cnt*seg_prog_time; if ((WPNeg != 1'b0) && !WriteProtect) begin if (OTPOverlay && (ProgBlck == 0)) if (ProgPage <= 7) begin for (j=0; j<=PageSize; j=j+1) begin getSegment(j, pom_seg); if (ProtStatus[ProgPage] && WrBuffData[j] != -1 && OTPProgramedFlag[ProgPage* (SegmentNum+1)+pom_seg]==1'b0) OTP_Area[ProgPage*(PageSize+1)+j] = WrBuffData[j]; end for (j=0; j<=SegmentNum; j=j+1) OTPProgramedFlag[ProgPage*(SegmentNum+1)+j] = CashSegForProg[j]; end else Status[0] = 1'b1; else begin for (j=0; j<=PageSize; j=j+1) begin getSegment(j,pom_seg); if (ProgramedFlag[ProgPage*(SegmentNum+1) +pom_seg]==1'b0 && (WrBuffData[j] != -1)) Mem[ProgPage*(PageSize+1)+j] = WrBuffData[j]; end for (j=0; j<=SegmentNum; j=j+1) ProgramedFlag[ProgPage*(SegmentNum+1)+j] = SegForProg[j]; end end end if (oe) if (STAT_ACT) DOut_zd <= Status; end PGMS: begin if ((WPNeg != 1'b0) && !WriteProtect && firstFlag && !Protect) begin firstFlag = 1'b0; if (OTPOverlay && (WrBlck == 0)) begin if (WrPage <= 7 ) begin for (j=0; j<=PageSize; j=j+1) begin getSegment(j, WrSeg); if ((ProtStatus[WrPage] == 1'b1) && (CashBuffData[j] != -1) ) begin if (OTPProgramedFlag [WrPage*(SegmentNum+1)+WrSeg]==1'b0) OTP_Area[WrPage*(PageSize+1)+j] = -1; else CashBuffData[j] = -1; end end end end else begin for (j=0; j<=PageSize; j=j+1) begin getSegment(j, WrSeg); if ((ProgramedFlag [WrPage*(SegmentNum+1)+WrSeg]==1'b0) && (CashBuffData[j] != -1)) Mem[WrPage*(PageSize+1)+j] = -1; else CashBuffData[j] = -1; end end for (j=0; j<=PageSize; j=j+1) WrBuffData[j] = CashBuffData[j]; ProgPage = WrPage; ProgBlck = WrBlck; end if (rising_edge_PROG_out) begin RY_zd <= 1'b1; PGD_ACT <= 1'b0; end else if (rising_edge_PROG2_out) RY_zd <= 1'b1; else if (rising_edge_DEF_OTP_out) RY_zd <= 1'b1; if (rising_edge_PROG_out || (rising_edge_PROG1_out && flagPROG1) || rising_edge_PROG2_out) begin flagPROG = 1'b0; PRG_ACT <= 1'b0; Status[5] = 1'b1; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; Status[1:0] = 2'b00; if ((WPNeg != 1'b0) && !WriteProtect && !Protect) begin if (OTPOverlay && (ProgBlck == 0)) begin if (ProgPage <= 7 ) begin for (j=0; j<=PageSize; j=j+1) begin getSegment(j, pom_seg); if (ProtStatus[ProgPage] && WrBuffData[j] != -1 && OTPProgramedFlag[ProgPage* (SegmentNum+1)+pom_seg]==1'b0) OTP_Area[ProgPage*(PageSize+1)+j] = WrBuffData[j]; end for (j=0; j<=SegmentNum; j=j+1) OTPProgramedFlag[ProgPage*(SegmentNum+1)+j] = SegForProg[j]; end else Status[0] = 1'b1; end else begin for (j=0; j<=PageSize; j=j+1) begin getSegment(j,pom_seg); if (ProgramedFlag[ProgPage*(SegmentNum+1) +pom_seg]==1'b0 && (WrBuffData[j] != -1)) Mem[ProgPage*(PageSize+1)+j] = WrBuffData[j]; end for (j=0; j<=SegmentNum; j=j+1) ProgramedFlag[ProgPage*(SegmentNum+1)+j] = SegForProg[j]; end end if (OTPDefault == Overlaid) OTPOverlay <= #1 1'b1; else OTPOverlay <= #1 1'b0; end else if (rising_edge_DEF_OTP_out) begin if ((WPNeg != 1'b0) && !WriteProtect && Protect) begin ProtStatus[ProgPage] = 1'b0; Protect = 1'b0; Status[5] = 1'b1; Status[0] = 1'b1; end DEF_OTP_in <= 1'b0; end if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF) && !ESUSP_ACT) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; DEF_OTP_in <= 1'b0; end else if (CLE && !ALE && (Data == 16'h70)) STAT_ACT <= 1'b1;// read status end if (oe) if (STAT_ACT) DOut_zd <= Status; end CBSY: begin if (firstFlag) begin Status[6] = 1'b0; firstFlag = 1'b0; CWrPage = WrPage; end if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF)) begin DBSY_in <= 1'b0; DBSY1_in <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end else if (CLE && !ALE && (Data == 16'h70)) STAT_ACT <= 1'b1; //read status end else if (rising_edge_DBSY_out) begin if ((WPNeg != 1'b0) && !WriteProtect) begin if (OTPOverlay && (WrBlck == 0 )) begin if (CWrPage <= 7 ) begin if (ProtStatus[CWrPage]==1'b1) begin for (j=0; j<=PageSize; j=j+1) begin if (CashBuffData[j] != -1) OTP_Area[CWrPage*(PageSize+1)+j]=-1; end end end end else begin for (j=0; j<=PageSize; j=j+1) begin if (CashBuffData[j] != -1) Mem[CWrPage*(PageSize+1)+j] = -1; end end end PRG_ACT <= 1'b1; PROG1_in <= 1'b1 ; Tmp = SegProgSt[3:0] | SegProgSt[7:4]; tmp_cnt = 0; for (i=0; i<=3; i=i+1) begin if (Tmp[i]) tmp_cnt = tmp_cnt + 1; end if (tmp_cnt == 4 ) prog_time = page_prog_time; else if (tmp_cnt == 0 ) prog_time = 1; else prog_time = tmp_cnt*seg_prog_time; Status[6] = 1'b1; Status[5] = 1'b0; RY_zd <= 1'b1; DBSY_in <= 1'b0; Status[6] = 1'b1; for (j=0; j<=PageSize; j=j+1) WrBuffData[j] = CashBuffData[j]; ProgPage = CWrPage; ProgBlck = WrBlck; CashSegForProg = SegForProg; end else if (rising_edge_DBSY1_out) begin if ((WPNeg != 1'b0) && !WriteProtect) begin if (OTPOverlay && (WrBlck == 0 )) begin if (CWrPage <= 7 ) begin if (ProtStatus[CWrPage]==1'b1) begin for (j=0; j<=PageSize; j=j+1) begin if (CashBuffData[j] != -1) OTP_Area[CWrPage*(PageSize+1)+j]=-1; end end end end else begin for (j=0; j<=PageSize; j=j+1) begin if (CashBuffData[j] != -1) Mem[CWrPage*(PageSize+1)+j] = -1; end end end PRG_ACT <= 1'b1; PROG1_in <= 1'b1 ; Tmp = SegProgSt[3:0] | SegProgSt[7:4]; tmp_cnt = 0; for (i=0; i<=3; i=i+1) begin if (Tmp[i]) tmp_cnt = tmp_cnt + 1; end if (tmp_cnt == 4 ) prog_time = page_prog_time; else if (tmp_cnt == 0 ) prog_time = 1; else prog_time = tmp_cnt*seg_prog_time; Status[6] = 1'b1; Status[5] = 1'b0; RY_zd <= 1'b1; DBSY1_in <= 1'b0; Status[6] = 1'b1; ProgPage = CWrPage; ProgBlck = WrBlck; for (j=0; j<=PageSize; j=j+1) WrBuffData[j] = CashBuffData[j]; CashSegForProg = SegForProg; end if (oe) if (STAT_ACT) DOut_zd <= Status; end RDY_PRG: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'h70)) STAT_ACT <= 1'b1; else if (CLE && !ALE && (Data == 16'h80)) STAT_ACT <= 1'b0; else if (CLE && !ALE && (Data == 16'hFF)) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end else STAT_ACT <= 1'b0; end else if (rising_edge_PROG1_out) begin RY_zd <= 1'b1; Status[5] = 1'b1; end if (rising_edge_PROG_out || rising_edge_PROG1_out || rising_edge_PROG2_out ) EndProgramming; if (oe) if (STAT_ACT) DOut_zd <= Status; end PREL_ERS: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) RowAddr[7 : 0] = AddrCom; else if (CLE && !ALE && (Data == 16'hFF) && !ESUSP_ACT) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end end end A1_ERS: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) begin RowAddr[15 : 8] = AddrCom; RowAddr[23 : 16] = 8'b0; end else if (CLE && (Data == 16'hFF) && !ESUSP_ACT) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A2_ERS: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) RowAddr[23 : 16] = AddrCom; else if (CLE && (Data == 8'hD0) && (WPNeg != 1'b0) && !WriteProtect) begin if (!ESUSP_ACT) begin getPage(RowAddr); ErsBlck = TmpBlck; if (OTPOverlay && (ErsBlck == 0)) begin if (ProtStatus == 8'hFF) begin for (i=0; i<=OTPPageNum; i=i+1) begin for (j=0; j<=PageSize; j=j+1) OTP_Area[i*(PageSize+1)+j]=-1; for (j=0; j<=SegmentNum; j=j+1) OTPProgramedFlag [i*(SegmentNum+1)+j]= 0; end end end else begin for (i=ErsBlck*PageNumInBl; i<= (ErsBlck*PageNumInBl)+BlockSize; i=i+1) begin for (j=0; j<=PageSize; j=j+1) Mem[i*(PageSize+1)+j] = -1; for (j=0; j<=SegmentNum; j=j+1) ProgramedFlag[i*(SegmentNum+1)+j]=1'b0; end end ESTART <= 1'b1; ESTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; ERS_PRESUS_in <= 1'b1; end else begin RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1] = 1'b0; Status[0] = 1'b0; ESUSP_ACT <= 1'b0; ERES <= 1'b1; ERES <= #1 1'b0; ERS_PRESUS_in <= 1'b1; end end else if (CLE && (Data == 8'hFF) && !ESUSP_ACT) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A3_ERS: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 8'hFF) && !ESUSP_ACT) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end else if (CLE && !ALE && (Data == 8'hD0) && (WPNeg != 1'b0) && !WriteProtect) begin if (!ESUSP_ACT) begin getPage(RowAddr); ErsBlck = TmpBlck; if (OTPOverlay && (ErsBlck == 0) ) begin if (ProtStatus == 8'hFF) begin for (i=0; i<=7; i=i+1) begin for (j=0; j<=PageSize; j=j+1) OTP_Area[i*(PageSize+1)+j]=-1; for (j=0; j<=SegmentNum; j=j+1) OTPProgramedFlag [i*(SegmentNum+1)+j]= 0; end end end else begin for (i=ErsBlck*PageNumInBl; i<= (ErsBlck*PageNumInBl)+BlockSize; i=i+1) begin for (j=0; j<=PageSize; j=j+1) Mem[i*(PageSize+1)+j] = -1; for (j=0; j<=SegmentNum; j=j+1) ProgramedFlag[i*(SegmentNum+1)+j]=1'b0; end end ESTART <= 1'b1; ESTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; ERS_PRESUS_in <= 1'b1; end else begin RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1] = 1'b0; Status[0] = 1'b0; ESUSP_ACT <= 1'b0; ERES <= 1'b1; ERES <= #1 1'b0; ERS_PRESUS_in <= 1'b1; end end end end ERS_EXEC: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF) && !ERS_PRESUS_in) begin ERS_SUSP_in <= 1'b1; STAT_ACT <= 1'b0; end else if (CLE && !ALE && (Data == 16'h70) ) STAT_ACT <= 1'b1; end else if (rising_edge_EDONE) begin if (OTPOverlay && (ErsBlck == 0) ) begin if (ProtStatus == 8'hFF) begin for (i=0; i<=7; i=i+1) begin for (j=0; j<=PageSize; j=j+1) OTP_Area[i*(PageSize+1)+j]=MaxData; for (j=0; j<=SegmentNum; j=j+1) OTPProgramedFlag [i*(SegmentNum+1)+j]= 0; end end end else begin for (i=ErsBlck*PageNumInBl; i<= (ErsBlck*PageNumInBl)+BlockSize; i=i+1) begin for (j=0; j<=PageSize; j=j+1) Mem[i*(PageSize+1)+j] = MaxData; for (j=0; j<=SegmentNum; j=j+1) ProgramedFlag[i*(SegmentNum+1)+j] = 1'b0; end end RY_zd <= 1'b1; Status[6:5] = 2'b11; Status[1:0] = 2'b00; ERS_PRESUS_in <= 1'b0; if (OTPDefault == Overlaid ) OTPOverlay = 1'b1; else OTPOverlay = 1'b0; end else if (rising_edge_ERS_PRESUS_out) ERS_PRESUS_in <= 1'b0; if (oe) if (STAT_ACT) DOut_zd <= Status; end ERS_SUSP: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF)) begin RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; STAT_ACT <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; ERS_SUSP_in <= 1'b0; end else if (CLE && !ALE && (Data == 16'h70) ) STAT_ACT <= 1'b1; end else if (rising_edge_ERS_SUSP_out) begin ESUSP <= 1'b1; ESUSP <= #1 1'b0; ESUSP_ACT <= 1'b1; ERS_SUSP_in <= 1'b0; Status[6:5] = 2'b11; Status[1:0] = 2'b11; RY_zd <= 1'b1; end if (oe) if (STAT_ACT) DOut_zd <= Status; end PGD_PREL: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) ColAddr[7:0] = AddrCom; else if (CLE&& (Data==16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A0_PGD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) begin ColAddr[15 : 8] = AddrCom; getAddress(ColAddr); WrAddr = AddrWithinPage; WrSeg = TmpSegm; end else if (CLE && (Data==16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A1_PGD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) RowAddr[7 : 0] = AddrCom; else if (CLE && (Data==16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end end end A2_PGD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) begin RowAddr[15 : 8] = AddrCom; RowAddr[23 : 16]= 8'b0; getPage(RowAddr); WrPage = TmpPage; WrBlck = TmpBlck; for (j=0; j<=PageSize; j=j+1) CashBuffData[j] = PDBuffer[j]; for (j=0; j<=SegmentNum; j=j+1) SegForProg[j] = 1'b1; for (j=0; j<=SegmentNum; j=j+1) SegProgSt[j] = 1'b1; end else if (CLE && (Data==16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end A3_PGD: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (ALE) begin RowAddr[23:16] = AddrCom; getPage(RowAddr); WrPage = TmpPage; WrBlck = TmpBlck; for (j=0; j<=PageSize; j=j+1) CashBuffData[j] = PDBuffer[j]; for (j=0; j<=SegmentNum; j=j+1) SegForProg[j] = 1'b1; for (j=0; j<=SegmentNum; j=j+1) SegProgSt[j] = 1'b1; end else if (!CLE && (WrAddr <= PageSize) ) begin getSegment(WrAddr, WrSeg); if (ProgramedFlag[WrPage*(SegmentNum+1) +WrSeg]==1'b0) CashBuffData[WrAddr] = Data; SegForProg[WrSeg] = 1'b1; WrAddr = WrAddr+1; end else if (CLE && (Data==16'h10) && ((ESUSP_ACT && (WrBlck != ErsBlck)) || !ESUSP_ACT)) begin prog_time = page_prog_time + WER_01; PRG_ACT <= 1'b1; PROG_in <= 1'b1; RY_zd <= 1'b0; Status[5] = 1'b0; firstFlag = 1'b1; end else if (CLE && (Data==16'hFF) && !ESUSP_ACT) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end end PREL_OTP: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'h00) ) begin OTPOverlay = 1'b1; OTP_in <= 1'b1; RY_zd <= 1'b0; end else if (CLE && !ALE && (Data == 16'h01) ) begin OTPOverlay = 1'b0; OTP_in <= 1'b1; RY_zd <= 1'b0; end else if (CLE && !ALE && (Data == 16'h02) ) begin OTP_STAT_ACT <= 1'b1; FirstByte = 1'b1; WAIT_OTP_in <= 1'b1; end else if (CLE && !ALE && (Data == 16'h03) ) begin DEF_OTP_in <= 1'b1; RY_zd <= 1'b0; Status[6:5] = 2'b00; end else if (CLE && !ALE && (Data == 16'h04) ) begin DEF_OTP_in <= 1'b1; RY_zd <= 1'b0; Status[6:5] = 2'b00; end else if (CLE && !ALE && (Data == 16'h05) ) WAIT_OTP_in <= 1'b1; else if (CLE && !ALE && (Data == 16'hFF) ) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end end end WAIT_STATE: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF) ) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end end else if (rising_edge_WAIT_OTP_out) WAIT_OTP_in <= 1'b0; end WAIT_STATE_1: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF) ) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1:0] = 2'b00; end end else if (rising_edge_WAIT_OTP_out) begin WAIT_OTP_in <= 1'b0; Protect = 1'b1; OTPOverlay = 1'b1; end end WAIT_STATE_2: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF) ) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end end else if (rising_edge_OTP_out) begin RY_zd <= 1'b1; OTP_in <= 1'b0; end end DEF_OVER: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF) ) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end end else if (rising_edge_DEF_OTP_out) begin DEF_OTP_in <= 1'b0; if (!SetDefault) begin SetDefault = 1'b1; OTPDefault = Overlaid; RY_zd <= 1'b1; Status[6:5] = 2'b11; Status[0] = 1'b0; end else begin RY_zd <= 1'b1; Status[6:5] = 2'b11; Status[0] = 1'b1; end end end DEF_REM: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 16'hFF) ) begin STAT_ACT <= 1'b0; RSTSTART <= 1'b1; RSTSTART <= #1 1'b0; RY_zd <= 1'b0; Status[6:5] = 2'b00; Status[1 : 0] = 2'b00; end end else if (rising_edge_DEF_OTP_out) begin DEF_OTP_in <= 1'b0; if (!SetDefault) begin SetDefault = 1'b1; OTPDefault = Removed; RY_zd <= 1'b1; Status[6:5] = 2'b11; Status[0] = 1'b0; end else begin RY_zd <= 1'b1; Status[6:5] = 2'b11; Status[0] = 1'b1; end end end endcase if (RENeg || CENeg) DOut_zd <= 8'bZ; end //Program Operation always @(posedge PROG_in) begin:ProgTime #(prog_time) PROG_out <= 1'b1; end always @(negedge PROG_in) begin disable ProgTime; #1 PROG_out <= 1'b0; end //Program1 Operation always @(posedge PROG1_in) begin:ProgTime1 PROG1_out <= 1'b0; #(prog_time) PROG1_out <= 1'b1; end always @(negedge PROG1_in) begin disable ProgTime1; #1 PROG1_out <= 1'b0; end //Program2 Operation always @(posedge PROG2_in) begin:ProgTime2 #(prog_time) PROG2_out = 1'b1; end always @(negedge PROG2_in) begin disable ProgTime2; #1 PROG2_out = 1'b0; end //OTPDefault Program Operation always @(posedge DEF_OTP_in) begin:OTPProgTime #(tdevice_OTPD + WER_01) DEF_OTP_out = 1'b1; end always @(negedge DEF_OTP_in) begin disable OTPProgTime; #1 DEF_OTP_out = 1'b0; end //Wait OTP protection out always @(posedge WAIT_OTP_in) begin:WaitOTPProt #(WER_01) WAIT_OTP_out = 1'b1; end always @(negedge WAIT_OTP_in) begin disable WaitOTPProt; #1 WAIT_OTP_out = 1'b0; end //Wait OTP out always @(posedge OTP_in) begin:WaitOTP #(WER_01 + tdevice_OTP) OTP_out = 1'b1; end always @(negedge OTP_in) begin disable WaitOTP; #1 OTP_out = 1'b0; end //Page read always @(posedge TR_in) begin:PageRead TR_out = 1'b0; #(tdevice_TR) TR_out = 1'b1; end always @(negedge TR_in) begin disable PageRead; #1 TR_out = 1'b0; end //Partial read always @(posedge TRP_in) begin:PartialRead TRP_out = 1'b0; #(tdevice_TRP) TRP_out = 1'b1; end always @(negedge TRP_in) begin disable PartialRead; #1 TRP_out = 1'b0; end //Pipeline read always @(posedge TPT_in) begin:PipelineRead TPT_out = 1'b0; #(tdevice_TPT) TPT_out = 1'b1; end always @(negedge TPT_in) begin disable PipelineRead; #1 TPT_out = 1'b0; end //DBSYTime always @(posedge DBSY_in) begin:DBSYTime DBSY_out = 1'b0; #(tdevice_DBSY+WER_01) DBSY_out = 1'b1; end always @(negedge DBSY_in) begin disable DBSYTime; #1 DBSY_out = 1'b0; end //DBSY1Time always @(posedge DBSY1_in) begin:DBSY1Time DBSY1_out = 1'b0; #(tdevice_DBSY+WER_01) DBSY1_out = 1'b1; end always @(negedge DBSY1_in) begin disable DBSY1Time; #1 DBSY1_out = 1'b0; end //SuspendTime always @(ERS_SUSP_in) begin:SuspendTime if (ERS_SUSP_in) begin ERS_SUSP_out <= 1'b0; #(tdevice_SUSP) ERS_SUSP_out <= 1'b1; end else ERS_SUSP_out <= 1'b0; end //PreSuspendTime always @(ERS_PRESUS_in) begin:PreSuspendTime if (ERS_PRESUS_in) begin ERS_PRESUS_out <= 1'b0; #(tdevice_PRESUS + WER_01) ERS_PRESUS_out <= 1'b1; end else ERS_PRESUS_out <= 1'b0; end //PRETime always @(posedge TPRE_in) begin:PRETime TPRE_out = 1'b0; #(tdevice_TPRE) TPRE_out = 1'b1; end always @(negedge TPRE_in) begin disable PRETime; #1 TPRE_out = 1'b0; end // determining rising/falling edges of signals always @(posedge PoweredUp) begin rising_edge_PoweredUp <= 1'b1; #1 rising_edge_PoweredUp <= 1'b0; end always @(posedge reseted) begin rising_edge_reseted = 1'b1; #1 rising_edge_reseted = 1'b0; end always @(posedge RSTSTART) begin rising_edge_RSTSTART = 1'b1; #1 rising_edge_RSTSTART = 1'b0; end always @(posedge RSTDONE) begin rising_edge_RSTDONE = 1'b1; #1 rising_edge_RSTDONE = 1'b0; end always @(negedge write) begin falling_edge_write <= 1'b1; #1 falling_edge_write <= 1'b0; end always @(negedge falling_edge_write) begin flagWRITE = 1'b1; end always @(posedge ESTART) begin rising_edge_ESTART = 1'b1; #1 rising_edge_ESTART = 1'b0; end always @(posedge ESUSP) begin rising_edge_ESUSP = 1'b1; #1 rising_edge_ESUSP = 1'b0; end always @(posedge ERES) begin rising_edge_ERES = 1'b1; #1 rising_edge_ERES = 1'b0; end always @(posedge EDONE) begin rising_edge_EDONE = 1'b1; #1 rising_edge_EDONE = 1'b0; end always @(posedge TR_out) begin rising_edge_TR_out = 1'b1; #1 rising_edge_TR_out = 1'b0; end always @(posedge TRP_out) begin rising_edge_TRP_out = 1'b1; #1 rising_edge_TRP_out = 1'b0; end always @(posedge TPT_out) begin rising_edge_TPT_out = 1'b1; #1 rising_edge_TPT_out = 1'b0; end always @(posedge TPRE_out) begin rising_edge_TPRE_out = 1'b1; #1 rising_edge_TPRE_out = 1'b0; end always @(posedge PROG_out) begin rising_edge_PROG_out = 1'b1; #1 rising_edge_PROG_out = 1'b0; end always @(negedge rising_edge_PROG_out) begin flagPROG = 1'b1; end always @(posedge PROG1_out) begin rising_edge_PROG1_out = 1'b1; #1 rising_edge_PROG1_out = 1'b0; end always @(negedge rising_edge_PROG1_out) begin flagPROG1 = 1'b1; end always @(posedge PROG2_out) begin rising_edge_PROG2_out = 1'b1; #1 rising_edge_PROG2_out = 1'b0; end always @(posedge DBSY_out) begin rising_edge_DBSY_out = 1'b1; #1 rising_edge_DBSY_out = 1'b0; end always @(posedge DBSY1_out) begin rising_edge_DBSY1_out = 1'b1; #1 rising_edge_DBSY1_out = 1'b0; end always @(posedge ERS_SUSP_out) begin rising_edge_ERS_SUSP_out = 1'b1; #1 rising_edge_ERS_SUSP_out = 1'b0; end always @(posedge ERS_PRESUS_out) begin rising_edge_ERS_PRESUS_out = 1'b1; #1 rising_edge_ERS_PRESUS_out = 1'b0; end always @(posedge OTP_out) begin rising_edge_OTP_out = 1'b1; #1 rising_edge_OTP_out = 1'b0; end always @(posedge WAIT_OTP_out) begin rising_edge_WAIT_OTP_out = 1'b1; #1 rising_edge_WAIT_OTP_out = 1'b0; end always @(posedge DEF_OTP_out) begin rising_edge_DEF_OTP_out = 1'b1; #1 rising_edge_DEF_OTP_out = 1'b0; end always @(posedge RENeg) begin rising_edge_RENeg = 1'b1; #1 rising_edge_RENeg = 1'b0; end always @(posedge CENeg) begin rising_edge_CENeg = 1'b1; #1 rising_edge_CENeg = 1'b0; end task getSegment (input integer paddress, output integer j); begin for (i = 0; i<= SegmentNum; i = i+1) begin if ((paddress >= ssa[i]) && (paddress <= sea[i])) j = i; end end endtask task Read_Data (input Page, inout Addr); integer Page; integer Addr; begin if (Mem[Page*(PageSize+1)+ Addr] != -1) DOut_zd <= Mem[Page*(PageSize+1)+ Addr]; else DOut_zd <= 8'bX; if (!PPGR_ACT) begin if (Addr != PageSize) Addr = Addr+1; end else begin getSegment(Addr, Segment); if (Segment < 4) begin if (Addr < sea[Segment]) Addr = Addr+1; else if (Addr == sea[Segment]) begin Segment = Segment + 4; Addr = ssa[Segment]; end end else begin if (Addr < sea[Segment]) Addr = Addr+1; end end end endtask task Read_OTP (input Page, inout Addr); integer Page; integer Addr; begin if (Page <= 7) begin if (OTP_Area[Page*(PageSize+1) + Addr] != -1) DOut_zd <= OTP_Area[Page*(PageSize+1) + Addr]; else DOut_zd <= 8'bX; end else DOut_zd <= 8'hFF; if (!PPGR_ACT) begin if (Addr != PageSize) Addr = Addr+1; end else begin getSegment(Addr, Segment); if (Segment < 4) begin if (Addr < sea[Segment]) Addr = Addr+1; else if (Addr == sea[Segment]) begin Segment = Segment + 4; Addr = ssa[Segment]; end end else begin if (Addr < sea[Segment]) Addr = Addr + 1; end end end endtask task EndProgramming; begin PRG_ACT <= 1'b0; Status[5] = 1'b1; PROG_in <= 1'b0; PROG1_in <= 1'b0; PROG2_in <= 1'b0; Status[1:0] = 2'b00; if ((WPNeg != 1'b0) && !WriteProtect) begin if (OTPOverlay && (ProgBlck == 0)) begin if (ProgPage <= 7) begin for (j=0; j<=PageSize; j=j+1) begin getSegment(j, pom_seg); if (ProtStatus[ProgPage] && WrBuffData[j] != -1 && OTPProgramedFlag [ProgPage*(SegmentNum+1)+pom_seg]==1'b0) OTP_Area[ProgPage*(PageSize+1)+j] = WrBuffData[j]; end for (j=0; j<=SegmentNum; j=j+1) OTPProgramedFlag[ProgPage*(SegmentNum+1)+j] = CashSegForProg[j]; end else Status[0] = 1'b1; end else begin for (j=0; j<=PageSize; j=j+1) begin getSegment(j,pom_seg); if (ProgramedFlag[ProgPage*(SegmentNum+1) +pom_seg]==1'b0 && (WrBuffData[j] != -1)) Mem[ProgPage*(PageSize+1)+j] = WrBuffData[j]; end for (j=0; j<=SegmentNum; j=j+1) ProgramedFlag[ProgPage*(SegmentNum+1)+j] = CashSegForProg[j]; end end end endtask task getAddress (input reg[15:0] Column); begin if (Column[MainAreaAddBit] == 1'b0) begin TmpSegm = Column[HAddBitSeg : HAddBitSeg-1]; AddrWithinPage = Column; end else begin TmpSegm = MainSize/SegmentSize + Column[HAddBitSpareSeg :HAddBitSpareSeg-1]; AddrWithinPage = MainSize + Column[HAddBitSpareSeg : 0]; end end endtask task getPage (input reg[23:0] Row); begin PageWithinBlock = Row[HAddBitPag-MainAreaAddBit-1 : 0]; TmpBlck = Row[HAddBitBl-MainAreaAddBit-1:HAddBitPag-MainAreaAddBit]; TmpPage = TmpBlck*PageNumInBl + PageWithinBlock; end endtask // extracting time parameter from sdf reg BuffInR; wire BuffOutR; BUFFER BUFR (BuffOutR , BuffInR); initial begin BuffInR = 1'b1; end always @(posedge BuffOutR) begin WER_01 = $time; end endmodule module BUFFER (OUT,IN); input IN; output OUT; buf ( OUT, IN); endmodule