////////////////////////////////////////////////////////////////////////////// // File name : s30ml128p00.v ////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2007 Free Model Foundry; http://www.FreeModelFoundry.com // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // MODIFICATION HISTORY: // // version: | author: | mod date: | changes made: // V1.0 I.Milutinovic 07 Feb 03 Initial Release // ////////////////////////////////////////////////////////////////////////////// // PART DESCRIPTION: // // Library: FLASH // Technology: FLASH MEMORY // Part: S30ML128P00 // // Description: 128 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 s30ml128p00 ( 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 = "s30ml128p00"; parameter MaxData = 8'hFF; parameter BlockNum = 31; parameter BlockSize = 1023; parameter PageSize = 527; parameter PageNum = 20'h7FFF; parameter InvalidData = 2; parameter SegmentNum = 2; parameter InvBlocksNum = 1; // max number of invalid blocks // If generic Long_Timming is set to 0, you need to uncomment line below // `define SPEEDSIM; // 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; // Mem(Page)(Address) integer Mem[0:(PageSize+1)*(PageNum+1)-1]; // 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 ; 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 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 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 BERS_EXEC =6'h1D; parameter PGD_PREL =6'h20; parameter A0_PGD =6'h21; parameter A1_PGD =6'h22; 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; 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;// 500 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 ms `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 / s30ml128p00 DEVICE SPECIFIC ////////////////////////////////////////////////////////////////// IDArray[4'd0] = 8'h01; IDArray[4'd1] = 8'h73; if (TimingModel == "s30ml128p50tfi50" || TimingModel == "S30ML128P50TFI50") IDArray[4'd2] = 8'h00; else if (TimingModel == "s30ml128p50tfi00" || TimingModel == "S30ML128P50TFI00") IDArray[4'd2] = 8'h01; IDArray[4'd3] = 8'h01; IDArray[4'd4] = 8'h01; end // initialize memory and load preoload files if any initial begin: InitMemory integer i,j,k,s; for (i=0;i<= PageNum;i=i+1) begin for (j=0;j<= PageSize;j=j+1) Mem[i*(PageSize+1)+j]=MaxData; end 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")) begin $readmemh(invblocks_file_name, InvalidBlockTable); end if (UserPreload && !(mem_file_name == "none")) begin //----------------------------------------------------------------- // Memory preload file format for s30ml128p00 //----------------------------------------------------------------- // / - 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 //----------------------------------------------------------------- $readmemh(mem_file_name, Mem); //mark pages that have been programed for (i=0;i<= PageNum;i=i+1) begin for (j=0;j<= PageSize;j=j+1) begin if (Mem[i*(PageSize+1)+j]!==MaxData) begin k = i*(PageSize+1)+j; getSegment(k,segment); ProgramedFlag[i*(SegmentNum+1)+segment] = 1'b1; end end end end s = 0; for (i=0; i<= BlockNum; i=i+1) begin if (InvalidBlockTable[i] == 1) begin Mem[i*(BlockSize+1)*(PageSize+1)+517] = InvalidData; s = s + 1; if (s > InvBlocksNum) $display("Warning: Number of invalid blocks exceeds range"); end end end 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; 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 = 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 = 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 > 3)) || (CLE && ~ALE && cnt_addr > 3)) 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) #1 next_state = IDLE; else if (rising_edge_XPROG_out && ~FP_ACT) #1 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 ( 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) #1 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 = 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 > 3) || (CLE && ~ALE && cnt_addr > 3)) 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 = AddrCom / 4; if ( XTREM_ACT ) Page = 2*(Page + (AddrCom % 4)*16'h100); else Page = (Page + (AddrCom % 4)*16'h100); Address = Pom_Address; PageAddr = Page+Blck*(BlockSize+1); BlockAddr = Blck; for (i=0;i<= PageSize; i=i+1) begin PDBuffer[i] = -1; PDBuffer1[i] = -1; end PGR_ACT = 1; TR_in = 1; R_zd = 0; Status[6] = 0; cnt_addr = cnt_addr + 1; end else if ( CLE && ~ALE && Data==8'hFF ) 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) PDBuffer[i] = Mem[PageAddr*(PageSize+1)+i]; end else if (XTREM_ACT) begin for (i=0;i<= PageSize; i=i+1) begin PDBuffer[i] = Mem[PageAddr*(PageSize+1)+i]; PDBuffer1[i] = Mem[(PageAddr+1)*(PageSize+1)+i]; 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) 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 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 = AddrCom / 4; if ( XTREM_ACT ) Page = 2*(Page + (AddrCom % 4)* 12'h100); else Page = (Page + (AddrCom % 4)* 12'h100); Page_pom = Page; 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 cnt_addr = cnt_addr + 1; 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]) CashBuffData[WrAddr] = Data; 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 for(i = Blck *(BlockSize+1) *(PageSize+1); i < (Blck+1)*(BlockSize+1) *(PageSize+1); i=i+1) Mem[i] = -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) Mem[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) Mem[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) Mem[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) Mem[(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 = AddrCom / 4; Page = Page+(AddrCom % 4)*12'h100; 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 ( CLE && ~ALE && Data==8'hFF ) set_reset; else if ( CLE && ~ALE && Data==8'hD0 ) begin if (~(WPNeg==1'b0) && InvalidBlockTable[Blck] == 0) begin for(i = Blck *(BlockSize+1) *(PageSize+1); i < (Blck+1)*(BlockSize+1) *(PageSize+1); i=i+1) Mem[i] = -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 for(i = Blck *(BlockSize+1) *(PageSize+1); i < (Blck+1)*(BlockSize+1) *(PageSize+1); i=i+1) Mem[i] = MaxData; 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; 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 for(i = Blck *(BlockSize+1) *(PageSize+1); i < (Blck+1)*(BlockSize+1) *(PageSize+1); i=i+1) Mem[i] = MaxData; 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; 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 = AddrCom / 4; BlckDup = Blck; cnt_addr = cnt_addr + 1; 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 == A1_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 Mem[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) Mem[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) Mem[(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 data_prog = Mem[i]; for (k=0; k<=7; k=k+1) if ((k % 2) == 0) data_prog[k] = 1'b1; Mem[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; integer i; integer j; begin if (~XTREM_ACT) begin if (Mem[Page*(PageSize+1)+Addr] != -1) DOut_zd = Mem[Page*(PageSize+1)+Addr]; else DOut_zd = 8'bx; if (Addr != PageSize) Addr = Addr+1; end else begin if (Addr*2 < PageSize) begin if (Mem[Page*(PageSize+1)+(Addr*2)] != -1 && Mem[Page*(PageSize+1)+(Addr*2+1)] != -1) begin data_tmp = Mem[Page*(PageSize+1)+(Addr*2+1)]; data_tmp1= Mem[Page*(PageSize+1)+(Addr*2)]; i = 0; j = 0; while (i <= 7) begin if ((i % 2) !=0) begin DOut_zd[j] = data_tmp1[i]; DOut_zd[j+4] = data_tmp[i]; j = j + 1; end i = i + 1; end end else DOut_zd = 8'bx; end else begin if (Mem[(Page+1)*(PageSize+1)+(Addr*2- PageSize)] != -1 && Mem[(Page+1)*(PageSize+1)+(Addr*2-(PageSize+1))] != -1) begin data_tmp = Mem[(Page+1)*(PageSize+1)+(Addr*2- PageSize)]; data_tmp1= Mem[(Page+1)*(PageSize+1)+(Addr*2-(PageSize+1))]; i = 0; j = 0; while (i <= 7) begin if ((i % 2) !=0) begin DOut_zd[j] = data_tmp1[i]; DOut_zd[j+4] =data_tmp[i]; j = j + 1; end i = i + 1; end end else DOut_zd = 8'bx; end 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 Mem[(Page)*(PageSize+1)+(i*2)] = - 1; Mem[(Page)*(PageSize+1)+(i*2+1)] = - 1; end else if (CashBuffData[i] != -1 && (i*2 > PageSize)) begin Mem[(Page+1)*(PageSize+1)+(i*2- PageSize)] = - 1; Mem[(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 data_tmp = Mem[(Page)*(PageSize+1)+(i*2)]; data_tmp1 = Mem[(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 Mem[(Page)*(PageSize+1)+(i*2)] = data_tmp; Mem[(Page)*(PageSize+1)+(i*2+1)] = data_tmp1; end else if (WrBuffData[i] != -1 && (i*2 > PageSize)) begin data_tmp = Mem[(Page+1)*(PageSize+1)+(i*2- (PageSize+1))]; data_tmp1 = Mem[(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 Mem[(Page+1)*(PageSize+1)+(i*2- PageSize)] = data_tmp1; Mem[(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 Mem[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