//////////////////////////////////////////////////////////////////////////// // File name : s30ms04gr01.sv //////////////////////////////////////////////////////////////////////////// // 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: s30ms04gr01 // // Description: 4Gb (256Mx16) NAND interface Flash Memory // //////////////////////////////////////////////////////////////////////////// // Known Bugs: // //////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////// // MODULE DECLARATION // //////////////////////////////////////////////////////////////////////////// `timescale 1 ns/1 ns module s30ms04gr01 ( IO15 , IO14 , IO13 , IO12 , IO11 , IO10 , IO9 , IO8 , IO7 , IO6 , IO5 , IO4 , IO3 , IO2 , IO1 , IO0 , CLE , ALE , CENeg , RENeg , WENeg , WPNeg , RY ); //////////////////////////////////////////////////////////////////////// // Port / Part Pin Declarations //////////////////////////////////////////////////////////////////////// inout IO15 ; inout IO14 ; inout IO13 ; inout IO12 ; inout IO11 ; inout IO10 ; inout IO9 ; inout IO8 ; 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 ; parameter mem1_file_name = "none";//"s30ms04gr01_1.mem" parameter mem2_file_name = "none";//"s30ms04gr01_2.mem" parameter OTP1_file_name = "none";//"s30ms04gr01_OTP_1.mem" parameter OTP2_file_name = "none";//"s30ms04gr01_OTP_2.mem" parameter protOTP1_file_name = "none";//"s30ms04gr01_OTPprot_1.mem" parameter protOTP2_file_name = "none";//"s30ms04gr01_OTPprot_2.mem" parameter UserPreload = 1'b0; parameter TimingModel = "DefaultTimingModel"; s30ms02gr01 #(mem1_file_name,OTP1_file_name,protOTP1_file_name, UserPreload,TimingModel) Flash_1 ( .IO15(IO15) , .IO14(IO14) , .IO13(IO13) , .IO12(IO12) , .IO11(IO11) , .IO10(IO10) , .IO9(IO9) , .IO8(IO8) , .IO7(IO7) , .IO6(IO6) , .IO5(IO5) , .IO4(IO4) , .IO3(IO3) , .IO2(IO2) , .IO1(IO1) , .IO0(IO0) , .CLE(CLE) , .ALE(ALE) , .CENeg(CENeg) , .RENeg(RENeg) , .WENeg(WENeg) , .WPNeg(WPNeg) , .INTAMAX(1'b0), .RY(RY) ); s30ms02gr01 #(mem2_file_name,OTP2_file_name,protOTP2_file_name, UserPreload,TimingModel) Flash_2 ( .IO15(IO15) , .IO14(IO14) , .IO13(IO13) , .IO12(IO12) , .IO11(IO11) , .IO10(IO10) , .IO9(IO9) , .IO8(IO8) , .IO7(IO7) , .IO6(IO6) , .IO5(IO5) , .IO4(IO4) , .IO3(IO3) , .IO2(IO2) , .IO1(IO1) , .IO0(IO0) , .CLE(CLE) , .ALE(ALE) , .CENeg(CENeg) , .RENeg(RENeg) , .WENeg(WENeg) , .WPNeg(WPNeg) , .INTAMAX(1'b1), .RY(RY) ); endmodule ////////////////////////////////////////////////////////////////////////////// //Flash component ////////////////////////////////////////////////////////////////////////////// module s30ms02gr01 ( IO15 , IO14 , IO13 , IO12 , IO11 , IO10 , IO9 , IO8 , IO7 , IO6 , IO5 , IO4 , IO3 , IO2 , IO1 , IO0 , CLE , ALE , CENeg , RENeg , WENeg , WPNeg , INTAMAX , RY ); //////////////////////////////////////////////////////////////////////// // Port / Part Pin Declarations //////////////////////////////////////////////////////////////////////// inout IO15 ; inout IO14 ; inout IO13 ; inout IO12 ; inout IO11 ; inout IO10 ; inout IO9 ; inout IO8 ; 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 ; input INTAMAX ; output RY ; // interconnect path delay signals wire IO15_ipd ; wire IO14_ipd ; wire IO13_ipd ; wire IO12_ipd ; wire IO11_ipd ; wire IO10_ipd ; wire IO9_ipd ; wire IO8_ipd ; 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 [15 : 0 ] DIn; assign DIn = {IO15_ipd, IO14_ipd, IO13_ipd, IO12_ipd, IO11_ipd, IO10_ipd, IO9_ipd, IO8_ipd, IO7_ipd, IO6_ipd, IO5_ipd, IO4_ipd, IO3_ipd, IO2_ipd, IO1_ipd, IO0_ipd }; wire [15 : 0 ] DOut; assign DOut = {IO15, IO14, IO13, IO12, IO11, IO10, IO9, IO8, 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 [15 : 0] DOut_zd; wire IO15_zd ; wire IO14_zd ; wire IO13_zd ; wire IO12_zd ; wire IO11_zd ; wire IO10_zd ; wire IO9_zd ; wire IO8_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 {IO15_zd, IO14_zd, IO13_zd, IO12_zd, IO11_zd, IO10_zd, IO9_zd, IO8_zd, 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";//"s30ms02gr01.mem" parameter OTP_file_name = "none";//"s30ms02gr01_OTP.mem" parameter protOTP_file_name = "none";//"s30ms02gr01_OTPprot.mem" parameter UserPreload = 1'b0; parameter TimingModel = "DefaultTimingModel"; parameter PartID = "s30ms02gr01"; parameter MaxData = 16'hFFFF; parameter BlockNum = 2047; parameter BlockSize = 63; parameter PageNum = 17'h1FFFF; parameter PageNumInBl = 64; parameter PageSize = 1055; parameter SegmentNum = 7; // 8 segments within page parameter SegmentSize = 256; parameter SperSegSize = 8; parameter SpareSize = 32; parameter MainSize = 1024; parameter OTPPageNum = 7; parameter MainAreaAddBit = 10; parameter HAddBitPag = 16; parameter HAddBitBl = 27; parameter HAddBitSpareSeg = 4; parameter HAddBitSeg = 9; // 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 = 7; parameter preload_data_width = 4; integer memory_read_data; // 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; integer sel_device = 0; integer param = 1; 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 [15: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 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[15:0] Status = 16'h00C0; 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 [5:0] prev_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 (IO15_ipd , IO15 ); buf (IO14_ipd , IO14 ); buf (IO13_ipd , IO13 ); buf (IO12_ipd , IO12 ); buf (IO11_ipd , IO11 ); buf (IO10_ipd , IO10 ); buf (IO9_ipd , IO9 ); buf (IO8_ipd , IO8 ); 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 (IO15 , IO15_zd , 1); nmos (IO14 , IO14_zd , 1); nmos (IO13 , IO13_zd , 1); nmos (IO12 , IO12_zd , 1); nmos (IO11 , IO11_zd , 1); nmos (IO10 , IO10_zd , 1); nmos (IO9 , IO9_zd , 1); nmos (IO8 , IO8_zd , 1); 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; memory_features memory_features_i0(); 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$CENeg$IO8 = (0); specparam PATHPULSE$CENeg$IO9 = (0); specparam PATHPULSE$CENeg$IO10 = (0); specparam PATHPULSE$CENeg$IO11 = (0); specparam PATHPULSE$CENeg$IO12 = (0); specparam PATHPULSE$CENeg$IO13 = (0); specparam PATHPULSE$CENeg$IO14 = (0); specparam PATHPULSE$CENeg$IO15 = (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); specparam PATHPULSE$RENeg$IO8 = (0); specparam PATHPULSE$RENeg$IO9 = (0); specparam PATHPULSE$RENeg$IO10 = (0); specparam PATHPULSE$RENeg$IO11 = (0); specparam PATHPULSE$RENeg$IO12 = (0); specparam PATHPULSE$RENeg$IO13 = (0); specparam PATHPULSE$RENeg$IO14 = (0); specparam PATHPULSE$RENeg$IO15 = (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; ( CENeg => IO8 ) = tpd_CENeg_IO0; ( CENeg => IO9 ) = tpd_CENeg_IO0; ( CENeg => IO10 ) = tpd_CENeg_IO0; ( CENeg => IO11 ) = tpd_CENeg_IO0; ( CENeg => IO12 ) = tpd_CENeg_IO0; ( CENeg => IO13 ) = tpd_CENeg_IO0; ( CENeg => IO14 ) = tpd_CENeg_IO0; ( CENeg => IO15 ) = 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; ( RENeg => IO8 ) = tpd_RENeg_IO0; ( RENeg => IO9 ) = tpd_RENeg_IO0; ( RENeg => IO10 ) = tpd_RENeg_IO0; ( RENeg => IO11 ) = tpd_RENeg_IO0; ( RENeg => IO12 ) = tpd_RENeg_IO0; ( RENeg => IO13 ) = tpd_RENeg_IO0; ( RENeg => IO14 ) = tpd_RENeg_IO0; ( RENeg => IO15 ) = 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); $setup ( IO8 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO9 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO10 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO11 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO12 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO13 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO14 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO15 ,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); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO8 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO9 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO10 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO11 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO12 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO13 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO14 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO15 ,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 / S30MS02GR01 DEVICE SPECIFIC ////////////////////////////////////////////////////////////////// IDArray[4'd0] = 8'h01; IDArray[4'd1] = 8'hCC; 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]; // memory region implicitly initialized memory_features_i0.initialize_w(); 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'h100; ssa[2] =12'h200; ssa[3] =12'h300; ssa[4] =12'h400; ssa[5] =12'h408; ssa[6] =12'h410; ssa[7] =12'h418; //page segment end address offset sea[0] =12'h0FF; sea[1] =12'h1FF; sea[2] =12'h2FF; sea[3] =12'h3FF; sea[4] =12'h407; sea[5] =12'h40F; sea[6] =12'h417; sea[7] =12'h41F; if (UserPreload && !(mem_file_name == "none")) begin // s30ms02gr01 memory preload file // / - comment // @aaaaaaaa - stands for page address and address within // first 1056 bytes of a page // dddd - is DWord to be written at Mem(page)(offset++) // page is div 1056 // offset is mod 1056 // 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 = 16'h00FF; 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 memory_features_i0.write_mem_w (scanf_address, scanf_data); ProgramedFlag[scanf_address / SegmentSize] = 1'b1; end else $display("Memory address out of range."); scanf_address++; 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<= 7; 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 = 16'b0000000001100100; 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 if (~INTAMAX) begin sel_device = 1; current_state <= BUFF_TR; end else begin sel_device = 0; current_state <= IDLE; end reseted <= 1'b1; 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 && sel_device) 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) && sel_device) 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) && sel_device) if (!ESUSP_ACT) next_state <= PREL_OTP; else next_state <= IDLE; else begin next_state <= IDLE; end prev_state <= IDLE; end end UNKNOWN: begin if (falling_edge_write && CLE && !ALE && (Data==16'hFF) && sel_device) 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) if (AddrCom[param] == INTAMAX) next_state <= RD_WCMD; else next_state <= prev_state; else if (CLE && (Data == 16'h30)) begin if (INTAMAX == 1'b1) next_state <= prev_state; else if (ESUSP_ACT && (TmpBlck == ErsBlck)) next_state <= IDLE; else next_state <= BUFF_TR; end else if (CLE && (Data == 16'h31)) begin if (INTAMAX == 1'b1) next_state <= prev_state; else if (ESUSP_ACT && (TmpBlck == ErsBlck)) next_state <= IDLE; else next_state <= BUFF_TR; end else if (CLE && (Data == 16'h32)) begin if (INTAMAX == 1'b1) next_state <= prev_state; else if (!ESUSP_ACT) next_state <= BUFF_TR; else next_state <= IDLE; end else if (CLE && (Data == 16'h33)) begin if (INTAMAX == 1'b1) next_state <= prev_state; else if (!ESUSP_ACT) next_state <= BUFF_TR; else next_state <= IDLE; end else if (CLE && (Data == 16'h35)) begin if (INTAMAX == 1'b1) next_state <= prev_state; else 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 && sel_device) 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 && sel_device) next_state <= CAC_PREL; else if (CLE && !ALE && (Data == 16'hB0) && !PGD_ACT && !PIPR_ACT && sel_device) begin if (!ESUSP_ACT) next_state <= PREL_OTP; else next_state <= IDLE; end else begin next_state <= IDLE; end prev_state <= RD; 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) && sel_device) 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) && sel_device) next_state <= IDLE; else if (CLE && !ALE && (Data==8'hB0) && sel_device) if (!ESUSP_ACT) next_state <= PREL_OTP; else next_state <= IDLE; else begin next_state <= IDLE; end prev_state <= ID; 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) if (AddrCom[param] == INTAMAX) next_state <= DATA_PRG; else next_state <= prev_state; else if (!ALE && !CLE) if (INTAMAX == 1'b1) next_state <= prev_state; else next_state <= DATA_PRG; else if (CLE && (Data == 8'h10)) begin if ((INTAMAX == 1'b1) && ~Protect) next_state <= prev_state; else 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 (INTAMAX == 1'b1) next_state <= prev_state; else 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) && sel_device) 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) && sel_device) 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) if (AddrCom[param] == INTAMAX) next_state <= A3_ERS; else next_state <= prev_state; else if (INTAMAX == 1'b1) next_state <= prev_state; 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 && sel_device) 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 && sel_device) 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 <= INTAMAX; 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) && sel_device) STAT_ACT <= 1'b1; else if (CLE && !ALE && (Data == 16'h00) && sel_device) STAT_ACT <= 1'b0; else if (CLE && !ALE && (Data == 16'h90) && sel_device) STAT_ACT <= 1'b0; else if (CLE && !ALE && (Data == 16'hB0) && sel_device) STAT_ACT <= 1'b0; else if (CLE && !ALE && (Data == 16'h80) && sel_device) begin STAT_ACT <= 1'b0; if (WPNeg) WriteProtect = 1'b0; else WriteProtect = 1'b1; end else if (CLE && !ALE && (Data==16'h60) && sel_device) begin STAT_ACT <= 1'b0; if (WPNeg) WriteProtect = 1'b0; else WriteProtect = 1'b1; end else if (CLE && !ALE && (Data == 16'hFF) && !ESUSP_ACT && sel_device) 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) && sel_device) 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) && sel_device) 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 && sel_device) 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 && sel_device) 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 && sel_device) 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 && sel_device) 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); if (AddrCom[param] == INTAMAX) sel_device = 1; else sel_device = 0; end else if (CLE && (Data == 16'h30) && ((ESUSP_ACT && (TmpBlck != ErsBlck)) || !ESUSP_ACT)) begin if (~INTAMAX) begin sel_device = 1; 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 sel_device = 0; end else if (CLE && (Data == 16'h31) && ((ESUSP_ACT && (TmpBlck != ErsBlck)) || !ESUSP_ACT)) begin if (~INTAMAX) begin sel_device = 1; 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 sel_device = 0; end else if (CLE && (Data == 16'h32) && !ESUSP_ACT) begin if (~INTAMAX) begin sel_device = 1; 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 sel_device = 0; end else if (CLE && (Data == 16'h33) && !ESUSP_ACT) begin if (~INTAMAX) begin sel_device = 1; 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 sel_device = 0; end else if (CLE && (Data == 16'h35) && ((ESUSP_ACT && (TmpBlck != ErsBlck)) || !ESUSP_ACT)) begin if (~INTAMAX) begin sel_device = 1; 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 sel_device = 0; end else if (CLE && (Data == 16'hFF) && !ESUSP_ACT && sel_device) 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 && sel_device) 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 && sel_device) 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) && sel_device) 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'hFFFF; end else for (i=0; i<=PageSize; i=i+1) begin memory_features_i0.read_mem_w( memory_read_data, RdPage * (PageSize + 1) + i ); PDBuffer[i] = memory_read_data; end 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) && sel_device) begin STAT_ACT <= 1'b1; end else if (CLE && !ALE && (Data == 16'h90) && !PGD_ACT && !PIPR_ACT && sel_device) 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 && sel_device) 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 && sel_device) STAT_ACT <= 1'b0; else if (CLE && !ALE && (Data == 16'hB0) && !PGD_ACT && !PIPR_ACT && sel_device) 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 && sel_device) 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 && sel_device) 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) && sel_device) 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 <= 16'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 && sel_device) 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 && sel_device) 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 && sel_device) 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 && sel_device) 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; if (INTAMAX == AddrCom[param]) sel_device = 1; else sel_device = 0; 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 if (~INTAMAX) begin sel_device = 1; 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 sel_device = 0; end else if (CLE && (Data == 16'h10) && ((ESUSP_ACT && (WrBlck != ErsBlck)) || !ESUSP_ACT) ) begin if (~INTAMAX) begin sel_device = 1; 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 sel_device = 0; end else if (CLE && !ALE && !PGD_ACT && (Data == 16'h15) && !ESUSP_ACT) begin if (~INTAMAX) begin sel_device = 1; if (!PRG_ACT) DBSY_in <= 1'b1; RY_zd <= 1'b0; Status[6] = 1'b0; firstFlag = 1'b1; end else sel_device = 0; end else if (CLE && (Data==16'hFF) && !ESUSP_ACT && sel_device) 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 && sel_device) 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)) memory_features_i0.write_mem_w( 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 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)) memory_features_i0.write_mem_w( 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) 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)) memory_features_i0.write_mem_w( 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 && sel_device) 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) memory_features_i0.write_mem_w( 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) memory_features_i0.write_mem_w( 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) && sel_device) 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 && sel_device) 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 && sel_device) 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) begin RowAddr[23 : 16] = AddrCom; if (INTAMAX == AddrCom[param]) sel_device = 1; else sel_device = 0; end else if (CLE && (Data == 8'hFF) && !ESUSP_ACT && sel_device) 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 (INTAMAX == 1'b1) sel_device = 0; 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 memory_features_i0.corrupt_mem_w( i * (PageSize + 1), i * (PageSize + 1) + PageSize ); 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 sel_device = 1; end end end A3_ERS: begin if (falling_edge_write && flagWRITE) begin flagWRITE = 1'b0; if (CLE && !ALE && (Data == 8'hFF) && !ESUSP_ACT && sel_device) 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 == 16'h00FF) 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 memory_features_i0.corrupt_mem_w( i * (PageSize + 1), i * (PageSize + 1) + PageSize ); 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 memory_features_i0.erase_mem_w( i * (PageSize + 1), i * (PageSize + 1) + PageSize ); 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; 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 && sel_device) 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 || (sel_device == 0)) DOut_zd <= 16'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; integer memory_read_data_internal; begin memory_features_i0.read_mem_w( memory_read_data_internal, Page * (PageSize+1) + Addr); if (memory_read_data_internal != -1) DOut_zd <= memory_read_data_internal; else DOut_zd <= 16'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 <= 16'bX; end else DOut_zd <= 16'hFFFF; 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)) memory_features_i0.write_mem_w( 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 module memory_features(); // ------------------------------------------------------------------------- // ---------------- start of memory management section --------------- // ------------------------------------------------------------------------- // memory partitioning parameters parameter list_num = 2048; parameter list_size = 20'h10800; // memory initial data value parameter MaxData = 16'hFFFF; // memory management routines // handle dynamic memory allocation // abstract memory region model class linked_list_c; // memory element model reg[31:0] key_address; integer val_data; // organize memory storage elements into a linked list linked_list_c successor; function new( integer address_a, integer data_a); begin key_address = address_a; val_data = data_a; successor = null; end endfunction endclass // partition memory region for faster access linked_list_c linked_list [list_num]; // class methods internal communication pool linked_list_c found; linked_list_c prev; linked_list_c sub_linked_list; linked_list_c sub_linked_list_last; // low-level routines class low_level_interface_c; // assure proper initialization function new; integer new_iter; begin // initialize linked list handles for(new_iter=0; new_iter < list_num; new_iter = new_iter + 1) linked_list[new_iter] = null; found = null; prev = null; sub_linked_list = null; sub_linked_list_last = null; end endfunction // Iterate through linked listed comapring key values // Stop when key value greater or equal task position_list( integer address_a, linked_list_c root); begin found = root; prev = null; while ((found != null) && (found.key_address < address_a)) begin prev = found; found = found.successor; end end endtask // Add new element to a linked list task insert_list( integer address_a, integer data_a, integer list_id); linked_list_c new_element; begin this.position_list( address_a, linked_list[list_id]); // Insert at list tail if (found == null) begin prev.successor = new(address_a, data_a); end else begin // Element exists, update memory data value if (found.key_address == address_a) begin found.val_data = data_a; end else begin // No element found, allocate and link new_element = new(address_a, data_a); new_element.successor = found; // Possible root position if (prev != null) begin prev.successor = new_element; end else begin linked_list[list_id] = new_element; end end end end endtask // Remove element from a linked list task remove_list( integer address_a, integer list_id); begin this.position_list( address_a, linked_list[list_id]); if (found != null) // Key value match if (found.key_address == address_a) begin // Handle root position removal if (prev != null) prev.successor = found.successor; else linked_list[list_id] = found.successor; // garbage collector found = null; end end endtask // Remove range of elements from a linked list // Higher performance than one-by-one removal task remove_list_range( integer address_low, integer address_high, integer list_id); linked_list_c iter; linked_list_c prev_remove; linked_list_c link_element; begin iter = linked_list[list_id]; prev_remove = null; // Find first linked list element belonging to // a specified address range [address_low, address_high] while ((iter != null) && !( (iter.key_address >= address_low) && (iter.key_address <= address_high))) begin prev_remove = iter; iter = iter.successor; end // Continue until address_high reached // Deallocate linked list elements pointed by iterator if (iter != null) begin while ((iter != null) && (iter.key_address >= address_low) && (iter.key_address <= address_high)) begin link_element = iter.successor; //garbage collector iter.successor = null; iter = link_element; end // Handle possible root value change if ( prev_remove != null ) prev_remove.successor = link_element; else linked_list[list_id] = link_element; end end endtask // Create side linked list modelling corrupted memory area task create_list_range( integer address_low, integer address_high); linked_list_c new_element; linked_list_c prev_create; integer create_list_range_iter; begin sub_linked_list = new(address_low, -1); prev_create = sub_linked_list; // Linked list representing memory region : // [address_low, address_high], memory data value corrupted // Heightens corrupt and erase operation performance for( create_list_range_iter = (address_low + 1); create_list_range_iter <= address_high; create_list_range_iter = create_list_range_iter + 1) begin new_element = new(create_list_range_iter, -1); prev_create.successor = new_element; prev_create = new_element; end prev_create.successor = null; sub_linked_list_last = prev_create; end endtask // Merge corrupted with memory area task insert_list_range( integer list_id); integer key; begin if (linked_list[list_id] != null) begin key = sub_linked_list.key_address; // Insert side created corrupted memory region // into corresponding linked list this.position_list(key, linked_list[list_id]); if (found == null) prev.successor = sub_linked_list; else begin sub_linked_list_last.successor = found; if (prev != null) prev.successor = sub_linked_list; else linked_list[list_id] = sub_linked_list; end end else linked_list[list_id] = sub_linked_list; // do not prevent garabge collection when possible sub_linked_list = null; sub_linked_list_last = null; end endtask endclass // higher-level routines // provided memory RW operation class interface class rw_interface_c; low_level_interface_c low_level_interface; // assure proper initialization function new; integer new_iter; begin // allocate low level interface object low_level_interface = new; end endfunction task read_mem( inout integer data_a, input integer address_a); integer mem_data; integer list_id; begin // Higher performance, segment paritioning list_id = address_a / list_size; if (linked_list[list_id] == null) // Not allocated, not written, initial value mem_data = MaxData; else begin low_level_interface.position_list( address_a, linked_list[list_id]); if (found != null) begin if (found.key_address == address_a) // Allocated, val_data stored mem_data = found.val_data; else // Not allocated, not written, initial value mem_data = MaxData; end else begin // Not allocated, not written, initial value mem_data = MaxData; end end data_a = mem_data; end endtask // Memory WRITE operation performed above dynamically allocated space task write_mem( input integer address_a, input integer data_a); integer list_id; begin // Higher performance, segment paritioning list_id = address_a / list_size; if (data_a !== MaxData) begin // Handle possible root value update if (linked_list[list_id] !== null) begin low_level_interface.insert_list( address_a, data_a, list_id); end else begin linked_list[list_id] = new(address_a, data_a); end end else begin // Deallocate if initial value written // No linked list, NOP, initial value implicit if (linked_list[list_id] !== null) begin low_level_interface.remove_list( address_a, list_id); end end end endtask // Address range to be corrupted task corrupt_mem( input integer address_low, input integer address_high); integer list_id; begin list_id = address_low / list_size; if (linked_list[list_id] != null) low_level_interface.remove_list_range( address_low, address_high, list_id); low_level_interface.create_list_range( address_low, address_high ); low_level_interface.insert_list_range( list_id ); end endtask // Address range to be erased task erase_mem( input integer address_low, input integer address_high); integer list_id; begin list_id = address_low / list_size; low_level_interface.remove_list_range( address_low, address_high, list_id ); end endtask endclass // object declaration holding memory management model rw_interface_c rw_interface; //interface towards higher hierarchy instances routine calls //wrapped from within the memory_features module //low-level routine access forbidden task initialize_w; begin rw_interface = new; end endtask task read_mem_w( inout integer data_a, input integer address_a); begin rw_interface.read_mem(data_a, address_a); end endtask task write_mem_w( input integer address_a, input integer data_a); begin rw_interface.write_mem(address_a, data_a); end endtask task erase_mem_w( input integer address_low, input integer address_high); begin rw_interface.erase_mem(address_low, address_high); end endtask task corrupt_mem_w( input integer address_low, input integer address_high); begin rw_interface.corrupt_mem(address_low, address_high); end endtask // ------------------------------------------------------------------------- // ---------------- the end of memory management section ------------- // ------------------------------------------------------------------------- endmodule