////////////////////////////////////////////////////////////////////////////// // File name : s30ml512p00.sv ////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2007 Free Model Foundry; http://www.FreeModelFoundry.com // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // MODIFICATION HISTORY: // // version: | author: | mod date: | changes made: // V1.0 I.Milutinovic 07 Feb 03 Initial Release // V1.1 I.Milutinovic 07 Feb 07 Removed procedures for modeling // corrupted memory area due to // increasing simulation speed // ////////////////////////////////////////////////////////////////////////////// // PART DESCRIPTION: // // Library: FLASH // Technology: FLASH MEMORY // Part: S30ML512P00 // // Description: 512 Megabit CMOS 3.0-Volt ORNAND Flash Memory Device // with MirrorBit Technology and NAND interface // ////////////////////////////////////////////////////////////////////////////// // Known Bugs: // ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // TOP MODULE DECLARATION // ////////////////////////////////////////////////////////////////////////////// `timescale 1 ns/1 ns module s30ml512p00 ( IO7 , IO6 , IO5 , IO4 , IO3 , IO2 , IO1 , IO0 , CLE , ALE , CENeg , RENeg , WENeg , WPNeg , RY , FPNeg , PRE ); //////////////////////////////////////////////////////////////////////// // Port / Part Pin Declarations //////////////////////////////////////////////////////////////////////// inout IO7 ; inout IO6 ; inout IO5 ; inout IO4 ; inout IO3 ; inout IO2 ; inout IO1 ; inout IO0 ; input CLE ; input ALE ; input CENeg ; input RENeg ; input WENeg ; input WPNeg ; input PRE ; input FPNeg ; output RY ; parameter mem_file_name = "none"; parameter invblocks_file_name = "none"; parameter UserPreload = 1'b0; parameter TimingModel = "DefaultTimingModel"; // interconnect path delay signals wire IO7_ipd ; wire IO6_ipd ; wire IO5_ipd ; wire IO4_ipd ; wire IO3_ipd ; wire IO2_ipd ; wire IO1_ipd ; wire IO0_ipd ; wire [7 : 0] A; assign A = {IO7_ipd, IO6_ipd, IO5_ipd, IO4_ipd, IO3_ipd, IO2_ipd, IO1_ipd, IO0_ipd }; wire [7 : 0 ] DIn; assign DIn = { IO7_ipd, IO6_ipd, IO5_ipd, IO4_ipd, IO3_ipd, IO2_ipd, IO1_ipd, IO0_ipd }; wire [7 : 0 ] DOut; assign DOut = { IO7, IO6, IO5, IO4, IO3, IO2, IO1, IO0 }; wire CLE_ipd ; wire ALE_ipd ; wire CENeg_ipd ; wire RENeg_ipd ; wire WENeg_ipd ; wire WPNeg_ipd ; wire PRE_ipd ; wire FP_ipd ; // internal delays reg PROG_in ; reg PROG_out ; reg XPROG_in ; reg XPROG_out ; reg PRE_PROG_in ; reg PRE_PROG_out ; reg BERS_in ; reg BERS_out ; reg XBERS_in ; reg XBERS_out ; reg TR_in ; reg TR_out ; reg TRPRE_in ; reg TRPRE_out ; reg FPSTART_in ; reg FPSTART_out ; reg BSTATINQ_in ; reg BSTATINQ_out ; reg [7 : 0] DOut_zd; wire IO7_zd ; wire IO6_zd ; wire IO5_zd ; wire IO4_zd ; wire IO3_zd ; wire IO2_zd ; wire IO1_zd ; wire IO0_zd ; assign {IO7_zd , IO6_zd , IO5_zd , IO4_zd , IO3_zd , IO2_zd , IO1_zd , IO0_zd } = DOut_zd; reg [7 : 0] DOut_pass; wire IO7_pass ; wire IO6_pass ; wire IO5_pass ; wire IO4_pass ; wire IO3_pass ; wire IO2_pass ; wire IO1_pass ; wire IO0_pass ; assign {IO7_pass , IO6_pass , IO5_pass , IO4_pass , IO3_pass , IO2_pass , IO1_pass , IO0_pass } = DOut_pass; reg R_zd = 1'b0; parameter PartID = "s30ml512p00"; parameter MaxData = 8'hFF; parameter BlockNum = 127; parameter BlockSize = 1023; parameter PageSize = 527; parameter PageNum = 20'h1FFFF; parameter InvalidData = 2; parameter SegmentNum = 2; parameter SegmentSize = 256; parameter InvBlocksNum = 2; // If generic Long_Timming is set to 0, you need to uncomment line below //`define SPEEDSIM; // constraint memory preload file parameters parameter preload_line_width = 160; parameter preload_address_width = 8; parameter preload_data_width = 2; integer memory_read_data; integer memory_read_data1; // control signals reg STAT_ACT =1'b0; reg STAT_M_ACT =1'b0; reg ERS_ACT =1'b0; reg PRG_ACT =1'b0; reg RD_ACT =1'b0; reg FP_ACT =1'b0; reg XTREM_ACT =1'b0; reg XTR_MPRG =1'b0; reg RSTSTART =1'b0; reg RSTDONE =1'b0; reg back_to_xtrem =1'b0; reg IDRD_ACT =1'b0; // Control signals for read operation reg PGR_ACT =1'b0; // Page read in progress reg PGD_ACT =1'b0; // Page Duplicate reg idread =1'b0; reg noidread =1'b1; // powerup reg PoweredUp =1'b0; reg reseted =1'b0; reg write =1'b0; reg read =1'b0; integer WER_01; // 8 bit Address integer AddrCom ; // Address within page integer Address ; // 0 - Pagesize // Page Number integer PageAddr = -1; //-1 - PageNum // Block Number integer BlockAddr = -1; //-1 - BlockNum integer BlckDup = 0; integer InvalidBlockTable [0: BlockNum]; //Data integer Data ; //-1 - MaxData //ID control signals integer IDAddr ; // 0 - 4 integer BlockPage ; // RANGE 0 TO BlockSize; integer Pom_Address ; // RANGE 0 TO PageSize; integer Blck_pom ; integer WrAddr_tmp ; // program control signals integer CashBuffData [0:PageSize]; //Page chache register integer CashBuffData1 [0:PageSize]; //Page chache register integer WrBuffData[0:PageSize]; integer WrBuffData1[0:PageSize]; integer WrAddr ; // -1 - Pagesize +1 integer WrPage ; // 0 - PageNum integer PDBuffer [0:PageSize]; integer PDBuffer1 [0:PageSize]; integer Page_pom; integer cnt_addr; reg [0:(PageNum+1)*(SegmentNum+1)-1] ProgramedFlag = 0; reg [0:BlockNum] InvBlock = 0; reg [0:BlockNum] InvBlockPgms = 0; reg [0:BlockNum] PreProgFlag = 0; reg [0:BlockNum] ProgBlock = 0; reg [0:BlockNum] BlockMod = 0; // 0 for NORMAL, 1 for XTREME integer ssa[0:SegmentNum]; integer sea[0:SegmentNum]; integer segment; integer segment1; integer pom_seg ; integer pom_seg1; reg [0:SegmentNum] SegForProg; reg [0:SegmentNum] SegForProg1; // ID Array integer IDArray[0:4]; // timing check violation reg Viol = 1'b0; // initial integer i,j; //RstTime time duration; //Functional reg[7:0] Status = 8'b01000000; reg oe = 1'b0; integer Page ; // 0 - PageNum integer Blck ; // 0 - BlockNum integer Pointer ; reg [0:BlockNum] corrupt_flag; integer prog_time; integer erase_time; reg falling_edge_write; reg rising_edge_reseted; reg rising_edge_PRE_PROG_out; reg rising_edge_RSTDONE; reg rising_edge_TR_out; reg rising_edge_TRPRE_out; reg rising_edge_PROG_out; reg rising_edge_XPROG_out; reg rising_edge_BERS_out; reg rising_edge_XBERS_out; reg rising_edge_BSTATINQ_out; reg rising_edge_read; // states reg [5:0] current_state; reg [5:0] next_state; // FSM states parameter IDLE =6'h00; // parameter XTREM_PREL =6'h01; // parameter XTREM_IDLE =6'h02; // parameter UNKNOWN =6'h03; // wrong command sequneces parameter RESET =6'h04; // parameter PREL_RD =6'h05; // parameter A0_RD =6'h06; // parameter A1_RD =6'h07; // parameter A2_RD =6'h08; // parameter BUFF_TR =6'h09; // parameter RD =6'h0A; // parameter ID_PREL =6'h10; // parameter ID =6'h11; // parameter PREL_PRG =6'h12; // parameter A0_PRG =6'h13; // parameter A1_PRG =6'h14; // parameter A2_PRG =6'h15; // parameter DATA_PRG =6'h16; // parameter PGMS =6'h17; parameter PRE_PRG =6'h18; parameter PREL_ERS =6'h19; parameter A0_ERS =6'h1A; parameter A1_ERS =6'h1B; parameter A2_ERS =6'h1C; parameter BERS_EXEC =6'h1D; parameter PGD_PREL =6'h20; parameter A0_PGD =6'h21; parameter A1_PGD =6'h22; parameter A2_PGD =6'h23; parameter CONF_PGD =6'h24; parameter BSTAT_INQ =6'h25; /////////////////////////////////////////////////////////////////////////////// //Interconnect Path Delay Section /////////////////////////////////////////////////////////////////////////////// buf (IO7_ipd , IO7 ); buf (IO6_ipd , IO6 ); buf (IO5_ipd , IO5 ); buf (IO4_ipd , IO4 ); buf (IO3_ipd , IO3 ); buf (IO2_ipd , IO2 ); buf (IO1_ipd , IO1 ); buf (IO0_ipd , IO0 ); buf (CLE_ipd , CLE ); buf (ALE_ipd , ALE ); buf (CENeg_ipd , CENeg ); buf (RENeg_ipd , RENeg ); buf (WENeg_ipd , WENeg ); buf (WPNeg_ipd , WPNeg ); buf (PRE_ipd , PRE ); buf (FPNeg_ipd , FPNeg ); /////////////////////////////////////////////////////////////////////////////// // Propagation delay Section /////////////////////////////////////////////////////////////////////////////// nmos (IO7 , IO7_pass , 1); nmos (IO6 , IO6_pass , 1); nmos (IO5 , IO5_pass , 1); nmos (IO4 , IO4_pass , 1); nmos (IO3 , IO3_pass , 1); nmos (IO2 , IO2_pass , 1); nmos (IO1 , IO1_pass , 1); nmos (IO0 , IO0_pass , 1); nmos (RY , 1'b0, ~R_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; reg tdp_AL, tdp_CE, tdp_RE; wire idread_cond; wire noidread_cond; assign idread_cond = idread && tdp_RE; assign noidread_cond = noidread && tdp_RE; 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 specparam tpd_ALE_IO0 = 1; //tsetup values specparam tsetup_CLE_WENeg = 1;//tcls edge \ specparam tsetup_CENeg_WENeg = 1;//tcs edge \ specparam tsetup_ALE_WENeg = 1;//tals edge \ specparam tsetup_IO0_WENeg = 1;//tds edge / specparam tsetup_WPNeg_WENeg = 1;//tww edge / specparam tsetup_CLE_RENeg = 1;//tclr specparam tsetup_RENeg_WENeg = 1;//twhw edge \ specparam tsetup_WENeg_CENeg = 1;//twhc edge \ specparam tsetup_WENeg_RENeg = 1;//twhr 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 / //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 = 9000; // Fast programming operation specparam tdevice_FPROG = 7200; // Program Operation specparam tdevice_XPROG = 2000; // Program Operation specparam tdevice_PRE_PROG = 90000; //Block Erase Operation specparam tdevice_BERS = 400000; //Fast block erase operation specparam tdevice_FBERS = 360000; //Block Erase Operation specparam tdevice_XBERS = 400000; //Block status inquiry time specparam tdevice_BSTATINQ = 1000; //Page transfer time specparam tdevice_TR = 7000; specparam tdevice_TRPRE = 10000; //Fast programming start time specparam tdevice_FPSTART = 100; `else // not SPEEDSIM // Program Operation specparam tdevice_PROG = 900000; // Fast programming operation specparam tdevice_FPROG = 720000; // Program Operation specparam tdevice_XPROG = 120000; // Program Operation specparam tdevice_PRE_PROG = 90000000; //Block Erase Operation specparam tdevice_BERS = 400000000; //Fast block erase operation specparam tdevice_FBERS = 360000000; //Block Erase Operation specparam tdevice_XBERS = 400000000; //Block status inquiry time specparam tdevice_BSTATINQ = 1000; //Page transfer time specparam tdevice_TR = 7000; specparam tdevice_TRPRE = 50000; //Fast programming start time specparam tdevice_FPSTART = 100; `endif // SPEEDSIM /////////////////////////////////////////////////////////////////////////////// // Input Port Delays don't require Verilog description /////////////////////////////////////////////////////////////////////////////// // Path delays // /////////////////////////////////////////////////////////////////////////////// // specify transport delay for Data output paths // Data ouptut paths if(tdp_CE) ( CENeg *> IO7 ) = tpd_CENeg_IO0; if(tdp_CE) ( CENeg *> IO6 ) = tpd_CENeg_IO0; if(tdp_CE) ( CENeg *> IO5 ) = tpd_CENeg_IO0; if(tdp_CE) ( CENeg *> IO4 ) = tpd_CENeg_IO0; if(tdp_CE) ( CENeg *> IO3 ) = tpd_CENeg_IO0; if(tdp_CE) ( CENeg *> IO2 ) = tpd_CENeg_IO0; if(tdp_CE) ( CENeg *> IO1 ) = tpd_CENeg_IO0; if(tdp_CE) ( CENeg *> IO0 ) = tpd_CENeg_IO0; if(idread_cond) ( RENeg *> IO7 ) = tpd_RENeg_IO0; if(idread_cond) ( RENeg *> IO6 ) = tpd_RENeg_IO0; if(idread_cond) ( RENeg *> IO5 ) = tpd_RENeg_IO0; if(idread_cond) ( RENeg *> IO4 ) = tpd_RENeg_IO0; if(idread_cond) ( RENeg *> IO3 ) = tpd_RENeg_IO0; if(idread_cond) ( RENeg *> IO2 ) = tpd_RENeg_IO0; if(idread_cond) ( RENeg *> IO1 ) = tpd_RENeg_IO0; if(idread_cond) ( RENeg *> IO0 ) = tpd_RENeg_IO0; if(noidread_cond) ( RENeg *> IO7 ) = tpd_RENeg_IO0; if(noidread_cond) ( RENeg *> IO6 ) = tpd_RENeg_IO0; if(noidread_cond) ( RENeg *> IO5 ) = tpd_RENeg_IO0; if(noidread_cond) ( RENeg *> IO4 ) = tpd_RENeg_IO0; if(noidread_cond) ( RENeg *> IO3 ) = tpd_RENeg_IO0; if(noidread_cond) ( RENeg *> IO2 ) = tpd_RENeg_IO0; if(noidread_cond) ( RENeg *> IO1 ) = tpd_RENeg_IO0; if(noidread_cond) ( RENeg *> IO0 ) = tpd_RENeg_IO0; if(tdp_AL) ( ALE => IO7 ) = tpd_ALE_IO0; if(tdp_AL) ( ALE => IO6 ) = tpd_ALE_IO0; if(tdp_AL) ( ALE => IO5 ) = tpd_ALE_IO0; if(tdp_AL) ( ALE => IO4 ) = tpd_ALE_IO0; if(tdp_AL) ( ALE => IO3 ) = tpd_ALE_IO0; if(tdp_AL) ( ALE => IO2 ) = tpd_ALE_IO0; if(tdp_AL) ( ALE => IO1 ) = tpd_ALE_IO0; if(tdp_AL) ( ALE => IO0 ) = tpd_ALE_IO0; // R output path (WENeg => RY) = tpd_WENeg_RY; /////////////////////////////////////////////////////////////////////////////// // Timing Violation / /////////////////////////////////////////////////////////////////////////////// $setup ( IO7 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO6 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO5 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO4 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO3 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO2 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO1 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $setup ( IO0 ,posedge WENeg &&& Check_IO0_WENeg ,tsetup_IO0_WENeg,Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO7 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO6 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO5 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO4 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO3 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO2 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO1 ,thold_IO0_WENeg, Viol); $hold ( posedge WENeg &&& Check_IO0_WENeg , IO0 ,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 ( WPNeg ,negedge WENeg ,tsetup_WENeg_RENeg , Viol); $setup ( CLE ,negedge RENeg ,tsetup_CLE_RENeg , Viol); $setup ( RENeg ,negedge WENeg ,tsetup_RENeg_WENeg , Viol); $setup ( WENeg ,negedge CENeg &&& WENeg ,tsetup_WENeg_CENeg , Viol); $setup ( WENeg ,negedge RENeg ,tsetup_WENeg_RENeg , Viol); $hold ( posedge WENeg &&& Check_WENeg,CLE,thold_CLE_WENeg, Viol); $hold ( posedge WENeg &&& Check_WENeg,CENeg,thold_CENeg_WENeg,Viol); $hold ( posedge WENeg &&& Check_WENeg,ALE,thold_ALE_WENeg, 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 //Used as wait periods `ifdef SPEEDSIM time poweredupT = 10000; // 10 us time poweredupT1 = 2000; time RstErsT = 500000;// 5 us time RstProgT = 10000; // 10 us time RstReadT = 5000; // 5 us `else // not SPEEDSIM time poweredupT = 10000; // 10 us time poweredupT1 = 10000; time RstErsT = 500000000;// 500 ms time RstProgT = 10000000; // 10 ms time RstReadT = 5000000; // 5 us `endif // SPEEDSIM /////////////////////////////////////////////////////////////////////////////// // 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; initial begin ////////////////////////////////////////////////////////////////// //ID array data / S30ML512P00 DEVICE SPECIFIC ////////////////////////////////////////////////////////////////// IDArray[4'd0] = 8'h01; IDArray[4'd1] = 8'h76; if (TimingModel == "s30ml512p50tfi50" || TimingModel == "S30ML512P50TFI50") IDArray[4'd2] = 8'h00; else if (TimingModel == "s30ml512p50tfi00" || TimingModel == "S30ML512P50TFI00") IDArray[4'd2] = 8'h01; IDArray[4'd3] = 8'h01; IDArray[4'd4] = 8'h01; 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,s,segm; // memory region implicitly initialized memory_features_i0.initialize_w(); // initialize flags only for (i=0;i<(PageNum+1)*(SegmentNum+1);i=i+1) ProgramedFlag[i] = 1'b0; for (i=0; i<= BlockNum; i=i+1) InvalidBlockTable[i] = 0; if (UserPreload && !(invblocks_file_name == "none")) $readmemh(invblocks_file_name, InvalidBlockTable); if (UserPreload && !(mem_file_name == "none")) begin //----------------------------------------------------------------- // Memory preload file format for s30ml512p00 //----------------------------------------------------------------- // / - comment // @aaaaaaaa - stands for page address and address within // first 528 bytes of the page // dd -
is byte to be written at Mem(Page)(offset++) // page is div 528 // offset is mod 528 // offset is incremented on every write //----------------------------------------------------------------- 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_data !== MaxData) begin if (scanf_address < ((PageNum + 1) * (PageSize + 1))) begin memory_features_i0.write_mem_w (scanf_address, scanf_data); getSegment(scanf_address,segm); ProgramedFlag[(scanf_address/(PageSize + 1)) *(SegmentNum+1)+segm] = 1'b1; end else $display("Memory address out of range."); end scanf_address++; end end end $fclose(mem_file_name); end s = 0; for (i=0; i<= BlockNum; i=i+1) begin if (InvalidBlockTable[i] == 1) begin memory_features_i0.write_mem_w( i*(BlockSize+1)*(PageSize+1)+517, InvalidData); s = s+1; if (s > InvBlocksNum) $display("Warning: Number of invalid blocks exceeds range"); end end end // ------------------------------------------------------------------------- // --------------- the end of preload section modifications -------------- // ------------------------------------------------------------------------- initial begin STAT_ACT =1'b0; STAT_M_ACT =1'b0; ERS_ACT =1'b0; PRG_ACT =1'b0; FP_ACT =1'b0; RD_ACT =1'b0; XTREM_ACT =1'b0; XTR_MPRG =1'b0; RSTSTART =1'b0; RSTDONE =1'b0; write =1'b0; read =1'b0; //page segment start address offset ssa[0] =12'h000; ssa[1] =12'h100; ssa[2] =12'h200; //page segment end address offset sea[0] =12'h0FF; sea[1] =12'h1FF; sea[2] =12'h20F; for (j=0; j<=PageSize; j=j+1) begin WrBuffData[j] = -1; WrBuffData1[j] = -1; end WrAddr = -1; WrPage = -1; for (j=0; j<= BlockNum; j=j+1) corrupt_flag[j] = 0; current_state = IDLE; next_state = IDLE; Status = 8'b01000000; PROG_in = 1'b0; PROG_out = 1'b0; XPROG_in = 1'b0; XPROG_out = 1'b0; PRE_PROG_in = 1'b0; PRE_PROG_out = 1'b0; BERS_in = 1'b0; BERS_out = 1'b0; XBERS_in = 1'b0; XBERS_out = 1'b0; TR_in = 1'b0; TR_out = 1'b0; TRPRE_in = 1'b0; TRPRE_out = 1'b0; FPSTART_in = 1'b0; FPSTART_out= 1'b0; BSTATINQ_in= 1'b0; BSTATINQ_out=1'b0; R_zd = 1'b1; prog_time = tdevice_PROG; erase_time = tdevice_BERS; idread = 1'b0; noidread = 1'b1; falling_edge_write = 0; rising_edge_reseted = 0; rising_edge_PRE_PROG_out = 0; rising_edge_RSTDONE = 0; rising_edge_TR_out = 0; rising_edge_TRPRE_out = 0; rising_edge_PROG_out = 0; rising_edge_XPROG_out = 0; rising_edge_BERS_out = 0; rising_edge_XBERS_out = 0; rising_edge_BSTATINQ_out = 0; rising_edge_read = 0; end //Power Up time 10 us; initial begin PoweredUp = 1'b0; #poweredupT PoweredUp = 1'b1; end always @(negedge FPNeg) begin FP_ACT = 1'b1; FPSTART_in = 1'b1; prog_time = tdevice_FPROG; erase_time= tdevice_FBERS; if (PRG_ACT) begin $display("Embeded programm in progress, simulation may be "); $display("inacurate due to timinig violation on FP"); end if (ERS_ACT) begin $display("Embeded erase in progress, simulation may be "); $display("inacurate due to timinig violation on FP"); end end always @(posedge FPNeg) begin if (PRG_ACT) begin $display("Embeded programm in progress, simulation may be "); $display("inacurate due to timinig violation on FP"); end if (ERS_ACT) begin $display("Embeded programm in progress, simulation may be "); $display("inacurate due to timinig violation on FP"); end FP_ACT = 1'b0; FPSTART_in = 1'b0; prog_time = tdevice_PROG; erase_time = tdevice_BERS; end always @(IDRD_ACT) begin: Id_read_activation if (IDRD_ACT) begin idread = 1; noidread = 0; end else if (~IDRD_ACT) begin idread = 0; noidread = 1; end end always @(posedge FPSTART_in) begin : FP_Time #(tdevice_FPSTART) FPSTART_out = 1'b1; end always @(negedge FPSTART_in) begin disable FP_Time; #1 FPSTART_out = 1'b0; end //Program Operation always @(posedge PROG_in) begin:ProgTime if (FP_ACT & (~FPSTART_out)) begin $display("Simulation results may been inacurate"); $display("since timing violation occures on FP"); end #(prog_time + WER_01) PROG_out = 1'b1; end always @(negedge PROG_in) begin disable ProgTime; #1 PROG_out = 1'b0; end //PreProgram Operation always @(posedge PRE_PROG_in) begin:PreProgTime #(tdevice_PRE_PROG + WER_01) PRE_PROG_out = 1'b1; end always @(negedge PRE_PROG_in) begin disable PreProgTime; #1 PRE_PROG_out = 1'b0; end //XProgram Operation always @(posedge XPROG_in) begin:XProgTime #(tdevice_XPROG + WER_01) XPROG_out = 1'b1; end always @(negedge XPROG_in) begin disable XProgTime; #1 XPROG_out = 1'b0; end //Block Erase Operation always @(posedge BERS_in) begin : ErsTime if (FP_ACT & (~FPSTART_out)) begin $display("Simulation results may been inacurate"); $display("since timing violation occures on FP"); end #(erase_time + WER_01) BERS_out = 1'b1; end always @(negedge BERS_in) begin disable ErsTime; #1 BERS_out = 1'b0; end //Block Erase Operation always @(posedge XBERS_in) begin : XErsTime #(tdevice_BERS + WER_01) XBERS_out = 1'b1; end always @(negedge XBERS_in) begin disable XErsTime; #1 XBERS_out = 1'b0; end //Page transfer time always @(posedge TR_in) begin : PageTransferTime #(tdevice_TR) TR_out = 1'b1; end always @(negedge TR_in) begin disable PageTransferTime; #1 TR_out = 1'b0; end always @(posedge TRPRE_in) begin : PageTransferTime1 #(tdevice_TRPRE-poweredupT1) TRPRE_out = 1'b1; end always @(negedge TRPRE_in) begin disable PageTransferTime1; #1 TRPRE_out = 1'b0; end always @(posedge BSTATINQ_in) begin : BSTATINQ_Time #(tdevice_BSTATINQ + WER_01) BSTATINQ_out = 1'b1; end always @(negedge BSTATINQ_in) begin disable BSTATINQ_Time; #1 BSTATINQ_out = 1'b0; end /////////////////////////////////////////////////////////////////////////// // process for reset control and FSM state transition /////////////////////////////////////////////////////////////////////////// always @(PoweredUp, next_state) begin if (PoweredUp) begin reseted = 1'b1; 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 /////////////////////////////////////////////////////////////////////////// event rstdone_event; always @ (posedge reseted) begin disable rstdone_process; RSTDONE = 1'b1; // reset done end always @ (posedge RSTSTART) begin if (reseted && RSTDONE) begin if (ERS_ACT) duration = RstErsT; else if (PRG_ACT) duration = RstProgT; else duration = RstReadT; RSTDONE = 1'b0; ->rstdone_event; end end always @(rstdone_event) begin:rstdone_process #duration RSTDONE = 1'b1; end /////////////////////////////////////////////////////////////////////////// // Main Behavior Process // combinational process for next state generation /////////////////////////////////////////////////////////////////////////// always @(falling_edge_write, rising_edge_reseted, rising_edge_PRE_PROG_out, rising_edge_RSTDONE, rising_edge_TR_out, rising_edge_TRPRE_out, rising_edge_PROG_out, rising_edge_XPROG_out, rising_edge_BERS_out, rising_edge_XBERS_out, rising_edge_BSTATINQ_out, reseted) begin: StateGen if (reseted != 1'b1 ) next_state = current_state; else if (rising_edge_reseted) begin if (PRE) next_state = BUFF_TR; else next_state = IDLE; end else case (current_state) IDLE : begin if (falling_edge_write) begin if (CLE && ~ALE && (Data==8'h00 || Data==8'h01 || Data==8'h50) && ~FP_ACT) next_state = PREL_RD; else if ( CLE && ~ALE && Data==8'h90 && ~FP_ACT) 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'hFF && ~FP_ACT) next_state = RESET; // reset else if ( CLE && ~ALE && Data==8'h70 ) next_state = IDLE; // reset else if ( CLE && ~ALE && Data==8'hA0 && ~FP_ACT ) next_state = XTREM_PREL; else if ( CLE) next_state = UNKNOWN; end end XTREM_PREL : begin if (falling_edge_write) begin if (CLE && ~ALE && Data==8'hA0 && ~FP_ACT) next_state = XTREM_IDLE; else if (CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; else if (CLE) next_state = UNKNOWN; end end XTREM_IDLE : begin if (falling_edge_write) begin if (CLE && ~ALE && (Data==8'h00 || Data==8'h01 || Data==8'h50) && ~FP_ACT) next_state = PREL_RD; else if ( CLE && ~ALE && Data==8'h90 && ~FP_ACT) next_state = ID_PREL; else if ( CLE && ~ALE && Data==8'h80 && ~FP_ACT) next_state = PREL_PRG; else if ( CLE && ~ALE && Data==8'h60 && ~FP_ACT) next_state = PREL_ERS; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if ( CLE && ~ALE && Data==8'h70 && ~FP_ACT) next_state = XTREM_IDLE; // reset else if ( CLE && ~ALE && Data==8'hA0 && ~FP_ACT) next_state = XTREM_IDLE; else if ( CLE) next_state = UNKNOWN; end end PRE_PRG : begin if (falling_edge_write) begin if (CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset end else if (rising_edge_PRE_PROG_out) next_state = XTREM_IDLE; end UNKNOWN: begin if (falling_edge_write) if (CLE && ~ALE && Data==8'hFF && ~FP_ACT ) next_state = RESET; end RESET: begin if (rising_edge_RSTDONE && ~FP_ACT) begin if (~XTREM_ACT) next_state = IDLE; else next_state = XTREM_IDLE; end end PREL_RD: begin if (falling_edge_write) begin if (ALE && ~FP_ACT) next_state = A0_RD; else if (CLE && ~ALE && Data == 8'h80 && ~FP_ACT) next_state = PREL_PRG; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; else if (CLE) next_state = UNKNOWN; // reset end end A0_RD : begin if (falling_edge_write) begin if ( ALE && ~FP_ACT) next_state = A1_RD; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if ( CLE) next_state = UNKNOWN; end end A1_RD : begin if (falling_edge_write) begin if ( ALE && ~FP_ACT) next_state = A2_RD; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT ) next_state = RESET; // reset else if ( CLE) next_state = UNKNOWN; end end A2_RD : begin if (falling_edge_write) begin if ( ALE && ~FP_ACT) next_state = BUFF_TR; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if ( CLE) next_state = UNKNOWN; end end BUFF_TR : begin if (falling_edge_write) begin if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset end else if (rising_edge_TR_out || rising_edge_TRPRE_out) next_state = RD; end RD : begin if (falling_edge_write) begin if (CLE && ~ALE && (Data==8'h00 || Data==8'h01 || Data==8'h50) && ~FP_ACT) begin if (STAT_ACT && PGR_ACT && Data==8'h00) next_state= RD; else if (PGR_ACT || STAT_M_ACT) next_state = PREL_RD; else next_state = UNKNOWN; end else if (CLE && ~ALE && Data==8'h80 && ~PGD_ACT) next_state = PREL_PRG; else if (CLE && ~ALE && Data==8'h90 && ~PGD_ACT && ~FP_ACT) next_state = ID_PREL; else if (CLE && ~ALE && Data==8'h70 && ~XTREM_ACT) next_state = RD; else if (CLE && ~ALE && Data==8'h70 && XTREM_ACT && ~FP_ACT) next_state = RD; else if (CLE && ~ALE && Data==8'hFF && ~FP_ACT ) next_state = RESET; // reset else if (CLE && ~ALE && Data==8'h60 && ~PGD_ACT) next_state = PREL_ERS; else if (CLE && ~ALE && (Data==8'h8A || (Data==8'h85 && XTREM_ACT) )) next_state = PGD_PREL; // Read next colomn address else if (CLE && ~ALE && Data==8'hA0 && ~PGD_ACT && ~XTREM_ACT && ~FP_ACT) next_state = XTREM_PREL; else if (CLE) next_state = UNKNOWN; else next_state = RD; end end ID_PREL : begin if (falling_edge_write) if ( ~CLE && ALE && AddrCom==8'h00 && ~FP_ACT ) next_state = ID; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if (CLE || ALE) next_state = UNKNOWN; end ID : begin if (falling_edge_write) begin if ( CLE && ~ALE && (Data==8'h00 || Data==8'h01 || Data==8'h50) && ~FP_ACT ) next_state = PREL_RD; else if ( CLE && ~ALE && Data==8'h90 && ~FP_ACT ) 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 && ~XTREM_ACT ) next_state = IDLE; else if ( CLE && ~ALE && Data==8'h70 && XTREM_ACT && ~FP_ACT) next_state = XTREM_IDLE; else if ( CLE && ~ALE && Data==8'hA0 && ~XTREM_ACT && ~FP_ACT) next_state = XTREM_PREL; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT ) next_state = RESET; // reset else if (CLE || ALE) next_state = UNKNOWN; end end PREL_PRG : begin if (falling_edge_write) begin if ( ALE ) next_state = A0_PRG; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if (CLE) next_state = UNKNOWN; end end A0_PRG : begin if (falling_edge_write) begin if ( ALE ) next_state = A1_PRG; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if (CLE) next_state = UNKNOWN; end end A1_PRG : begin if (falling_edge_write) begin if ( ALE ) next_state = A2_PRG; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if (CLE) next_state = UNKNOWN; end end A2_PRG : begin if (falling_edge_write) begin if ( ALE ) next_state = DATA_PRG; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if (CLE) next_state = UNKNOWN; end end DATA_PRG : begin if (falling_edge_write) begin if ((ALE && (cnt_addr <2 || cnt_addr >= 4)) || (CLE && ~ALE && cnt_addr > 4)) next_state = UNKNOWN; else if (CLE && ~ALE && Data==8'h10) begin if (~PRG_ACT) next_state = PGMS; end else if (CLE && ~ALE && Data==8'hFF) next_state = RESET; // reset else if (CLE) next_state = UNKNOWN; else if (~ALE && ~CLE && WrAddr < PageSize+1) next_state = DATA_PRG; // write next word to buffer end end PGMS : begin if (falling_edge_write) begin if (CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset end else if (rising_edge_PROG_out) next_state = IDLE; else if (rising_edge_XPROG_out && ~FP_ACT) next_state = XTREM_IDLE; end PREL_ERS : begin if (falling_edge_write) begin if ( ALE ) next_state = A0_ERS; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if ( CLE ) next_state = UNKNOWN; // reset end end A0_ERS : begin if (falling_edge_write) begin if ( ALE ) next_state = A1_ERS; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if ( CLE ) next_state = UNKNOWN; // reset end end A1_ERS : begin if (falling_edge_write) begin if ( ALE ) next_state = A2_ERS; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if ( CLE ) next_state = UNKNOWN; // reset end end A2_ERS : begin if (falling_edge_write) begin if ( CLE && ~ALE && Data==8'hD0) next_state = BERS_EXEC; else if (CLE && ~ALE && XTREM_ACT && Data == 8'h11 && ~FP_ACT) next_state = PRE_PRG; else if (CLE && ~ALE && Data == 8'h71 && ~FP_ACT) next_state = BSTAT_INQ; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; else if ( CLE || ALE) next_state = UNKNOWN; end end BERS_EXEC : begin if (falling_edge_write) begin if (CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset end else if (rising_edge_BERS_out) next_state = IDLE; else if (rising_edge_XBERS_out && ~FP_ACT) next_state = XTREM_IDLE; end PGD_PREL : begin if (falling_edge_write) begin if ( ALE ) next_state = A0_PGD; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT ) next_state = RESET; // reset else if ( CLE ) next_state = UNKNOWN; // reset end end A0_PGD : begin if (falling_edge_write) begin if (ALE) next_state = A1_PGD; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if ( CLE ) next_state = UNKNOWN; // reset end end A1_PGD : begin if (falling_edge_write) begin if ( ALE ) next_state = A2_PGD; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT ) next_state = RESET; // reset else if ( CLE ) next_state = UNKNOWN; // reset end end A2_PGD : begin if (falling_edge_write) begin if ( ALE ) next_state = CONF_PGD; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if ( CLE ) next_state = UNKNOWN; // reset end end CONF_PGD : begin if (falling_edge_write) begin if ((ALE && cnt_addr >= 4) || (CLE && ~ALE && cnt_addr > 4)) next_state = UNKNOWN; else if ( CLE && ~ALE && Data==8'h10) next_state = PGMS; else if ( CLE && ~ALE && XTREM_ACT && Data==8'h12 && ~FP_ACT) next_state = PGMS; else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset else if ( CLE ) next_state = UNKNOWN; // reset end end BSTAT_INQ : begin if (falling_edge_write) begin if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) next_state = RESET; // reset end else if (rising_edge_BSTATINQ_out && ~FP_ACT) next_state = RD; end endcase end /////////////////////////////////////////////////////////////////////////// //FSM Output generation and general funcionality /////////////////////////////////////////////////////////////////////////// always @(rising_edge_reseted, rising_edge_read, falling_edge_write, rising_edge_RSTDONE, rising_edge_TR_out, rising_edge_TRPRE_out, rising_edge_PRE_PROG_out, rising_edge_PROG_out, rising_edge_XPROG_out, rising_edge_BERS_out, rising_edge_XBERS_out, rising_edge_BSTATINQ_out, RENeg, CENeg) begin: Functional oe = rising_edge_read; Status[7] = WPNeg_ipd; if (~reseted) R_zd = 1'b0; else if (rising_edge_reseted) begin Pointer = 0; if (PRE) begin Address = 0; PageAddr = 0; BlockAddr = 0; PGR_ACT = 1; TRPRE_in = 1; end else begin PGR_ACT = 0; R_zd = 1; end end case (current_state) IDLE, XTREM_IDLE : begin IDRD_ACT = 0; if (falling_edge_write) begin if (CLE && ~ALE && (Data == 8'h00 || Data == 8'h01 || Data == 8'h50) && ~FP_ACT) begin Status[6] = 1; Status[0] = 0; STAT_ACT = 0; end else if (CLE && ~ALE && Data==8'h70) STAT_ACT = 1'b1; else if (CLE && ~ALE && Data==8'h80) STAT_ACT = 1'b0; else if (CLE && ~ALE && Data==8'h90 && ~FP_ACT) begin STAT_ACT = 1'b0; IDRD_ACT = 1; end else if (CLE && ~ALE && Data==8'h60) begin STAT_ACT = 0; Status[6] = 1; Status[0] = 0; end else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) set_reset; end back_to_xtrem = 0; if (oe) if (STAT_ACT) Read_status(Blck); end XTREM_PREL : begin if (falling_edge_write && ~FP_ACT) begin if (CLE && ~ALE && Data == 8'hA0) XTREM_ACT = 1'b1; else if (CLE && ~ALE && Data==8'hFF) set_reset; end end UNKNOWN: begin if (falling_edge_write) if (CLE && ~ALE && Data==8'hFF) begin ERS_ACT = 1'b0; PGD_ACT = 1'b0; RD_ACT = 1'b0; PGR_ACT = 1'b0; Status[6] = 1'b1; Status[0] = 1'b0; set_reset; end end RESET: begin if (falling_edge_write) begin if ( CLE && ~ALE && Data==8'h70 ) STAT_ACT = 1'b1; end if (back_to_xtrem == 0) XTREM_ACT = 0; else XTREM_ACT = 1; if (rising_edge_RSTDONE && ~FP_ACT) begin ERS_ACT = 0; RD_ACT = 0; PGD_ACT = 0; STAT_M_ACT = 0; XTR_MPRG = 0; R_zd = 1; Status[6] = 1; Status[0] = 0; PGR_ACT = 0; end else begin Status[6] = 0; Status[0] = 0; end IDRD_ACT = 0; if (oe) if (STAT_ACT) Read_status(Blck); end PREL_RD: begin if (Data == 8'h00) Pointer = 0; else if (Data == 8'h01) Pointer = 256; else if (Data == 8'h50) Pointer = 512; if (falling_edge_write) begin if (ALE && ~FP_ACT) begin Pom_Address = AddrCom + Pointer; cnt_addr = 0; end else if (CLE && ~ALE && Data==8'hFF && ~FP_ACT) set_reset; end end A0_RD : begin if (falling_edge_write) begin if ( ALE && ~FP_ACT) begin Page = AddrCom; cnt_addr = cnt_addr + 1; end else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) set_reset; end end A1_RD : begin if (falling_edge_write) begin if ( ALE && ~FP_ACT) begin Blck_pom = AddrCom / 8'h04; if ( XTREM_ACT ) Page = 2*(Page + (AddrCom % 4)*16'h100); else Page = (Page + (AddrCom % 4)*16'h100); cnt_addr = cnt_addr + 1; end else if ( CLE && ~ALE && Data==8'hFF ) set_reset; end end A2_RD : begin if (falling_edge_write) begin if ( ALE && ~FP_ACT) begin Blck = AddrCom* 8'h40 + Blck_pom; Address = Pom_Address; PageAddr = Page+Blck*(BlockSize+1); BlockAddr = Blck; PGR_ACT = 1; TR_in = 1; R_zd = 0; Status[6] = 0; cnt_addr = cnt_addr + 1; for (i=0;i<= PageSize; i=i+1) begin PDBuffer[i] = -1; PDBuffer1[i] = -1; end end else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) set_reset; end end BUFF_TR : begin if (falling_edge_write) begin if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) begin TR_in = 1'b0; TRPRE_in = 1'b0; if (XTREM_ACT) back_to_xtrem = 1'b1; else back_to_xtrem = 1'b0; set_reset; end else if ( CLE && ~ALE && Data==8'h70 ) STAT_ACT = 1'b1; end else if (rising_edge_TR_out && ~FP_ACT) begin R_zd = 1; Status[6] = 1; TR_in = 0; if (~XTREM_ACT) begin for (i=0;i<= PageSize; i=i+1) begin memory_features_i0.read_mem_w( memory_read_data, PageAddr * (PageSize + 1) + i ); PDBuffer[i] = memory_read_data; end end else if (XTREM_ACT) begin for (i=0; i<= PageSize; i=i+1) begin memory_features_i0.read_mem_w( memory_read_data, PageAddr * (PageSize + 1) + i ); PDBuffer[i] = memory_read_data; memory_features_i0.read_mem_w( memory_read_data1, (PageAddr + 1) * (PageSize + 1) + i ); PDBuffer1[i] = memory_read_data1; end end end else if (rising_edge_TRPRE_out) begin R_zd = 1; Status[6] = 1; TRPRE_in = 0; end IDRD_ACT = 0; if (oe && STAT_ACT) Read_status(Blck); end RD : begin IDRD_ACT = 0; if (falling_edge_write) begin if ( CLE && ~ALE && Data==8'h00 && ~FP_ACT) begin if (STAT_ACT) STAT_ACT = 1'b0; else if (~PGD_ACT) begin PGR_ACT = 1'b0; STAT_ACT = 1'b0; STAT_M_ACT = 1'b0; Status[6] = 1'b1; Status[0] = 1'b0; end end else if ( CLE && ~ALE && Data==8'h70) STAT_ACT = 1'b1; else if ( CLE && ~ALE && Data==8'h90 && ~PGD_ACT && ~FP_ACT) begin STAT_ACT = 1'b0; STAT_M_ACT = 1'b0; PGR_ACT = 1'b0; IDRD_ACT = 1; end else if ( CLE && ~ALE && Data==8'h80 && ~PGD_ACT) begin STAT_ACT = 1'b0; STAT_M_ACT = 1'b0; PGR_ACT = 1'b0; Status[6] = 1'b1; Status[0] = 1'b0; end else if (CLE && ~ALE && Data==8'hA0 && ~PGD_ACT && ~XTREM_ACT && ~FP_ACT) begin STAT_ACT = 1'b0; STAT_M_ACT = 1'b0; Status[6] = 1'b1; Status[0] = 1'b0; end else if ( CLE && ~ALE && Data==8'h60 && ~PGD_ACT) begin STAT_ACT = 1'b0; STAT_M_ACT = 1'b0; PGR_ACT = 1'b0; Status[6] = 1'b1; Status[0] = 1'b0; end else if ( CLE && ~ALE && Data==8'hFF ) begin set_reset; STAT_M_ACT = 1'b0; end else if ( CLE && ~ALE && Data==8'h85 && XTREM_ACT) begin PGD_ACT = 1; STAT_ACT = 1'b0; STAT_M_ACT = 1'b0; Status[6] = 1'b1; Status[0] = 1'b0; end else if (CLE && ~ALE && Data==8'h8A ) begin PGD_ACT = 1; STAT_ACT = 1'b0; STAT_M_ACT = 1'b0; Status[6] = 1'b1; Status[0] = 1'b0; end end if (Pointer == 256) Pointer = 0; back_to_xtrem = 0; if (oe) begin if (~STAT_ACT && ~STAT_M_ACT && ~PGD_ACT && ~FP_ACT) Read_Data(Address, PageAddr, BlockAddr); else if (~STAT_ACT && ~FP_ACT && ~PGD_ACT && STAT_M_ACT) Read_StatMode(Blck); else if (STAT_ACT) Read_status(Blck); end end ID_PREL : begin if (falling_edge_write && ~FP_ACT) begin if ( ALE && AddrCom==8'h00 ) IDAddr = 0; else if ( CLE && ~ALE && Data==8'hFF ) set_reset; end end ID : begin if (falling_edge_write) begin if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) set_reset; else if ( CLE && ~ALE && Data==8'h70 ) STAT_ACT = 1'b1; else if ( CLE && ~ALE && Data==8'h00 ) STAT_ACT = 1'b0; end if (oe) if (IDAddr < 5 && ~FP_ACT) begin DOut_zd = IDArray[IDAddr]; IDAddr = IDAddr+1; end else DOut_zd = 8'bz; end PREL_PRG : begin if (falling_edge_write) begin if ( ALE ) begin WrAddr = AddrCom + Pointer; cnt_addr = 0; end else if ( CLE && ~ALE && Data==8'hFF ) set_reset; end end A0_PRG : begin if (falling_edge_write) begin if ( ALE ) begin Page = AddrCom; cnt_addr = cnt_addr + 1; for(i=0; i<=PageSize; i=i+1) CashBuffData[i]=-1; end else if ( CLE && ~ALE && Data==8'hFF ) set_reset; end end A1_PRG : begin if (falling_edge_write) begin if ( ALE ) begin Blck_pom = AddrCom / 8'h4; if ( XTREM_ACT ) Page = 2*(Page + (AddrCom % 4)* 12'h100); else Page = (Page + (AddrCom % 4)* 12'h100); cnt_addr = cnt_addr + 1; end else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) set_reset; end end A2_PRG : begin if (falling_edge_write) begin if ( ALE ) begin Blck = AddrCom* 8'h40 +Blck_pom; Page_pom = Page; cnt_addr = cnt_addr + 1; for (i=0; i<=SegmentNum; i=i+1) begin SegForProg[i] = ProgramedFlag[Blck*(BlockSize+1)*(SegmentNum+1) +Page*(SegmentNum+1)+i]; SegForProg1[i] = ProgramedFlag[Blck*(BlockSize+1)*(SegmentNum+1) +(Page+1)*(SegmentNum+1)+i]; end end else if ( CLE && ~ALE && Data==8'hFF && ~FP_ACT) set_reset; end end DATA_PRG : begin if (falling_edge_write) begin if (CLE && ~ALE && Data==8'hFF) set_reset; else if (~ALE && ~CLE && WrAddr < PageSize+1) begin if (~XTREM_ACT) begin getSegment(WrAddr, segment); if (~ProgramedFlag[Blck*(BlockSize+1)*(SegmentNum+1) + Page*(SegmentNum+1)+segment]) begin CashBuffData[WrAddr] = Data; end SegForProg[segment] = 1; end else begin WrAddr_tmp = WrAddr; Page_pom = Page; XgetSegment(WrAddr_tmp,segment,segment1); if (~ProgramedFlag[Blck*(BlockSize+1)*(SegmentNum+1) + Page_pom*(SegmentNum+1)+segment] && ~ProgramedFlag[Blck*(BlockSize+1)*(SegmentNum+1) + Page_pom*(SegmentNum+1)+segment1] && ~PGD_ACT) CashBuffData[WrAddr] = Data; if (Page_pom > Page) begin SegForProg1[segment] = 1; SegForProg1[segment1] = 1; end else if (Page_pom == Page) begin SegForProg[segment] = 1; SegForProg[segment1] = 1; end end Page_pom = Page ; WrAddr = WrAddr+1; end else if (CLE && ~ALE && Data==8'h10) begin R_zd = 1'b0; Status[6] = 1'b0; ProgBlock[Blck] = 1; if (~PRG_ACT) WrPage = Page + Blck*(BlockSize+1); end else if (ALE) cnt_addr = cnt_addr + 1; end end PRE_PRG : begin if (rising_edge_PRE_PROG_out && ~FP_ACT) begin R_zd = 1; Status[6] = 1; BlockMod[Blck] = 1; end if (falling_edge_write) begin if (CLE && ~ALE && Data==8'hFF) begin if (~(WPNeg==1'b0) && InvalidBlockTable[Blck]== 0) begin corrupt_flag[Blck] = 1; InvBlock[Blck] = 1; end back_to_xtrem = 1; set_reset; end else if (CLE && ~ALE && Data==8'h70) STAT_ACT = 1; // read status end IDRD_ACT = 0; if (oe) if (STAT_ACT) Read_status(Blck); end PGMS : begin if ( WPNeg && InvalidBlockTable[Blck] ==0) begin for (i=0; i<=PageSize; i=i+1) begin WrBuffData[i] = CashBuffData[i]; WrBuffData1[i] = CashBuffData1[i]; end if (~XTREM_ACT) begin for(i=0;i<=PageSize;i=i+1) begin getSegment(i,segment); if (CashBuffData[i] != -1 && ProgramedFlag[WrPage*(SegmentNum+1)+ (WrPage%(BlockSize+1))*(SegmentNum+1) +segment]== 0) memory_features_i0.write_mem_w( WrPage * (PageSize + 1) + i, -1 ); end end else if (XTR_MPRG) begin for (i=0;i<=PageSize;i=i+1) begin getSegment(i,segment); if ( CashBuffData[i] != -1 && ProgramedFlag[WrPage*(SegmentNum+1) + (WrPage%(BlockSize+1))*(SegmentNum+1) + segment]== 0) memory_features_i0.write_mem_w( WrPage * (PageSize + 1) + i, -1 ); end end else if (PGD_ACT) begin for (i=0;i<=PageSize;i=i+1) begin Page_pom = WrPage % (BlockSize+1); XgetSegment(i ,pom_seg,pom_seg1); Page_pom = WrPage % (BlockSize+1); if (ProgramedFlag[Blck*(BlockSize+1)*(SegmentNum+1) +Page_pom*(SegmentNum+1) + pom_seg] ==0 && ProgramedFlag[Blck*(BlockSize+1)*(SegmentNum+1) +Page_pom*(SegmentNum+1) + pom_seg1] ==0 && CashBuffData[i] != -1) memory_features_i0.write_mem_w( WrPage * (PageSize + 1) + i, -1 ); if (ProgramedFlag[Blck*(BlockSize+1)*(SegmentNum+1) +(Page_pom+1)*(SegmentNum+1)+pom_seg]==0 && ProgramedFlag[Blck*(BlockSize+1)*(SegmentNum+1) +(Page_pom+1)*(SegmentNum+1)+pom_seg1]==0 && CashBuffData1[i] != -1) memory_features_i0.write_mem_w( (WrPage + 1) * (PageSize + 1) + i, -1 ); end end end if (rising_edge_PROG_out || rising_edge_XPROG_out) begin R_zd = 1; #1 PGD_ACT = 0; #1 XTR_MPRG = 0; if (Pointer == 256) Pointer = 0; end if (falling_edge_write) begin if ( CLE && ~ALE && Data==8'hFF ) begin set_reset; InvBlockPgms[Blck] = 1; if (XTREM_ACT) back_to_xtrem = 1'b1; else back_to_xtrem = 1'b0; if (XTREM_ACT && ~PGD_ACT) XTR_Pgms_init(WrPage); end else if ( CLE && ~ALE && Data==8'h70 ) STAT_ACT = 1'b1; end IDRD_ACT = 0; if (oe) if (STAT_ACT) Read_status(Blck); end PREL_ERS : begin if (falling_edge_write) begin if ( ALE ) begin Page = AddrCom; cnt_addr = 0; end else if ( CLE && ~ALE && Data==8'hFF ) set_reset; end end A0_ERS : begin if (falling_edge_write) begin if (ALE) begin Blck_pom = AddrCom / 4; cnt_addr = cnt_addr + 1; end else if ( CLE && ~ALE && Data==8'hFF ) set_reset; end end A1_ERS : begin if (falling_edge_write) begin if ( ALE ) begin Blck = AddrCom * 8'h40 + Blck_pom; cnt_addr = cnt_addr + 1; end else if ( CLE && ~ALE && Data==8'hFF ) set_reset; end end A2_ERS : begin if (falling_edge_write) begin if ( CLE && ~ALE && Data==8'hFF ) set_reset; else if ( CLE && ~ALE && Data==8'hD0 ) begin if (~(WPNeg==1'b0) && InvalidBlockTable[Blck] == 0) begin corrupt_flag[Blck] = 1; end if (~XTREM_ACT) BERS_in = 1'b1; else XBERS_in = 1'b1; ERS_ACT = 1'b1; R_zd = 1'b0; Status[6] = 1'b0; end else if ( CLE && ~ALE && XTREM_ACT && Data==8'h11 ) begin R_zd = 1'b0; Status[6] = 1'b0; end else if ( CLE && ~ALE && Data==8'h71 ) begin STAT_M_ACT = 1'b1; BSTATINQ_in = 1'b1; R_zd = 1'b0; Status[6] = 1'b0; end else if (ALE) cnt_addr = cnt_addr + 1; end end BERS_EXEC : begin if (rising_edge_BERS_out) begin if (WPNeg && InvalidBlockTable[Blck] == 0) begin memory_features_i0.erase_mem_w( (Blck ) * (BlockSize + 1) * (PageSize + 1), (Blck + 1) * (BlockSize + 1) * (PageSize + 1) - 1 ); for(i = Blck *(BlockSize+1)*(SegmentNum+1); i < (Blck+1)*(BlockSize+1)*(SegmentNum+1); i=i+1) ProgramedFlag[i] = 1'b0; InvBlock[Blck] = 0; BlockMod[Blck] = 0; PreProgFlag[Blck] = 0; ProgBlock[Blck] = 0; InvBlockPgms[Blck] = 0; corrupt_flag[Blck] = 0; end BERS_in = 1'b0; ERS_ACT = 1'b0; R_zd = 1'b1; Status[6] = 1'b1; end else if (rising_edge_XBERS_out) begin if (WPNeg && InvalidBlockTable[Blck] == 0) begin memory_features_i0.erase_mem_w( (Blck ) * (BlockSize + 1) * (PageSize + 1), (Blck + 1) * (BlockSize + 1) * (PageSize + 1) - 1 ); for(i = Blck *(BlockSize+1)*(SegmentNum+1); i < (Blck+1)*(BlockSize+1)*(SegmentNum+1); i=i+1) ProgramedFlag[i] = 1'b0; InvBlock[Blck] = 0; BlockMod[Blck] = 1; ProgBlock[Blck] = 0; InvBlockPgms[Blck] = 0; corrupt_flag[Blck] = 0; end XBERS_in = 1'b0; ERS_ACT = 1'b0; R_zd = 1'b1; Status[6] = 1'b1; end if (falling_edge_write) begin if ( CLE && ~ALE && Data==8'hFF ) begin InvBlock[Blck] = 1; BERS_in = 1'b0; XBERS_in = 1'b0; set_reset; if (XTREM_ACT) back_to_xtrem = 1'b1; else back_to_xtrem = 1'b0; end else if ( CLE && ~ALE && Data==8'h70 ) STAT_ACT = 1'b1; end IDRD_ACT = 0; if (oe) if (STAT_ACT) Read_status(Blck); end PGD_PREL : begin if (falling_edge_write) begin if (ALE) begin Pom_Address = AddrCom; cnt_addr = 0; end else if( CLE && ~ALE && Data==8'hFF) set_reset; end end A0_PGD: begin if (falling_edge_write) begin if (ALE) begin Page = AddrCom; WrAddr = Pom_Address; cnt_addr = cnt_addr + 1; end else if (CLE && ~ALE && Data==8'hFF) set_reset; end end A1_PGD : begin if (falling_edge_write) begin if ( ALE ) begin Page = (Page + (AddrCom % 4) * 16'h100); Blck_pom = AddrCom / 8'h4; cnt_addr = cnt_addr + 1; end else if (CLE && ~ALE && Data==8'hFF ) set_reset; end end A2_PGD : begin if (falling_edge_write) begin if ( ALE ) begin Blck = AddrCom * 8'h40 + Blck_pom; cnt_addr = cnt_addr + 1; BlckDup = Blck; end else if (CLE && ~ALE && Data==8'hFF ) set_reset; end end CONF_PGD : begin if (falling_edge_write) begin if (CLE && ~ALE && (Data==8'h10 || Data==8'h12)) begin if (~XTREM_ACT) for (i=0; i<=PageSize; i=i+1) CashBuffData[i] = PDBuffer[i]; else begin for (i=0; i<=PageSize; i=i+1) begin CashBuffData[i] = PDBuffer[i]; CashBuffData1[i] = PDBuffer1[i]; end end if (Data == 8'h12 && XTREM_ACT) begin XTR_MPRG = 1'b1; Page =Page/2; end else XTR_MPRG = 1'b0; WrPage = Page + Blck*(BlockSize+1); for (i=0; i<= SegmentNum; i=i+1) SegForProg[i] = 1; if (CLE && ~ALE && (Data==8'h10 || Data==8'h12) && ~PRG_ACT) begin ProgBlock[Blck] = 1; R_zd = 1'b0; Status[6] = 1'b0; end end else if ( CLE && ~ALE && Data==8'hFF) set_reset; else if (ALE) cnt_addr = cnt_addr + 1; end end BSTAT_INQ: begin if (falling_edge_write) begin if (CLE && ~ALE && Data == 8'hFF && ~FP_ACT) set_reset; end if (rising_edge_BSTATINQ_out && ~FP_ACT) begin R_zd = 1; Status[6] = 1; BSTATINQ_in = 0; end end endcase // Output disable control if (RENeg || CENeg) DOut_zd = 8'bz; if ((rising_edge_TR_out || rising_edge_PROG_out || (rising_edge_XPROG_out && ~FP_ACT)) && read && STAT_ACT) Read_status(Blck); end //////////////////////////////////////////////////////////////////////// // Flag Generation process //////////////////////////////////////////////////////////////////////// always @(falling_edge_write, rising_edge_PROG_out, rising_edge_XPROG_out, rising_edge_PRE_PROG_out, rising_edge_RSTDONE) begin: FlagGeneration if (falling_edge_write) begin if ((current_state == DATA_PRG || current_state == CONF_PGD) && CLE && ~ALE && (Data == 8'h10 || Data == 8'h12)) begin if (~PRG_ACT && ~XTREM_ACT) begin #1 PRG_ACT = 1; PROG_in = 1; end else if (~PRG_ACT && XTREM_ACT) begin if (BlockMod[BlckDup] == 0 && current_state == CONF_PGD) begin PRG_ACT = 1; PROG_in = 1; end else begin PRG_ACT = 1; XPROG_in = 1; end end end else if (current_state == A2_ERS && XTREM_ACT && CLE && ~ALE && Data == 8'h11) begin PRE_PROG_in = 1; PRG_ACT = 1; end end if (current_state == PGMS || current_state == PRE_PRG || current_state == UNKNOWN) begin if (rising_edge_PROG_out || rising_edge_XPROG_out) begin PRG_ACT = 0; Status[6] = 1; PROG_in = 0; XPROG_in = 0; if (WPNeg && ~XTREM_ACT && InvBlock[WrPage/(BlockSize+1)] == 0 && InvalidBlockTable[WrPage/(BlockSize+1)] == 0) begin for (j=0; j<=PageSize; j=j+1) begin getSegment(j,pom_seg); if (WrBuffData[j] != -1 && ProgramedFlag[WrPage*(SegmentNum+1)+ (WrPage%(BlockSize+1))*(SegmentNum+1)+pom_seg]== 0) begin memory_features_i0.write_mem_w( WrPage * (PageSize + 1) + j, WrBuffData[j] ); WrBuffData[j]=-1; end end for (j=0; j<= SegmentNum; j=j+1) ProgramedFlag[WrPage*(SegmentNum+1)+ (WrPage%(BlockSize+1))*(SegmentNum+1)+j] = SegForProg[j]; end else if (WPNeg && XTREM_ACT && InvBlock[WrPage/(BlockSize+1)] == 0 && InvalidBlockTable[WrPage/(BlockSize+1)] == 0) begin for (j=0; j<=PageSize; j=j+1) begin Page_pom = WrPage %(BlockSize+1); XgetSegment(j, pom_seg,pom_seg1); if (~PGD_ACT) begin if (ProgramedFlag[WrPage*(SegmentNum+1)+Page_pom *(SegmentNum+1)+pom_seg] == 0 && ProgramedFlag[WrPage*(SegmentNum+1)+Page_pom *(SegmentNum+1)+pom_seg1] == 0 && WrBuffData[j] != -1) XTR_Pgms_data(j,WrPage); end else if (~XTR_MPRG) begin Page_pom = WrPage% (BlockSize+1); if (ProgramedFlag[WrPage*(SegmentNum+1)+Page_pom *(SegmentNum+1)+pom_seg] ==0 && ProgramedFlag[WrPage*(SegmentNum+1)+Page_pom *(SegmentNum+1)+pom_seg1] ==0 && WrBuffData[j] != -1) memory_features_i0.write_mem_w( WrPage * (PageSize + 1) + j, WrBuffData[j] ); if (ProgramedFlag[WrPage*(SegmentNum+1)+(Page_pom+1) *(SegmentNum+1)+pom_seg]==0 && ProgramedFlag[WrPage*(SegmentNum+1)+(Page_pom+1) *(SegmentNum+1)+pom_seg1]==0 && WrBuffData1[j] != -1) memory_features_i0.write_mem_w( (WrPage + 1) * (PageSize + 1) + j, WrBuffData1[j] ); end else begin if (ProgramedFlag[WrPage*(SegmentNum+1)+Page_pom *(SegmentNum+1)+pom_seg] == 0) XTR_MPrg_proc; end end for (j=0; j<= SegmentNum; j=j+1) begin ProgramedFlag[WrPage*(SegmentNum+1)+ (WrPage%(BlockSize+1))*(SegmentNum+1)+j] = SegForProg[j]; if (~XTR_MPRG) ProgramedFlag[WrPage*(SegmentNum+1)+ ((WrPage+1)%(BlockSize+1))*(SegmentNum+1)+j] = SegForProg1[j]; end end end else if (rising_edge_PRE_PROG_out) begin if (WPNeg && XTREM_ACT && InvalidBlockTable[WrPage/(BlockSize+1)] == 0) begin if (InvBlock[WrPage/(BlockSize+1)] == 0 && InvBlockPgms[WrPage/(BlockSize+1)] == 0) begin XTR_PrePrg_proc(WrPage/(BlockSize+1)); PreProgFlag[WrPage/(BlockSize+1)] = 1; end end Status[6] = 1'b1; PRE_PROG_in = 1'b0; PRG_ACT = 1'b0; end else if (falling_edge_write) begin if (CLE && ~ALE && Data == 8'hff && PRG_ACT) begin PROG_in = 0; XPROG_in = 0; PRE_PROG_in = 0; end else if (CLE && ~ALE && Data == 8'hff) PRE_PROG_in = 0; end end else if (current_state == RESET) if (rising_edge_RSTDONE) PRG_ACT = 0; end task getSegment; input integer paddress; output integer seg; integer z; begin for (z=0; z<=SegmentNum; z=z+1) if(paddress >= ssa[z] && paddress <= sea[z]) seg = z; end endtask task XgetSegment; input [31:0] paddress; output [31:0] j; output [31:0] k; integer addr; integer i; begin if (~PGD_ACT) if (paddress*2 < PageSize) addr = paddress*2; else begin addr = paddress*2 - PageSize; Page_pom = Page_pom + 1; end else addr = paddress; for (i=0; i<= SegmentNum; i=i+1) if (addr >= ssa[i] && addr <= sea[i]) j = i; if ((j % 2) ==0 && j<2) k = j + 1; else k = j - 1; end endtask task XTR_PrePrg_proc; input [31:0] Blck; reg [7:0] data_prog; integer i; integer k; begin for (i=Blck * (BlockSize+1)*(PageSize+1); i<=(Blck+1)*(BlockSize+1)*(PageSize+1); i=i+1) begin memory_features_i0.read_mem_w( data_prog, i ); for (k=0; k<=7; k=k+1) if ((k % 2) == 0) data_prog[k] = 1'b1; memory_features_i0.write_mem_w( i, data_prog ); end end endtask task Read_Data; inout [31:0] Addr; inout [31:0] Page; inout [31:0] Blck; reg [7:0] data_tmp; reg [7:0] data_tmp1; reg [7:0] ReadD; integer i; integer j; integer memory_read_data_internal; integer memory_read_data_internal1; begin memory_features_i0.read_mem_w( memory_read_data_internal, Page * (PageSize + 1) + Addr ); if (~XTREM_ACT) begin if (memory_read_data_internal == -1) DOut_zd = 8'bx; else begin if (corrupt_flag[Blck] == 1) DOut_zd = 8'bx; else DOut_zd = memory_read_data_internal; end if (Addr != PageSize) Addr = Addr+1; end else begin if (Addr*2 < PageSize) begin memory_features_i0.read_mem_w( memory_read_data_internal, Page * (PageSize + 1) + Addr*2 ); memory_features_i0.read_mem_w( memory_read_data_internal1, Page * (PageSize + 1) + Addr*2 + 1 ); if (memory_read_data_internal != -1 && memory_read_data_internal1 != -1) begin data_tmp = memory_read_data_internal1; data_tmp1= memory_read_data_internal; i = 0; j = 0; while (i <= 7) begin if ((i % 2) !=0) begin ReadD[j] = data_tmp1[i]; ReadD[j+4] = data_tmp[i]; j = j + 1; end i = i + 1; end if (corrupt_flag[Blck] == 0) DOut_zd = ReadD; end else DOut_zd = 8'bx; end else begin memory_features_i0.read_mem_w( memory_read_data_internal, (Page + 1) * (PageSize + 1) + (Addr*2 - PageSize) ); memory_features_i0.read_mem_w( memory_read_data_internal1, (Page + 1) * (PageSize + 1) + (Addr*2 - (PageSize+1)) ); if (memory_read_data_internal != -1 && memory_read_data_internal1 != -1) begin data_tmp = memory_read_data_internal; data_tmp1= memory_read_data_internal1; i = 0; j = 0; while (i <= 7) begin if ((i % 2) !=0) begin ReadD[j] = data_tmp1[i]; ReadD[j+4] = data_tmp[i]; j = j + 1; end i = i + 1; end if (corrupt_flag[Blck] == 0) DOut_zd = ReadD; end else DOut_zd = 8'bx; end if (corrupt_flag[Blck] == 1) DOut_zd = 8'bx; if (Addr != PageSize) Addr = Addr+1; end end endtask task Read_status; input [31:0] Blck; begin if ((PreProgFlag[Blck] == 1 && ProgBlock[Blck] == 0) || BlockMod[Blck] == 1) Status[2] = 1'b1; else Status[2] = 1'b0; DOut_zd = Status; end endtask task Read_StatMode; input [31:0] Blck; begin DOut_zd[7:0] = 0; if ((PreProgFlag[Blck] == 1 && ProgBlock[Blck] == 0) || BlockMod[Blck] == 1) DOut_zd[2] = 1'b1; else DOut_zd[2] = 1'b0; end endtask task XTR_Pgms_init; input [31:0] Page; integer i; begin if (WPNeg) for(i=0; i<=PageSize; i=i+1) begin if (CashBuffData[i] != -1 && (i*2 < PageSize)) begin memory_features_i0.write_mem_w( Page * (PageSize + 1) + i*2, -1); memory_features_i0.write_mem_w( Page * (PageSize + 1) + i*2 + 1, -1); end else if (CashBuffData[i] != -1 && (i*2 > PageSize)) begin memory_features_i0.write_mem_w( (Page + 1) * (PageSize + 1) + (i*2 - PageSize), -1); memory_features_i0.write_mem_w( (Page + 1) * (PageSize + 1) + (i*2 - (PageSize+1)), -1); end end end endtask task XTR_Pgms_data; input [31:0] i; input [31:0] Page; reg [7:0] data_tmp; reg [7:0] data_tmp1; reg [7:0] data_reg; integer k; integer j; begin k = 0; if (WrBuffData[i] != -1 && (i*2 < PageSize)) begin memory_features_i0.read_mem_w( data_tmp, Page * (PageSize + 1) + i*2 ); memory_features_i0.read_mem_w( data_tmp1, Page * (PageSize + 1) + i*2 + 1 ); data_reg = WrBuffData[i]; for (j=0; j<=7; j=j+1) begin if ((j % 2) !=0) begin data_tmp[j] = data_reg[k]; data_tmp1[j] = data_reg[k+4]; k = k + 1; end else begin data_tmp[j] = data_tmp[j]; data_tmp1[j] = data_tmp1[j]; end end memory_features_i0.write_mem_w( Page * (PageSize + 1) + i*2, data_tmp ); memory_features_i0.write_mem_w( Page * (PageSize + 1) + i*2 + 1, data_tmp1 ); end else if (WrBuffData[i] != -1 && (i*2 > PageSize)) begin memory_features_i0.read_mem_w( data_tmp, (Page + 1)*(PageSize + 1) + (i*2 - (PageSize + 1)) ); memory_features_i0.read_mem_w( data_tmp1, (Page + 1) * (PageSize + 1) + (i*2 - PageSize ) ); data_reg = WrBuffData[i]; for (j=0; j<=7; j=j+1) begin if ((j % 2) !=0) begin data_tmp[j] = data_reg[k]; data_tmp1[j] = data_reg[k+4]; k = k + 1; end else begin data_tmp[j] = data_tmp[j]; data_tmp1[j] = data_tmp1[j]; end end memory_features_i0.write_mem_w( (Page + 1) * (PageSize + 1) + (i*2 - PageSize), data_tmp1 ); memory_features_i0.write_mem_w( (Page + 1) * (PageSize + 1) + (i*2 -(PageSize + 1)), data_tmp ); end end endtask task XTR_MPrg_proc; reg [7:0] data_tmp; reg [7:0] data_tmp1; reg [7:0] data_tmp2; integer k; integer i; integer inv; begin inv = 0; k = 0; i = 0; if (j*2 < PageSize && WrBuffData[j*2+1] != -1 && WrBuffData[j*2] != -1) begin data_tmp = WrBuffData[j*2+1]; data_tmp1 = WrBuffData[j*2]; inv = 1; end else if (j*2 > PageSize && WrBuffData1[j*2 - PageSize] != -1 && WrBuffData1[j*2 - (PageSize+1)] != -1) begin data_tmp = WrBuffData1[j*2 - PageSize]; data_tmp1 = WrBuffData1[j*2- (PageSize+1)]; inv = 1; end if (inv == 1) begin while (i <= 7) begin if ((i % 2) !=0) begin data_tmp2[k] = data_tmp1[i]; data_tmp2[k+4] = data_tmp[i]; k = k + 1; end i = i + 1; end memory_features_i0.write_mem_w( WrPage*(PageSize+1)+j, data_tmp2 ); end end endtask task set_reset; begin STAT_ACT = 1'b0; RSTSTART = 1'b1; RSTSTART <= #1 1'b0; R_zd = 1'b0; Pointer = 0; end endtask always @(negedge write) begin falling_edge_write = 1; #1 falling_edge_write = 0; end always @(posedge reseted) begin rising_edge_reseted = 1; #1 rising_edge_reseted = 0; end always @(posedge PROG_out) begin rising_edge_PROG_out = 1; #1 rising_edge_PROG_out = 0; end always @(posedge XPROG_out) begin rising_edge_XPROG_out = 1; #1 rising_edge_XPROG_out = 0; end always @(posedge PRE_PROG_out) begin rising_edge_PRE_PROG_out = 1; #1 rising_edge_PRE_PROG_out = 0; end always @(posedge read) begin rising_edge_read = 1; #1 rising_edge_read = 0; end always @(posedge RSTDONE) begin rising_edge_RSTDONE = 1; #1 rising_edge_RSTDONE = 0; end always @(posedge TR_out) begin rising_edge_TR_out = 1; #1 rising_edge_TR_out = 0; end always @(posedge TRPRE_out) begin rising_edge_TRPRE_out = 1; #1 rising_edge_TRPRE_out = 0; end always @(posedge BERS_out) begin rising_edge_BERS_out = 1; #1 rising_edge_BERS_out = 0; end always @(posedge XBERS_out) begin rising_edge_XBERS_out = 1; #1 rising_edge_XBERS_out = 0; end always @(posedge BSTATINQ_out) begin rising_edge_BSTATINQ_out = 1; #1 rising_edge_BSTATINQ_out = 0; end reg BuffInR; wire BuffOutR; BUFFER BUFR (BuffOutR , BuffInR); initial begin BuffInR = 1'b1; end always @(posedge BuffOutR) begin WER_01 = $time; end reg BuffInRE, BuffInCE, BuffInALE, BuffInREid; wire BuffOutRE, BuffOutCE, BuffOutALE, BuffOutREid; BUFFER BUFRENeg (BuffOutRE, BuffInRE); BUFFER BUFRENegid (BuffOutREid, BuffInREid); BUFFER BUFCENeg (BuffOutCE, BuffInCE); BUFFER BUFALE (BuffOutALE, BuffInALE); initial begin BuffInRE = 1'b1; BuffInREid = 1'b1; BuffInCE = 1'b1; BuffInALE = 1'b1; end time CEDQ_t, REDQ_t, ALEDQ_t, REDQ_tid ; time REDQ_01, CEDQ_01, ALEDQ_01, REDQ_01id; time CENeg_event, RENeg_event, ALE_event; always @(posedge BuffOutRE) begin REDQ_01 = $time; end always @(posedge BuffOutREid) begin REDQ_01id = $time; end always @(posedge BuffOutCE) begin CEDQ_01 = $time; end always @(BuffOutALE) begin ALEDQ_01 = $time; end always @(negedge CENeg) begin CENeg_event = $time; end always @(negedge RENeg) begin RENeg_event = $time; end always @(negedge ALE) begin ALE_event = $time; end always @(DOut_zd) begin : OutputGen if (DOut_zd[0] !== 1'bz) begin CEDQ_t = CENeg_event + CEDQ_01; REDQ_t = RENeg_event + REDQ_01; REDQ_tid = RENeg_event + REDQ_01id; ALEDQ_t = ALE_event + ALEDQ_01; if (noidread) begin tdp_CE = ((CEDQ_t >= REDQ_t) && ( CEDQ_t > $time)); tdp_RE = ((REDQ_t > CEDQ_t) && ( REDQ_t > $time)); end else if (idread) begin tdp_CE = ((CEDQ_t > REDQ_tid) && (CEDQ_t > ALEDQ_t) && (CEDQ_t > $time)); tdp_RE = ((REDQ_tid >= CEDQ_t) && (REDQ_tid >= ALEDQ_t) && (REDQ_tid > $time)); tdp_AL = ((ALEDQ_t >= CEDQ_t) && (ALEDQ_t >= REDQ_tid) && (ALEDQ_t > $time)); end DOut_pass = DOut_zd; end end always @(DOut_zd) begin if (DOut_zd[0] === 1'bz) begin disable OutputGen; tdp_CE = 1'b1; tdp_RE = 1'b1; tdp_AL = 1'b1; DOut_pass <= DOut_zd; end 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 = 128; parameter list_size = 20'h84000; // memory initial data value parameter MaxData = 8'hFF; // 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 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 // ------------------------------------------------------------------------- // ---------------- the end of memory management section ------------- // ------------------------------------------------------------------------- endmodule