////////////////////////////////////////////////////////////////////////////// // File name : hy27ss16121m.vhd ////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2004 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 N.Makljenovic 04 Oct 18 initial version ////////////////////////////////////////////////////////////////////////////// // PART DESCRIPTION: // // Library: FLASH // Technology: Nand Technology Flash memory // Part: hy27ss16121m // // Description: 512Mbit (32M x16-Bit) NAND Flash Memory // ////////////////////////////////////////////////////////////////////////////// // Known Bugs: // ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // MODULE DECLARATION // ////////////////////////////////////////////////////////////////////////////// `timescale 1 ns/1 ns module hy27ss16121m ( IO15 , IO14 , IO13 , IO12 , IO11 , IO10 , IO9 , IO8 , IO7 , IO6 , IO5 , IO4 , IO3 , IO2 , IO1 , IO0 , CENeg , ALE , RENeg , WENeg , CLE , WPNeg , RBNeg ); //////////////////////////////////////////////////////////////////////// // Port / Part Pin Declarations //////////////////////////////////////////////////////////////////////// input CENeg ; input ALE ; input RENeg ; input WENeg ; input CLE ; input WPNeg ; inout IO15 ; inout IO14 ; inout IO13 ; inout IO12 ; inout IO11 ; inout IO10 ; inout IO9 ; inout IO8 ; inout IO7 ; inout IO6 ; inout IO5 ; inout IO4 ; inout IO3 ; inout IO2 ; inout IO1 ; inout IO0 ; output RBNeg; // port signals declaration wire CENeg ; wire ALE ; wire RENeg ; wire WENeg ; wire CLE ; wire WPNeg ; wire IO15 ; wire IO14 ; wire IO13 ; wire IO12 ; wire IO11 ; wire IO10 ; wire IO9 ; wire IO8 ; wire IO7 ; wire IO6 ; wire IO5 ; wire IO4 ; wire IO3 ; wire IO2 ; wire IO1 ; wire IO0 ; wire RBNeg ; // interconnect path delay signals wire IO15_ipd ; wire IO14_ipd ; wire IO13_ipd ; wire IO12_ipd ; wire IO11_ipd ; wire IO10_ipd ; wire IO9_ipd ; wire IO8_ipd ; wire IO7_ipd ; wire IO6_ipd ; wire IO5_ipd ; wire IO4_ipd ; wire IO3_ipd ; wire IO2_ipd ; wire IO1_ipd ; wire IO0_ipd ; wire ALE_ipd ; wire RENeg_ipd ; wire WENeg_ipd ; wire CENeg_ipd ; wire CLE_ipd ; wire WPNeg_ipd ; wire [15 : 0 ] IOIn; assign IOIn = {IO15_ipd, IO14_ipd, IO13_ipd, IO12_ipd, IO11_ipd, IO10_ipd, IO9_ipd, IO8_ipd, IO7_ipd, IO6_ipd, IO5_ipd, IO4_ipd, IO3_ipd, IO2_ipd, IO1_ipd, IO0_ipd }; wire [15 : 0 ] IOOut; assign IOOut ={IO15, IO14, IO13, IO12, IO11, IO10, IO9, IO8, IO7, IO6, IO5, IO4, IO3, IO2, IO1, IO0 }; // internal delays reg RDone_in ; reg RDone ; // Device Read Buffer done reg WDone_in ; reg WDone ; // Device Page write done reg EDone_in ; reg EDone ; // Device Block erase reg RReset_in ; reg RReset ; // Device reset during write reg WReset_in ; // read buffer reg WReset ; // Device reset during program reg EReset_in ; reg EReset ; // Device reset during erase reg Cache_in ; reg Cache ; reg CDone_in ; reg CDone ; // Device Cache Done wire IO15_zd; wire IO14_zd; wire IO13_zd; wire IO12_zd; wire IO11_zd; wire IO10_zd; wire IO9_zd; wire IO8_zd; wire IO7_zd; wire IO6_zd; wire IO5_zd; wire IO4_zd; wire IO3_zd; wire IO2_zd; wire IO1_zd; wire IO0_zd; wire IO15_pass; wire IO14_pass; wire IO13_pass; wire IO12_pass; wire IO11_pass; wire IO10_pass; wire IO9_pass; wire IO8_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; reg [15 : 0] IOOut_zd; assign {IO15_zd, IO14_zd, IO13_zd, IO12_zd, IO11_zd, IO10_zd, IO9_zd, IO8_zd, IO7_zd, IO6_zd, IO5_zd, IO4_zd, IO3_zd, IO2_zd, IO1_zd, IO0_zd } = IOOut_zd; reg [15 : 0] IOOut_pass ; assign {IO15_pass, IO14_pass, IO13_pass, IO12_pass, IO11_pass, IO10_pass, IO9_pass, IO8_pass, IO7_pass, IO6_pass, IO5_pass, IO4_pass, IO3_pass, IO2_pass, IO1_pass, IO0_pass } = IOOut_pass; parameter mem_file_name = "none"; parameter bbl_file_name = "none"; parameter UserPreload = 0; parameter SeqRow_en = 0; parameter TimingModel = "DefaultTimingModel"; parameter PartID = "hy27ss16121m"; parameter MaxData = 16'hFFFF; // 65535; parameter BlMSize = 8192; // block Memory size parameter BlSSize = 256; // block Spare size parameter BlNum = 4096; parameter PgNum = 32; parameter PgMSize = 256; parameter PgSSize = 8; // powerup reg PoweredUp = 0; // Write Commnad Signal reg WCmd = 0; // Write Address Signal reg WAddr = 0; // Write Data Signal reg WData = 0; // Write Data Signal reg RData = 0; reg ready_reset = 0; reg read_busy = 0; reg page_busy = 0; reg rd_start = 0; reg Last_st; //Address integer Address =0; integer Bla =0; integer Page =0; integer mem_ind=0; integer spr_ind=0; integer mem_ind_t =0; integer spr_ind_t =0; integer Data_tmp ; integer addr_cnt =0; reg [24:0] Address_tmp=0; integer D_tmp ; reg [7:0] Status_reg = 8'h00; reg PointMain = 1; reg RBNeg_zd = 1'b1; integer Bl_wr =0 ; integer Bla_cb =0 ; integer Page_cb =0 ; integer Page_wr =0 ; integer buf_cnt =0 ; integer buf_pcnt =0 ; integer BL_erase =0 ; integer Mem [0:(BlNum*PgNum*PgMSize)-1]; integer SprMem [0:(BlNum*PgNum*PgSSize)-1]; integer PageMBuf[PgMSize-1:0]; integer PageSBuf[PgSSize-1:0]; integer TempMBuf[PgMSize-1:0] ; integer TempSBuf[PgSSize-1:0] ; integer ProgMPag[BlNum*PgNum-1:0] ; integer ProgSPag[BlNum*PgNum-1:0] ; integer BadPage[0:BlNum*PgNum-1] ; reg Prog_cont; reg FROMCE = 1; reg FROMRE = 1; reg command_valid; time CEIO_01, REIO_01; time tdevice_Cache =0; event set_buf; event WDone_ev; event EDone_ev; event state_ev; event Pow_ev; reg Viol; wire RD_ES; reg RD_ES_tmp; assign RD_ES = RD_ES_tmp; wire CENeg_width_EN; assign CENeg_width_EN = WENeg & ~CLE & ~ALE; /////////////////////////////////////////////////////////////////////////////// //Interconnect Path Delay Section /////////////////////////////////////////////////////////////////////////////// buf (IO15_ipd, IO15); buf (IO14_ipd, IO14); buf (IO13_ipd, IO13); buf (IO12_ipd, IO12); buf (IO11_ipd, IO11); buf (IO10_ipd, IO10); buf (IO9_ipd, IO9); buf (IO8_ipd, IO8); buf (IO7_ipd, IO7); buf (IO6_ipd, IO6); buf (IO5_ipd, IO5); buf (IO4_ipd, IO4); buf (IO3_ipd, IO3); buf (IO2_ipd, IO2); buf (IO1_ipd, IO1); buf (IO0_ipd, IO0); buf (CENeg_ipd , CENeg ); buf (ALE_ipd , ALE ); buf (RENeg_ipd , RENeg ); buf (WENeg_ipd , WENeg); buf (CLE_ipd , CLE); buf (WPNeg_ipd , WPNeg); /////////////////////////////////////////////////////////////////////////////// // ProPagetion delay Section /////////////////////////////////////////////////////////////////////////////// nmos (IO15, IO15_pass , 1); nmos (IO14, IO14_pass , 1); nmos (IO13, IO13_pass , 1); nmos (IO12, IO12_pass , 1); nmos (IO11, IO11_pass , 1); nmos (IO10, IO10_pass , 1); nmos (IO9 , IO9_pass , 1); nmos (IO8 , IO8_pass , 1); 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 (RBNeg, 1'b0 , ~RBNeg_zd); ///////////////////////////////////////////// // Timing check and proPagetion delay section ///////////////////////////////////////////// specify // tipd delays: interconnect path delays , mapped to input port delays. // In Verilog is not necessary to declare any tipd_ delay variables, // they can be taken from SDF file // With all the other delays real delays would be taken from SDF file // tpd delays specparam tpd_CENeg_IO0 =1; //tCE specparam tpd_RENeg_IO0 =1; specparam tpd_RENeg_RBNeg =1; //tsetup delays specparam tsetup_IO0_WENeg =1; specparam tsetup_ALE_WENeg =1; specparam tsetup_CLE_WENeg =1; specparam tsetup_CENeg_WENeg =1; specparam tsetup_IO0_RENeg =1; specparam tsetup_ALE_RENeg_RD_ES_0 =1; specparam tsetup_ALE_RENeg_RD_ES_1 =1; specparam tsetup_CLE_RENeg =1; //thold delays specparam thold_IO0_WENeg =1; specparam thold_ALE_WENeg =1; specparam thold_CLE_WENeg =1; specparam thold_CENeg_WENeg =1; specparam thold_RENeg_WENeg =1; specparam thold_RENeg_RBNeg =1; //tpw values specparam tpw_WENeg_negedge =1; specparam tpw_WENeg_posedge =1; specparam tpw_RENeg_negedge =1; specparam tpw_RENeg_posedge =1; specparam tpw_CENeg_posedge =1; // tdevice values: values for internal delays specparam tdevice_RDone =12000; // 12 us; specparam tdevice_WDone =500000; // 500 us; specparam tdevice_EDone =3000000; // 3 ms; specparam tdevice_CDone =3000; // 3 us; specparam tdevice_RReset =5000; // 5 us; specparam tdevice_WReset =10000; // 10 us; specparam tdevice_EReset =500000; // 500 us; /////////////////////////////////////////////////////////////////////////////// // Input Port Delays don't require Verilog description /////////////////////////////////////////////////////////////////////////////// // Path delays // /////////////////////////////////////////////////////////////////////////////// if (FROMCE) (CENeg => IO0) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO1) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO2) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO3) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO4) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO5) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO6) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO7) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO8) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO9) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO10) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO11) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO12) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO13) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO14) = tpd_CENeg_IO0; if (FROMCE) (CENeg => IO15) = tpd_CENeg_IO0; if (FROMRE) (RENeg => IO0) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO1) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO2) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO3) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO4) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO5) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO6) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO7) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO8) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO9) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO10) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO11) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO12) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO13) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO14) = tpd_RENeg_IO0; if (FROMRE) (RENeg => IO15) = tpd_RENeg_IO0; (RENeg => RBNeg) = tpd_RENeg_RBNeg; (WENeg => RBNeg) = tpd_RENeg_RBNeg; $setup (IO0 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO1 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO2 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO3 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO4 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO5 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO6 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO7 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO8 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO9 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO10 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO11 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO12 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO13 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO14 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (IO15 , posedge WENeg &&& ~CLE, tsetup_IO0_WENeg, Viol); $setup (ALE , negedge WENeg&&&~ALE, tsetup_ALE_WENeg, Viol); $setup (CENeg , negedge WENeg&&&~CENeg, tsetup_CENeg_WENeg, Viol); $setup (CLE , negedge WENeg&&&~CLE, tsetup_CLE_WENeg, Viol); $setup (ALE , negedge RENeg &&& RD_ES == 0, tsetup_ALE_RENeg_RD_ES_0, Viol); $setup (ALE , negedge RENeg &&& RD_ES == 1, tsetup_ALE_RENeg_RD_ES_1, Viol); $setup (CLE , negedge RENeg, tsetup_CLE_RENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO0, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO1, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO2, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO3, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO4, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO5, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO6, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO7, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO8, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO9, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO10, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO11, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO12, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO13, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO14, thold_IO0_WENeg, Viol); $hold (posedge WENeg &&& ~CLE , IO15, thold_IO0_WENeg, Viol); $hold (posedge WENeg&&&~ALE , ALE, thold_ALE_WENeg, Viol); $hold (posedge WENeg&&&~CLE , CLE, thold_CLE_WENeg, Viol); $hold (posedge WENeg&&&~CENeg , CENeg, thold_CENeg_WENeg, Viol); $hold (posedge WENeg , RENeg, thold_RENeg_WENeg, Viol); $hold (posedge RBNeg , RENeg, thold_RENeg_RBNeg, Viol); $width (posedge WENeg, tpw_WENeg_posedge); $width (negedge WENeg, tpw_WENeg_negedge); $width (posedge RENeg, tpw_RENeg_posedge); $width (negedge RENeg, tpw_RENeg_negedge); $width (posedge CENeg &&& CENeg_width_EN, tpw_CENeg_posedge); endspecify /////////////////////////////////////////////////////////////////////////////// // Main Behavior Block / /////////////////////////////////////////////////////////////////////////////// // CommandState FSM states parameter POWER_UP =4'd0; parameter PROGRAM_START =4'd1; parameter ERASE =4'd2; parameter PAGE_PROGRAM =4'd3; parameter COPY_BACK_PROGRAM =4'd5; parameter COPY_BACK =4'd6; parameter CACHE_PROGRAM =4'd7; parameter BLOCK_ERASE =4'd8; parameter CACHE_START =4'd9; parameter RESET_C =4'd10; reg [3:0] CommandState=0; reg [3:0] LastState; parameter READ_A =4'd0; parameter READ_C =4'd1; parameter READ_ELECTRONIC =4'd2; parameter READ_STATUS =4'd3; parameter RESET_R =4'd4; reg [3:0] ReadState=0; //Bus cycle states parameter CommandState_Input =3'd0; parameter Address_Input =3'd1; parameter Data_Input =3'd2; parameter Data_Output =3'd3; parameter Write_Protect =3'd4; parameter Standby =3'd5; parameter MemorySp =1'd0; parameter SpareSp =1'd1; reg [3:0] BusCycle; integer CommandData; integer ReadSpace =1'd0; // preload initial begin: InitMemory integer i; integer bl_t; integer pg_t; for (i=0;i<(BlNum*PgNum*PgMSize-1);i=i+1) Mem[i] =MaxData; for (i=0;i<=(BlNum*PgNum*PgSSize-1);i=i+1) SprMem[i] = MaxData; for (i=0;i<=(BlNum*PgNum-1);i=i+1) BadPage[i] = 0; // - Memory preload // h727ss16121m.mem memory file // // - comment // @aaa - stands for sector address // dd -
is wrod to be written at Mem(aa++) // (aa is incremented at every load) if (UserPreload && mem_file_name != "none") $readmemh(mem_file_name,Mem); // - Memory preload // h727ss16121m.mem memory file // // - comment // @aaa - stands for sector address // dd - is bit that sign in bad page memory(aaaa++) and // value different form FFFF in appropriate location of spare memory // (aaaa is incremented at every load) if (UserPreload && bbl_file_name != "none") $readmemh(bbl_file_name,BadPage); for (i=0;i Pow_ev; end always @(posedge RDone_in) begin:TRDone1 #tdevice_RDone RDone = RDone_in; end always @(negedge RDone_in) begin:TRDone2 disable TRDone1; #1 RDone = RDone_in; end always @(posedge WDone_in) begin:TWDone1 #tdevice_WDone WDone = WDone_in; end always @(negedge WDone_in) begin:TWDone2 disable TWDone1; #1 WDone = WDone_in; end always @(posedge EDone_in) begin:TEDone1 #tdevice_EDone EDone = EDone_in; end always @(negedge EDone_in) begin:TEDone2 disable TEDone1; #1 EDone = EDone_in; end always @(posedge CDone_in) begin:TCDone1 #tdevice_Cache CDone = CDone_in; end always @(negedge CDone_in) begin:TCDone2 disable TCDone1; #1 CDone = CDone_in; end always @(posedge WReset_in) begin:TWReset1 #tdevice_WReset WReset = WReset_in; end always @(negedge WReset_in) begin:TWReset2 disable TWReset1; #1 WReset = WReset_in; end always @(posedge RReset_in) begin:TRReset1 #tdevice_RReset RReset = RReset_in; end always @(negedge RReset_in) begin:TRReset2 disable TRReset1; #1 RReset = RReset_in; end always @(posedge EReset_in) begin:TEReset1 #tdevice_EReset EReset = EReset_in; end always @(negedge EReset_in) begin:TEReset2 disable TEReset1; #1 EReset = EReset_in; end always @(ReadState) begin if (ReadState == READ_ELECTRONIC) RD_ES_tmp = 1'b1; else RD_ES_tmp = 1'b0; end always @ (posedge WENeg) begin: BusDecodeCycle1 if ((CENeg === 0) && (ALE === 0) && (CLE === 1) && (RENeg === 1)) begin BusCycle = CommandState_Input; WCmd = 1; WCmd <= #1 0; end else if ((CENeg === 0) && (ALE === 1) && (CLE === 0) && (RENeg === 1)) begin BusCycle = Address_Input; WAddr = 1; WAddr <= #1 0; end else if (CENeg === 0 && ALE === 0 && CLE === 0 && RENeg === 1) begin BusCycle = Data_Input; WData = 1; WData <= #1 0; end end always @ (negedge RENeg) begin: BusDecodeCycle2 if ((CENeg === 0) && (ALE === 0) && (CLE === 0) && (WENeg === 1)) begin BusCycle = Data_Output; RData = 1; RData <= #1 0; end end always @ (negedge CENeg) begin: BusDecodeCycle3 if (( RENeg === 0) && (ALE === 0) && (CLE === 0) && (WENeg === 1)) begin BusCycle = Data_Output; RData = 1; RData <= #1 0; end end always @ (posedge WAddr) begin: AddrCycleDecode1 if (RBNeg_zd != 1'b0) begin if (CommandState == RESET_C && addr_cnt == 4) addr_cnt = 0; if (addr_cnt == 0) Address_tmp[7:0] = IOIn[7:0]; else if (addr_cnt == 1) Address_tmp[15:8] = IOIn[7:0]; else if (addr_cnt == 2) Address_tmp[23:16] = IOIn[7:0]; else if (addr_cnt == 3) begin Address_tmp[24] = IOIn[0]; if ((ReadState == READ_A) || (ReadState == READ_C)) begin rd_start = 1; rd_start <= #1 0; end end addr_cnt = (addr_cnt+1); end end always @ (posedge WCmd) begin: AddrCycleDecode2 cmd_valid_task; if (command_valid) addr_cnt = 0; end always@ (addr_cnt) begin : SetAddrProc if (CommandState == RESET_C && addr_cnt == 4) begin Bla = Address_tmp[24 :13]; Page = Address_tmp[12 : 8]; Address = Address_tmp[7 : 0]; end else if (addr_cnt == 3 && (CommandState == ERASE || CommandState == COPY_BACK || CommandState == CACHE_START || CommandState == PROGRAM_START)) begin Bla = Address_tmp[16 : 5]; Page = Address_tmp[4 : 0]; end end reg [3:0] State_tmp; always@(CommandState) begin LastState = State_tmp; State_tmp = CommandState; end always @ (posedge WCmd, posedge RData, posedge WAddr) begin: CommandStateDecode1 if(WCmd) CommandData = IOIn; if (~WPNeg && ((CommandState == ERASE && CommandData == 8'hD0) || ((CommandState == PROGRAM_START || CommandState == CACHE_START) && (CommandData == 8'h10 || CommandData == 8'h15) ) ) ) CommandData = 8'hFF; if (~RReset_in && ~WReset_in && ~EReset_in) begin if (CommandData == 8'hFF && WCmd) begin if (CommandState == RESET_C) begin ready_reset <= 1'b1; ready_reset <= #1 1'b0; end CommandState = RESET_C; ReadState = RESET_R; end else begin case (CommandState) RESET_C, POWER_UP : begin if (RBNeg_zd !== 0 && WCmd) case (CommandData) 8'h00 : begin ReadState = READ_A; CommandState = RESET_C; end 8'h50 : begin ReadState = READ_C; CommandState = RESET_C; end 8'h90 : begin ReadState = READ_ELECTRONIC; CommandState = RESET_C; end 8'h60 : begin CommandState = ERASE; ReadState <= RESET_R; end 8'h80 : begin CommandState = PROGRAM_START; ReadState <= #1 RESET_R; end 8'h8A : begin if (ReadState == READ_A && WCmd) begin CommandState = COPY_BACK; ReadState <= RESET_R; end end endcase if (CommandData == 8'h70) begin ReadState = READ_STATUS; CommandState = RESET_C; end end COPY_BACK: begin if (CommandData == 8'h10 && WCmd) if (2*Bla/BlNum==2*Bla_cb/BlNum) CommandState = COPY_BACK_PROGRAM; else CommandState = RESET_C; end COPY_BACK_PROGRAM : begin if (CommandData == 8'h70 && WCmd) ReadState = READ_STATUS; end PROGRAM_START : begin if (CommandData == 8'h10 && WCmd) CommandState = PAGE_PROGRAM; else if (CommandData == 8'h15) CommandState = CACHE_PROGRAM; end PAGE_PROGRAM : begin if (CommandData == 8'h70 && WCmd) ReadState = READ_STATUS; end CACHE_PROGRAM: begin if (CommandData == 16'h70 && WCmd) ReadState <= READ_STATUS; else if (~CDone_in && CommandData == 8'h80 && WCmd) begin CommandState <= CACHE_START; ReadState <= RESET_R; end end CACHE_START: begin if (CommandData == 8'h10 && WCmd) CommandState = PAGE_PROGRAM; else if (CommandData == 8'h15 && WCmd) CommandState = CACHE_PROGRAM; end ERASE : begin if (CommandData == 8'hD0 && WCmd) CommandState = BLOCK_ERASE; end BLOCK_ERASE: begin if (CommandData == 8'h70 && WCmd) ReadState = READ_STATUS; end endcase end end end always @ (WDone_ev ) begin: CommandStateDecode2 case (CommandState) COPY_BACK_PROGRAM: begin CommandState = RESET_C; end PAGE_PROGRAM, CACHE_PROGRAM: begin if (~CDone_in) CommandState = RESET_C; end endcase end always @ (posedge CDone ) begin: CommandStateDecode3 case (CommandState) PAGE_PROGRAM, CACHE_PROGRAM: begin if (~WDone_in) CommandState = RESET_C; end endcase end always @ (EDone_ev) begin: CommandStateDecode4 case (CommandState) BLOCK_ERASE: begin CommandState = RESET_C; end endcase end always @ (posedge RData ) begin: ReadDecode1 if (ReadState == READ_A && RBNeg_zd !==0) begin ReadMem(ReadSpace); SetAddress(ReadSpace); end else if (ReadState == READ_C && RBNeg_zd !==0) begin ReadMem(ReadSpace); Address = (Address + 1)%PgSSize; end else if (ReadState == READ_ELECTRONIC) Rd_elect_sig; else if (ReadState == READ_STATUS) Read_ST; end always @ ( ReadState ) begin: ReadDecode2 if (ReadState == READ_A) begin ReadSpace = MemorySp; PointMain = 1; end else if ( ReadState == READ_C) begin ReadSpace = SpareSp; Address = Address % PgSSize; PointMain = 0; end else if (ReadState == READ_ELECTRONIC) Address = Address_tmp[7:0]; end always @ (posedge RENeg ) begin: ReadDecode3 if ((CENeg === 0) && (WENeg === 1)) if (Address == 0 && ((ReadState == READ_A && ReadSpace==MemorySp) || ReadState == READ_C)) begin page_busy = 1; page_busy <= #1 0 ; end end always @ (RENeg, WENeg, CENeg) begin: ReadDecode4 if (RENeg || ~WENeg || CENeg) IOOut_zd <= 16'bz; end reg AutoSeq = 1'b0; always @(page_busy) begin : SeqRowCount1 if (SeqRow_en && ~CENeg) AutoSeq = 1'b1; end always @(RDone) begin : SeqRowCount2 if (AutoSeq) if (Page + 1 == PgNum && CommandState == POWER_UP) begin Page = 0; Bla = (Bla +1) % BlNum; end else Page = (Page + 1) % PgNum; AutoSeq = 1'b0; end always @(CENeg) begin : SeqRowCount3 AutoSeq = 1'b0; end always@(rd_start, page_busy) read_busy = rd_start | page_busy; always @ ( posedge read_busy, Pow_ev ) begin: RB_gen1 RDone_in = 1; RBNeg_zd = 0; end time WDone_pos; always@ (posedge WDone_in) WDone_pos = $time; always @ (state_ev) begin: RB_gen2 case (CommandState) PAGE_PROGRAM, COPY_BACK_PROGRAM: begin if (LastState == CACHE_START) begin tdevice_Cache = tdevice_CDone + 2*tdevice_WDone - ($time - WDone_pos)* WDone_in; Prog_cont = 1; CDone_in = 1'b1; end else WDone_in = 1'b1; RBNeg_zd = 1'b0; end BLOCK_ERASE: begin EDone_in = 1'b1; RBNeg_zd = 1'b0; end CACHE_PROGRAM: begin if (LastState == PROGRAM_START) begin tdevice_Cache = tdevice_CDone; WDone_in <= 1'b1; end else begin tdevice_Cache = tdevice_CDone + tdevice_WDone - ($time - WDone_pos)* WDone_in; Prog_cont = 1; end CDone_in = 1'b1; RBNeg_zd = 1'b0; end RESET_C: begin if (WDone_in) begin WDone_in = 1'b0; CDone_in = 1'b0; WReset_in = 1'b1; RBNeg_zd = 1'b0; end else if (EDone_in) begin EDone_in = 1'b0; EReset_in = 1'b1; RBNeg_zd = 1'b0; end end endcase end always@(posedge ready_reset) begin RDone_in = 1'b0; RReset_in = 1'b1; RBNeg_zd = 1'b0; end always @(posedge RDone or posedge EDone or posedge RReset or posedge WReset or posedge EReset) begin: RB_gen3 EReset_in = 1'b0; RReset_in = 1'b0; WReset_in = 1'b0; CDone_in = 1'b0; EDone_in = 1'b0; RDone_in = 1'b0; WDone_in = 1'b0; RBNeg_zd = 1'b1; end always @(posedge CDone) begin: RB_gen4 EReset_in = 1'b0; RReset_in = 1'b0; WReset_in = 1'b0; CDone_in = 1'b0; EDone_in = 1'b0; RDone_in = 1'b0; RBNeg_zd = 1'b1; end always @(posedge WDone) begin: RB_gen5 EReset_in = 1'b0; RReset_in = 1'b0; WReset_in = 1'b0; EDone_in = 1'b0; RDone_in = 1'b0; if (CDone_in) begin if (Prog_cont) begin WDone_in = 1'b0; WDone_in = #2 1'b1; Prog_cont = 0; end else WDone_in = 1'b0; end else begin WDone_in = 1'b0; RBNeg_zd = 1'b1; end end always @ (RBNeg_zd or WPNeg or CommandState, WDone_in) begin: StatusGen1 Status_reg[7] = WPNeg; Status_reg[6] = RBNeg_zd; Status_reg[5] = RBNeg_zd; if (CommandState == CACHE_PROGRAM || CommandState == CACHE_START) begin Status_reg[5] = ~ WDone_in; Status_reg[1] = Last_st; end end always @ (EReset_in, WReset_in, RReset_in) begin: StatusGen2 if (EReset_in || WReset_in || RReset_in) begin Status_reg[6] = 1; Status_reg[0] = 1; end end always @ (posedge WDone_in) begin: StatusGen3 Last_st = Status_reg[0]; Status_reg[0] = BadPage[Bla*PgNum + Page]; end always @ (posedge EDone_in) begin: StatusGen4 integer i; Status_reg[0] = 1'b0; for(i=0; i<=PgNum-1; i= i+1) if (BadPage[Bla*PgNum + i] == 1) Status_reg[0] = 1'b1; end always @ (CommandState) begin: Functional1 integer i; case (CommandState) COPY_BACK: begin Bla_cb = Bla; Page_cb = Page; end COPY_BACK_PROGRAM: begin setBuf_copy; end BLOCK_ERASE: begin mem_ind = (Bla*BlMSize); spr_ind = (Bla*BlSSize); for(i=0;i<(PgMSize*PgNum);i=i+1) Mem[mem_ind+i] = -1; for(i=0;i<(PgSSize*PgNum);i=i+1) SprMem[spr_ind+i] = -1; for(i=0;i state_ev; end always @ (posedge WDone) begin: Functional2 integer i; case (CommandState) COPY_BACK_PROGRAM: begin writeMem; end PAGE_PROGRAM, CACHE_PROGRAM, CACHE_START: begin writeMem; if ((LastState == CACHE_START && (CommandState==PAGE_PROGRAM || CommandState == CACHE_PROGRAM) && Prog_cont) || CommandState == CACHE_START) begin SetBuf; Prog_cont = 1'b0; end end endcase -> WDone_ev; end always@ (set_buf) begin: set_buffer integer i; for (i=0; i EDone_ev; end always @ (posedge WData) begin: Functional4 case (CommandState) PROGRAM_START, CACHE_START: begin if ((buf_pcnt <= PgMSize-1) && PointMain) begin TempMBuf[buf_pcnt] = IOIn; buf_pcnt = buf_pcnt + 1; end else if ((buf_pcnt <= PgMSize + PgSSize - 1) && PointMain) begin TempSBuf[buf_pcnt-PgMSize] = IOIn; buf_pcnt = buf_pcnt + 1; end else if ((buf_pcnt <= PgSSize - 1) && !PointMain) begin TempSBuf[buf_pcnt] = IOIn; buf_pcnt = buf_pcnt + 1; end else begin $display("Page Buffer overload"); end end endcase end task cmd_valid_task; begin CommandData = IOIn[7:0]; if (CommandData == 8'hFF) command_valid = 1'b1; else if ((CommandState == RESET_C || CommandState == POWER_UP) && (CommandData == 8'h00 || CommandData == 8'h50 || CommandData == 8'h90 || CommandData == 8'h70 || CommandData == 8'h60 || CommandData == 8'h80 || (CommandData == 8'h8A && ReadState ==READ_A))) command_valid = 1'b1; else if ((CommandState == COPY_BACK && CommandData == 8'h10) || ((CommandState == PROGRAM_START || CommandState == PROGRAM_START) && (CommandData == 8'h10 || CommandData == 8'h15)) || (CommandState == CACHE_PROGRAM && CommandData == 8'h80) || (CommandState == ERASE && CommandData == 8'hD0)) command_valid = 1'b1; else command_valid = 1'b0; end endtask task ReadMem; input ReadSpace; begin mem_ind = (Bla*BlMSize)+(Page*PgMSize); spr_ind = (Bla*BlSSize)+(Page*PgSSize); if (ReadSpace == MemorySp) if (Mem[mem_ind+Address]== -1) IOOut_zd[15:0] = 16'hxxxx; else IOOut_zd[15:0] = Mem[mem_ind+Address]; else if (SprMem[spr_ind+(Address%PgSSize)]== -1) IOOut_zd[15:0] = 16'hxxxx; else IOOut_zd[15:0] = SprMem[spr_ind+(Address%PgSSize)]; end endtask task SetAddress; inout ReadSpace; begin Address = Address + 1; if (((Address % PgMSize) == 0) && (ReadSpace==MemorySp)) begin ReadSpace = SpareSp; Address = 0; end else if(((Address % PgSSize) == 0) &&(ReadSpace==SpareSp)) begin ReadSpace = MemorySp; Address = 0; end end endtask task Rd_elect_sig; begin if ((Address % PgMSize) == 16'h0000) begin IOOut_zd = 16'h00AD; Address = Address + 1; end else if ((Address % PgMSize) == 16'h01) begin IOOut_zd = 16'h0046; Address = Address + 1; end else IOOut_zd = 16'hxxxx; end endtask task Read_ST; begin IOOut_zd = {8'bZZZZZZZZ, Status_reg}; end endtask task SetBuf; integer i; begin mem_ind = (Bla*BlMSize)+(Page*PgMSize); spr_ind = (Bla*BlSSize)+(Page*PgSSize); if (PointMain) begin for(i=0;i set_buf; Prog_cont = 1'b0; end endtask task setBuf_copy; integer i; begin mem_ind = (Bla*BlMSize)+(Page*PgMSize); spr_ind = (Bla*BlSSize)+(Page*PgSSize); mem_ind_t = (Bla_cb*BlMSize)+(Page_cb*PgMSize); spr_ind_t = (Bla_cb*BlSSize)+(Page_cb*PgSSize); for(i=0;i= REIO_t) && (CEIO_t >= $time)); FROMRE = ((REIO_t > CEIO_t) && (REIO_t >= $time)); IOOut_pass[15:0] = 16'hz; if(FROMCE && ~FROMRE) begin #(CEIO_t - $time); end IOOut_pass[15:0] = IOOut_zd[15:0]; end end always @(IOOut_zd) begin if (IOOut_zd[0] === 1'bz) begin disable OutputGen; FROMCE = 1'b1; FROMRE = 1'b1; if (CENeg_posEvent == RENeg_posEvent) FROMRE = 1'b0; IOOut_pass <= IOOut_zd; end end endmodule module VITALBuf ( OUT,IN); input IN; output OUT; buf ( OUT, IN); endmodule