/////////////////////////////////////////////////////////////////////////////// // File name : M45PE80.v /////////////////////////////////////////////////////////////////////////////// // 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 Dj.Tanasijevic 04 SEP 28 initial release /////////////////////////////////////////////////////////////////////////////// // PART DESCRIPTION: // // Library: FLASH MEMORY // Technology: CMOS // Part: M45PE80 // // Description: 8Mbit Page Erasable Serial Flash memory // /////////////////////////////////////////////////////////////////////////////// // Known Bugs: // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // MODULE DECLARATION // /////////////////////////////////////////////////////////////////////////////// `timescale 1 ns/1 ns module m45pe80 ( C , D , SNeg , ResetNeg , WNeg , Q ); /////////////////////////////////////////////////////////////////////////////// // Port / Part Pin Declarations /////////////////////////////////////////////////////////////////////////////// input C ; input D ; input SNeg ; input ResetNeg ; input WNeg ; output Q ; // interconnect path delay signals wire C_ipd ; wire D_ipd ; wire SNeg_ipd ; wire ResetNeg_ipd ; wire WNeg_ipd ; // internal delays reg PW_in ; reg PW_out ; reg PP_in ; reg PP_out ; reg PE_in ; reg PE_out ; reg SE_in ; reg SE_out ; reg DP_in ; reg DP_out ; reg RDP_in ; reg RDP_out ; reg VSL_in ; reg VSL_out ; reg PUW_in ; reg PUW_out ; reg Q_zd; parameter UserPreload = 1'b0; parameter mem_file_name = "none"; parameter TimingModel = "DefaultTimingModel"; parameter PartID = "m45pe80"; parameter MaxData = 255; parameter SecSize = 16'hFFFF; parameter SecNum = 15; parameter HiAddrBit = 23; parameter AddrRANGE = 24'hFFFFF; parameter BYTE = 8; parameter ID = 24'h204014; // powerup parameters reg ChipSelectOk; reg WriteOk ; reg PDONE ; //Programming Done reg PSTART ; //Start Programming reg EDONE ; //Erasing Done reg ESTART ; //Start Erasing reg WDONE ; //Writing Done reg WSTART ; //Start writing //Command Register reg write; reg read_out; reg fast_rd = 1'b1; reg rd = 1'b0; //Status reg. reg[7:0] Status_reg = 8'b0; integer SA = 0; // 0 TO SecNum integer Byte_number = 0; //Address integer Address = 0; // 0 - AddrRANGE reg change_addr; // timing check violation reg Viol = 1'b0; integer Mem[0:AddrRANGE]; integer WByte[0:255]; integer AddrLo; integer AddrHi; reg[7:0] old_bit, new_bit; integer old_int, new_int; integer wr_cnt; integer read_cnt = 0; integer read_addr = 0; reg[7:0] data_out; reg[23:0] id_out; reg oe = 1'b0; event oe_event; /////////////////////////////////////////////////////////////////////////////// //Interconnect Path Delay Section /////////////////////////////////////////////////////////////////////////////// buf (C_ipd , C ); buf (D_ipd , D ); buf (SNeg_ipd , SNeg ); buf (ResetNeg_ipd, ResetNeg); buf (WNeg_ipd , WNeg ); /////////////////////////////////////////////////////////////////////////////// // Propagation delay Section /////////////////////////////////////////////////////////////////////////////// nmos (Q , Q_zd , 1); wire check_rd; assign check_rd = rd; wire check_fast_rd; assign check_fast_rd = fast_rd; 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_C_Q =1; specparam tpd_SNeg_Q =1; // tsetup values: setup time specparam tsetup_D_C =1; specparam tsetup_SNeg_C =1; specparam tsetup_WNeg_SNeg =1; specparam tsetup_SNeg_ResetNeg =1; // thold values: hold times specparam thold_D_C =1; specparam thold_SNeg_C =1; specparam thold_WNeg_SNeg =1; // tpw values: pulse width specparam tpw_C_posedge =1; specparam tpw_C_negedge =1; specparam tpw_SNeg_posedge =1; specparam tpw_ResetNeg_negedge =1; specparam tperiod_C_rd =1; specparam tperiod_C_fast_rd =1; // tdevice values: values for internal delays //Page Write Operation specparam tdevice_PW = 25000000; //25 ms; //Page Program Operation specparam tdevice_PP = 5000000; //5 ms; //Page Erase Operation specparam tdevice_PE = 20000000; //20 ms; //Sector Erase Operation specparam tdevice_SE = 1000000000; //5 sec; //SNeg to Deep Power Down mode specparam tdevice_DP = 3000; //3 us; //SNeg to Stand-by mode specparam tdevice_RDP = 30000; //30 us; //VCC (min) to S# Low specparam tdevice_VSL = 30000; //30 us; //Time delay to Write instruction specparam tdevice_PUW = 10000000; //10 ms; /////////////////////////////////////////////////////////////////////////////// // Input Port Delays don't require Verilog description /////////////////////////////////////////////////////////////////////////////// // Path delays // /////////////////////////////////////////////////////////////////////////////// (C => Q) = tpd_C_Q; (SNeg *> Q) = tpd_SNeg_Q; /////////////////////////////////////////////////////////////////////////////// // Timing Violation // /////////////////////////////////////////////////////////////////////////////// $setuphold (posedge C, D, tsetup_D_C, thold_D_C, Viol); $setuphold (posedge C, SNeg, tsetup_SNeg_C, thold_SNeg_C, Viol); $setup (WNeg, negedge SNeg, tsetup_WNeg_SNeg, Viol); $setup (SNeg, posedge ResetNeg, tsetup_WNeg_SNeg, Viol); $hold (posedge SNeg, WNeg, thold_WNeg_SNeg, Viol); $width (posedge SNeg, tpw_SNeg_posedge); $width (negedge ResetNeg, tpw_ResetNeg_negedge); $width (posedge C, tpw_C_posedge); $width (negedge C, tpw_C_negedge); $period(posedge C &&& check_rd, tperiod_C_rd); $period(posedge C &&& check_fast_rd, tperiod_C_fast_rd); $period(negedge C &&& check_rd, tperiod_C_rd); $period(negedge C &&& check_fast_rd, tperiod_C_fast_rd); endspecify /////////////////////////////////////////////////////////////////////////////// // Main Behavior Block // /////////////////////////////////////////////////////////////////////////////// // FSM states parameter IDLE =4'd0; parameter DP_DOWN =4'd1; parameter SECTOR_ER =4'd2; parameter PAGE_ER =4'd3; parameter PAGE_WR =4'd4; parameter PAGE_PG =4'd5; reg [3:0] current_state; reg [3:0] next_state; // Instructions parameter NONE =5'd0; parameter WREN =5'd1; parameter WRDI =5'd2; parameter RDID =5'd3; parameter RDSR =5'd4; parameter READ =5'd5; parameter FAST_READ =5'd6; parameter PW =5'd7; parameter PP =5'd8; parameter PE =5'd9; parameter SE =5'd10; parameter DP =5'd11; parameter RDP =5'd12; reg [4:0] Instruct; //Bus cycle states parameter STAND_BY =3'd0; parameter CODE_BYTE =3'd1; parameter ADDRESS_BYTES =3'd2; parameter DUMMY_BYTES =3'd3; parameter DATA_BYTES =3'd4; reg [2:0] bus_cycle_state; initial begin : Init write = 1'b0; read_out = 1'b0; Address = 0; change_addr = 1'b0; PDONE = 1'b1; PSTART = 1'b0; EDONE = 1'b1; ESTART = 1'b0; WDONE = 1'b1; WSTART = 1'b0; RDP_in = 1'b0; RDP_out = 1'b0; Instruct = NONE; bus_cycle_state = STAND_BY; current_state = IDLE; next_state = IDLE; end // initialize memory initial begin: InitMemory integer i; for (i=0;i<=AddrRANGE;i=i+1) begin Mem[i] = MaxData; end if ((UserPreload) && !(mem_file_name == "none")) begin // Memory Preload // m45pe80.mem, memory preload file // @aaaaa - stands for address // dd -
is byte to be written at Mem(aaaaa++) // (aaaaa is incremented at every load) $readmemh(mem_file_name,Mem); end end initial begin ChipSelectOk = 1'b0; #tdevice_VSL ChipSelectOk = 1'b1; end initial begin WriteOk = 1'b0; #tdevice_PUW WriteOk = 1'b1; end always @(posedge RDP_in) begin:TRDPr #tdevice_RDP RDP_out = RDP_in; end always @(negedge RDP_in) begin:TRDPf #1 RDP_out = RDP_in; end always @(next_state or WriteOk) begin: StateTransition if (WriteOk) current_state = next_state; end // ///////////////////////////////////////////////////////////////////////// // // Instruction cycle decode // ///////////////////////////////////////////////////////////////////////// integer data_cnt = 0; integer addr_cnt = 0; integer code_cnt = 0; integer dummy_cnt = 0; integer bit_cnt = 0; reg[2047:0] Data_in = 2048'b0; reg[7:0] code = 8'b0; reg[7:0] code_in = 8'b0; reg[7:0] Byte_slv = 8'b0; reg[19:0] addr_bytes; reg[23:0] Address_in = 8'b0; always @(negedge SNeg_ipd) begin: Buscycle1 if (bus_cycle_state==STAND_BY) begin bus_cycle_state = CODE_BYTE; Instruct = NONE; write = 1'b1; code_cnt = 0; addr_cnt = 0; data_cnt = 0; dummy_cnt = 0; end end always @(posedge C_ipd) begin: Buscycle2 integer i; if (ResetNeg_ipd) begin case (bus_cycle_state) CODE_BYTE : begin code_in[code_cnt] = D_ipd; code_cnt = code_cnt + 1; if (code_cnt == BYTE) begin for (i=0;i<=7;i=i+1) begin code[i] = code_in[7-i]; end case(code) 8'b00000110 : begin Instruct = WREN; bus_cycle_state = DATA_BYTES; end 8'b00000100 : begin Instruct = WRDI; bus_cycle_state = DATA_BYTES; end 8'b10011111 : begin Instruct = RDID; bus_cycle_state = DATA_BYTES; end 8'b00000101 : begin Instruct = RDSR; bus_cycle_state = DATA_BYTES; end 8'b00000011 : begin Instruct = READ; bus_cycle_state = ADDRESS_BYTES; end 8'b00001011 : begin Instruct = FAST_READ; bus_cycle_state = ADDRESS_BYTES; end 8'b00001010 : begin Instruct = PW; bus_cycle_state = ADDRESS_BYTES; end 8'b00000010 : begin Instruct = PP; bus_cycle_state = ADDRESS_BYTES; end 8'b11011011 : begin Instruct = PE; bus_cycle_state = ADDRESS_BYTES; end 8'b11011000 : begin Instruct = SE; bus_cycle_state = ADDRESS_BYTES; end 8'b10111001 : begin Instruct = DP; bus_cycle_state = DATA_BYTES; end 8'b10101011 : begin Instruct = RDP; bus_cycle_state = DATA_BYTES; end endcase end end ADDRESS_BYTES : begin Address_in[addr_cnt] = D_ipd; addr_cnt = addr_cnt + 1; if (addr_cnt == 3*BYTE) begin for (i=19;i>=0;i=i-1) begin addr_bytes[19-i] = Address_in[i+4]; end Address = addr_bytes; change_addr = 1'b1; #1 change_addr = 1'b0; if (Instruct == FAST_READ) bus_cycle_state = DUMMY_BYTES; else bus_cycle_state = DATA_BYTES; end end DUMMY_BYTES : begin dummy_cnt = dummy_cnt + 1; if (dummy_cnt == BYTE && Instruct == FAST_READ) bus_cycle_state = DATA_BYTES; end DATA_BYTES : begin if (data_cnt > 2047) //In case of PP or PW, if more than 256 bytes are //sent to the device begin if (bit_cnt == 0) begin for (i=0;i<=(255*BYTE-1);i=i+1) begin Data_in[i] = Data_in[i+8]; end end Data_in[2040 + bit_cnt] = D_ipd; bit_cnt = bit_cnt + 1; if (bit_cnt == 8) begin bit_cnt = 0; end data_cnt = data_cnt + 1; end else begin Data_in[data_cnt] = D_ipd; data_cnt = data_cnt + 1; bit_cnt = 0; end end endcase end end always @(negedge C_ipd) begin: Buscycle3 if (bus_cycle_state==DATA_BYTES && (~SNeg_ipd) && ResetNeg_ipd) if (Instruct == READ || Instruct == RDID || Instruct == FAST_READ || Instruct == RDSR) read_out = 1'b1; #1 read_out = 1'b0; end always @(posedge SNeg_ipd) begin: Buscycle4 integer i; integer j; if (bus_cycle_state == DATA_BYTES) begin bus_cycle_state = STAND_BY; if (ResetNeg_ipd && WriteOk) begin case (Instruct) WREN, WRDI, DP, RDP, PE, SE : begin if (data_cnt == 0) write = 1'b0; end RDID : begin write = 1'b0; end PW, PP : begin if ((data_cnt > BYTE) && ((data_cnt % 8) == 0)) begin write = 1'b0; for (i=0;i<=255;i=i+1) begin for (j=7;j>=0;j=j-1) begin Byte_slv[j] = Data_in[(i*8) + (7-j)]; end WByte[i] = Byte_slv; end if (data_cnt > 256*BYTE) Byte_number = 255; else Byte_number = ((data_cnt/8) - 1); end end endcase end end else begin bus_cycle_state = STAND_BY; end end // ///////////////////////////////////////////////////////////////////////// // // Timing control for the Page Write Operation // // start // ///////////////////////////////////////////////////////////////////////// event wdone_event; always @(WSTART) begin if (WSTART && WDONE) begin if (~((~WNeg) && (SA==0))) begin WDONE = 1'b0; ->wdone_event; end end end always @(wdone_event) begin:wdone_process WDONE = 1'b0; #tdevice_PW WDONE = 1'b1; end // ///////////////////////////////////////////////////////////////////////// // // Timing control for the Page program Operation // // start // ///////////////////////////////////////////////////////////////////////// event pdone_event; always @(PSTART) begin if (PSTART && PDONE) begin if (~((~WNeg) && (SA==0))) begin PDONE = 1'b0; ->pdone_event; end end end always @(pdone_event) begin:pdone_process PDONE = 1'b0; #tdevice_PP PDONE = 1'b1; end // ///////////////////////////////////////////////////////////////////////// // // Timing control for the Erase Operations // ///////////////////////////////////////////////////////////////////////// integer cnt_erase = 0; time duration_erase; event edone_event; always @(ESTART) begin: erase if (ESTART && EDONE) begin if (~((~WNeg) && (SA==0))) begin if (Instruct == PE) begin duration_erase = tdevice_PE; end else if (Instruct == SE) begin duration_erase = tdevice_SE; end EDONE = 1'b0; ->edone_event; end end end always @(edone_event) begin : edone_process EDONE = 1'b0; #duration_erase EDONE = 1'b1; end // ///////////////////////////////////////////////////////////////////////// // // Main Behavior Process // // combinational process for next state generation // ///////////////////////////////////////////////////////////////////////// integer sect; always @(negedge write) begin: StateGen1 case (current_state) IDLE : begin if (~write) begin if (Instruct == PW && Status_reg[1]) begin sect = Address / 24'h10000; if (~((~WNeg_ipd) && (sect==0))) next_state = PAGE_WR; end else if (Instruct == PP && Status_reg[1]) begin sect = Address / 24'h10000; if (~((~WNeg_ipd) && (sect==0))) next_state = PAGE_PG; end else if (Instruct == PE && Status_reg[1]) begin sect = Address / 24'h10000; if (~((~WNeg_ipd) && (sect==0))) next_state = PAGE_ER; end else if (Instruct == SE && Status_reg[1]) begin sect = Address / 24'h10000; if (~((~WNeg_ipd) && (sect==0))) next_state = SECTOR_ER; end else if (Instruct == DP) next_state = DP_DOWN; else next_state = IDLE; end end DP_DOWN: begin if (~write) begin if (Instruct == RDP) next_state = IDLE; end end endcase end always @(posedge PDONE) begin: StateGen2 if (current_state==PAGE_PG) begin next_state = IDLE; end end always @(posedge WDONE) begin: StateGen3 if (current_state==PAGE_WR) begin next_state = IDLE; end end always @(posedge EDONE) begin: StateGen4 if (current_state==PAGE_ER || current_state==SECTOR_ER) begin next_state = IDLE; end end // ///////////////////////////////////////////////////////////////////////// // //FSM Output generation and general funcionality // ///////////////////////////////////////////////////////////////////////// always @(posedge read_out) begin if (ResetNeg_ipd == 1'b1 && ChipSelectOk == 1'b1) ->oe_event; end always @(oe_event) begin oe = 1'b1; #1 oe = 1'b0; end always @(Instruct) begin read_cnt = 0; fast_rd = 1; rd = 0; end always @(change_addr) begin if (change_addr) read_addr = Address; end always @(negedge ResetNeg) begin Status_reg[1] = 0; end always @(posedge ResetNeg) begin if (~SNeg) begin $display ("Chip should have been deselected"); $display ("before Reset is de-asserted"); end end always @(posedge RDP_out) begin RDP_in = 0; end always @(oe or current_state) begin case (current_state) IDLE : begin if (oe && RDP_in == 1'b0) begin if (Instruct == RDSR) begin //Read Status Register Q_zd = Status_reg[7-read_cnt]; read_cnt = read_cnt + 1; if (read_cnt == 8) read_cnt = 0; end else if (Instruct == READ || Instruct == FAST_READ) begin //Read Memory array data_out[7:0] = Mem[read_addr]; Q_zd = data_out[7-read_cnt]; read_cnt = read_cnt + 1; if (read_cnt == 8) begin read_cnt = 0; if (read_addr == AddrRANGE) read_addr = 0; else read_addr = read_addr + 1; end end else if (Instruct == RDID) begin // Read ID id_out[23:0] = ID; Q_zd = id_out[23-read_cnt]; read_cnt = read_cnt + 1; if (read_cnt == 24) read_cnt = 0; end end else if (oe && RDP_in == 1'b1) begin $display ("Command results can be corrupted"); Q_zd = 1'bX; read_cnt = read_cnt + 1; if (read_cnt == 8) read_cnt = 0; end end PAGE_WR, PAGE_PG, PAGE_ER, SECTOR_ER: begin if (oe && Instruct == RDSR) begin //Read Status Register Q_zd = Status_reg[7-read_cnt]; read_cnt = read_cnt + 1; if (read_cnt == 8) read_cnt = 0; end end endcase end integer sector; integer WData [0:255]; integer Addr; always @(negedge write) begin : Output_generation integer i; case (current_state) IDLE : begin if (WriteOk) begin if ((RDP_in == 1'b1) && (Instruct != DP)) begin $display ("Command results can be corrupted"); end if (Instruct == WREN) Status_reg[1] = 1'b1; else if (Instruct == WRDI) Status_reg[1] = 1'b0; else if (Instruct == PW && Status_reg[1]) begin sector = Address / 20'h10000; if (~((~WNeg) && (sector==0))) begin WSTART = 1'b1; WSTART <= #1 1'b0; Status_reg[0] = 1'b1; Addr = Address; SA = sector; wr_cnt = Byte_number; for (i=wr_cnt;i>=0;i=i-1) begin if (Viol!=1'b0) WData[i] = -1; else WData[i] = WByte[i]; end end end else if (Instruct == PP && Status_reg[1] == 1'b1) begin sector = Address / 20'h10000; if (~((~WNeg) && (sector==0))) begin PSTART = 1'b1; PSTART <= #1 1'b0; Status_reg[0] = 1'b1; Addr = Address; SA = sector; wr_cnt = Byte_number; for (i=wr_cnt;i>=0;i=i-1) begin if (Viol!=1'b0) WData[i] = -1; else WData[i] = WByte[i]; end end end else if (Instruct == PE && Status_reg[1] == 1'b1) begin sector = Address / 20'h10000; if (~((~WNeg) && (sector==0))) begin ESTART = 1'b1; ESTART <= #1 1'b0; Status_reg[0] = 1'b1; Addr = Address; end end else if (Instruct == SE && Status_reg[1] == 1'b1) begin sector = Address / 20'h10000; if (~((~WNeg) && (sector==0))) begin ESTART = 1'b1; ESTART <= #1 1'b0; Status_reg[0] = 1'b1; Addr = Address; end end end end DP_DOWN: begin if (~write) begin if (Instruct == RDP) RDP_in = 1'b1; end end endcase end always @(current_state or EDONE) begin: ERASE1 integer i; case (current_state) PAGE_ER : begin ADDRHILO_PG(AddrLo, AddrHi, Addr); for (i=AddrLo;i<=AddrHi;i=i+1) begin Mem[i] = -1; end if (EDONE) begin Status_reg[0] = 1'b0; Status_reg[1] = 1'b0; for (i=AddrLo;i<=AddrHi;i=i+1) begin Mem[i] = MaxData; end end end SECTOR_ER : begin ADDRHILO_SEC(AddrLo, AddrHi, Addr); for (i=AddrLo;i<=AddrHi;i=i+1) begin Mem[i] = -1; end if (EDONE) begin Status_reg[0] = 1'b0; Status_reg[1] = 1'b0; for (i=AddrLo;i<=AddrHi;i=i+1) begin Mem[i] = MaxData; end end end endcase end always @(current_state or WDONE) begin: PWR1 integer i, j; if (current_state == PAGE_WR) begin ADDRHILO_PG(AddrLo, AddrHi, Addr); if ((Addr + wr_cnt) > AddrHi) begin for (i=Addr;i<=AddrHi;i=i+1) Mem[i] = -1; for (i=AddrLo;i<=(AddrLo+Addr+wr_cnt-AddrHi-1);i=i+1) Mem[i] = -1; end else begin for (i=Addr;i<=(Addr+wr_cnt);i=i+1) Mem[i] = -1; end if (WDONE) begin Status_reg[0] = 1'b0;//wip Status_reg[1] = 1'b0;// wel if ((Addr + wr_cnt) > AddrHi) begin for (i=Addr;i<=AddrHi;i=i+1) Mem[i] = WData[i-Addr]; for (i=AddrLo;i<=(AddrLo+Addr+wr_cnt-AddrHi-1);i=i+1) Mem[i] = WData[AddrHi-Addr+1+i-AddrLo]; end else begin for (i=Addr;i<=(Addr+wr_cnt);i=i+1) Mem[i] = WData[i-Addr]; end end end end always @(current_state or PDONE) begin: PPG1 integer i, j; if (current_state == PAGE_PG) begin ADDRHILO_PG(AddrLo, AddrHi, Addr); if ((Addr + wr_cnt) > AddrHi) begin for (i=Addr;i<=AddrHi;i=i+1) begin new_int = WData[i-Addr]; old_int = Mem[i]; if (new_int > -1) begin new_bit = new_int; if (old_int > -1) begin old_bit = old_int; for(j=0;j<=7;j=j+1) if (~old_bit[j]) new_bit[j]=1'b0; new_int=new_bit; end WData[i-Addr]= new_int; end else begin WData[i-Addr] = -1; end end for (i=AddrLo;i<=(AddrLo+Addr+wr_cnt-AddrHi-1);i=i+1) begin new_int = WData[AddrHi-Addr+1+i-AddrLo]; old_int = Mem[i]; if (new_int > -1) begin new_bit = new_int; if (old_int > -1) begin old_bit = old_int; for(j=0;j<=7;j=j+1) if (~old_bit[j]) new_bit[j]=1'b0; new_int=new_bit; end WData[AddrHi-Addr+1+i-AddrLo]= new_int; end else begin WData[AddrHi-Addr+1+i-AddrLo] = -1; end end end else begin for (i=Addr;i<=(Addr+wr_cnt);i=i+1) begin new_int = WData[i-Addr]; old_int = Mem[i]; if (new_int > -1) begin new_bit = new_int; if (old_int > -1) begin old_bit = old_int; for(j=0;j<=7;j=j+1) if (~old_bit[j]) new_bit[j]=1'b0; new_int=new_bit; end WData[i-Addr]= new_int; end else begin WData[i-Addr] = -1; end end end if ((Addr + wr_cnt) > AddrHi) begin for (i=Addr;i<=AddrHi;i=i+1) Mem[i] = -1; for (i=AddrLo;i<=(AddrLo+Addr+wr_cnt-AddrHi-1);i=i+1) Mem[i] = -1; end else begin for (i=Addr;i<=(Addr+wr_cnt);i=i+1) Mem[i] = -1; end if (PDONE) begin Status_reg[0] = 1'b0;//wip Status_reg[1] = 1'b0;// wel if ((Addr + wr_cnt) > AddrHi) begin for (i=Addr;i<=AddrHi;i=i+1) Mem[i] = WData[i-Addr]; for (i=AddrLo;i<=(AddrLo+Addr+wr_cnt-AddrHi-1);i=i+1) Mem[i] = WData[AddrHi-Addr+1+i-AddrLo]; end else begin for (i=Addr;i<=(Addr+wr_cnt);i=i+1) Mem[i] = WData[i-Addr]; end end end end // Output Control always @(SNeg_ipd or ResetNeg_ipd) begin //Output Disable Control if (SNeg_ipd || (~ResetNeg_ipd)) Q_zd = 1'bZ; end // Procedure ADDRHILO_SEC task ADDRHILO_SEC; inout AddrLOW; inout AddrHIGH; input Addr; integer AddrLOW; integer AddrHIGH; integer Addr; integer sector; begin sector = Addr / 20'h10000; AddrLOW = sector * 20'h10000; AddrHIGH = sector * 20'h10000 + 20'hFFFF; end endtask // Procedure ADDRHILO_PG task ADDRHILO_PG; inout AddrLOW; inout AddrHIGH; input Addr; integer AddrLOW; integer AddrHIGH; integer Addr; integer page; begin page = Addr / 16'h100; AddrLOW = page * 16'h100; AddrHIGH = page * 16'h100 + 8'hFF; end endtask endmodule