URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [verilog/] [AT26DFxxx.v] - Rev 534
Go to most recent revision | Compare with Previous | Blame | View Log
//-------------------------------------------------------------------------- // This is the property of PERFTRENDS TECHNOLOGIES PRIVATE LIMITED and // possession or use of file has to be with the written LICENCE AGGREMENT // from PERFTRENDS TECHNOLOGIES PRIVATE LIMITED. // //-------------------------------------------------------------------------- // // Project : ATMEL Data Flash Device //-------------------------------------------------------------------------- // File : $RCSfile: AT26DFxxx.v,v $ // Path : $Source: /home/cvs/atmel_flash_dev/design_26x/AT26DFxxx.v,v $ // Author : $ Devi Vasumathy N $ // Created on : $ 13-03-07 $ // Revision : $Revision: 1.8 $ // Last modified by : $Author: devivasumathy $ // Last modified on : $Date: 2007/05/10 05:15:51 $ //-------------------------------------------------------------------------- // Module : AT26DFxxx.v // Description : BFM for devices AT25DF041A, AT26DF081A, // AT26DF161A, AT26DF321 // //-------------------------------------------------------------------------- // // Design hierarchy : _top.v/top_1.v/top_2.v/... // Instantiated Modules : top_1.v, top_2.v //-------------------------------------------------------------------------- // Revision history : // $Log: AT26DFxxx.v,v $ // Revision 1.8 2007/05/10 05:15:51 devivasumathy // Card Memory preload // // Revision 1.7 2007/04/27 09:09:40 devivasumathy // *** empty log message *** // // Revision 1.6 2007/04/17 10:50:59 devivasumathy // Timing verified // // Revision 1.5 2007/04/16 06:24:44 devivasumathy // *** empty log message *** // // Revision 1.4 2007/04/10 09:37:36 devivasumathy // *** empty log message *** // // Revision 1.3 2007/04/09 12:06:09 devivasumathy // *** empty log message *** // // Revision 1.2 2007/04/05 14:45:12 devivasumathy // *** empty log message *** // // Revision 1.1 2007/04/05 11:32:18 devivasumathy // AT26DFx data flash model // //-------------------------------------------------------------------------- `timescale 1ns/10ps //ME added `define def_321 1 //ME added module AT26DFxxx ( CSB, SCK, SI, WPB, `ifdef def_321 `else HOLDB, `endif SO); // ******************************************************************** // // Port Declaration: // ******************************************************************** // input CSB; // Chip Select! input SCK; // Serial Clock input SI; // Serial Input input WPB; // Write Protect! `ifdef def_321 `else input HOLDB; // Hold! `endif output SO; // Serial Output `ifdef def_321 wire HOLDB; `endif parameter DEVICE = "AT25DF041A"; // Device selected parameter PRELOAD = 1; // preload memory with content in MEMORY_FILE parameter MEMORY_FILE = "flash.in"; // Memory pre-load parameter VERBOSE = 1; // ********************************************************************* // //Timing Parameters : // ******************************************************************** // // Fixed parameters parameter fRDLF = 33; // SCK Frequency for read Array (Low freq - 03h opcode) //representation in ns parameter tDIS = 6; // Output Disable time parameter tV = 6; // Output Valid time parameter tOH = 0 ; // Output Hold time parameter tHLQZ = 6 ; // HOLD! Low to Output High-z parameter tHHQX = 6 ; // HOLD! High to Output Low-z parameter tSECP = 20; // Sector Protect Time parameter tSECUP = 20; // Sector Unprotect Time parameter tEDPD = 3000; // Chip Select high to Deep Power-down (3 us) parameter tRDPD = 3000; // Chip Select high to Stand-by Mode parameter tWRSR = 200; // Write Status Register Time parameter tPP = 5000000; // Page Program Time parameter tBLKE4 = 200000000; // Block Erase Time 4-kB parameter tBLKE32 = 600000000; // Block Erase Time 32-kB parameter tCHPEn = 1000000000; // local chip erase time // variable parameters // ******************************************************************** // //parameter tBP = 7000; // Byte Program Time //parameter tBLKE64 = 950000000; // Block Erase Time 64-kB //parameter tCHPE = 3000000000; // Chip Erase Time // this is actual; // due to simulation warning splitted into 2 parameters as tCHPE = tmult * tCHPEn //parameter tmult = 3; // Multiplication factor for chip erase timing parameter tBP = (DEVICE == "AT25DF041A") ? 7000 : (DEVICE == "AT26DF081A") ? 7000 : (DEVICE == "AT26DF161A") ? 7000 : (DEVICE == "AT26DF321") ? 6000 : 7000; parameter tBLKE64 = (DEVICE == "AT25DF041A") ? 950000000 : (DEVICE == "AT26DF081A") ? 950000000 : (DEVICE == "AT26DF161A") ? 950000000 : (DEVICE == "AT26DF321") ? 1000000000 :950000000 ; parameter tmult = (DEVICE == "AT25DF041A") ? 3 : (DEVICE == "AT26DF081A") ? 6 : (DEVICE == "AT26DF161A") ? 12 : (DEVICE == "AT26DF321") ? 36 : 3; //parameter fSCK = 70; // Serial clock (SCK) Frequency in MHz //parameter tSCKH = 6.4; // SCK High time //parameter tSCKL = 6.4; // SCK Low time parameter fSCK = (DEVICE == "AT25DF041A") ? 70 : (DEVICE == "AT26DF081A") ? 70 : (DEVICE == "AT26DF161A") ? 70 : (DEVICE == "AT26DF321") ? 66 : 70; parameter tSCKH = (DEVICE == "AT25DF041A") ? 6.4 : (DEVICE == "AT26DF081A") ? 6.4 : (DEVICE == "AT26DF161A") ? 6.4 : (DEVICE == "AT26DF321") ? 6.8 : 6.4; parameter tSCKL = (DEVICE == "AT25DF041A") ? 6.4 : (DEVICE == "AT26DF081A") ? 6.4 : (DEVICE == "AT26DF161A") ? 6.4 : (DEVICE == "AT26DF321") ? 6.8 : 6.4; // ******************************************************************** // // ********************** Manufacturer ID ********************** // parameter [31:0] MAN_ID = (DEVICE == "AT25DF041A") ? 32'h1F_04_00_00 : (DEVICE == "AT26DF081A") ? 32'h1F_45_01_00 : (DEVICE == "AT26DF161A") ? 32'h1F_46_01_00 : (DEVICE == "AT26DF321") ? 32'h1F_47_00_00 : 32'h1F_04_00_00; // ********* Memory And Access Related Declarations ***************** // parameter BLOCK64 = (DEVICE == "AT25DF041A") ? 8 : // no of 64kB blocks (DEVICE == "AT26DF081A") ? 16 : (DEVICE == "AT26DF161A") ? 32 : (DEVICE == "AT26DF321") ? 64 : 8 ; parameter SECTOR = (DEVICE == "AT25DF041A") ? 11 : // no of sectors (DEVICE == "AT26DF081A") ? 19 : (DEVICE == "AT26DF161A") ? 32 : (DEVICE == "AT26DF321") ? 64 : 11 ; // total memory size = no. of blocks * 64 k bits (i.e each block contains 64 KB) parameter MEMSIZE = BLOCK64 * 64 * 1024; // total memory size reg [7:0] memory [MEMSIZE-1:0]; // memory of selected device reg [7:0] status_reg; // Status register reg [63:0] sector_reg; // Sector protection reg reg [7:0] int_buffer [255:0]; // internal buffer to store data in page programming mode // ****************** ***************** ***************** // // ********* Registers to track the current operation of the device ******** // reg deep_power_down; // Device in Deep Power Down Mode reg status_read; // Status register is being read reg erasing_block4; // 4kB block erase reg erasing_block32; // 32kB block erase reg erasing_block64; // 64kB block erase reg erasing_chip; // chip erase reg rd_dummy; // low/high freq read array reg byte_prog; // Byte/page programming reg seq_byte_prog; // sequential byte programming reg seq_byte_start; // sequential byte programming start intimation // ********* Events to trigger some task based on opcode *********** // event EDPD; // Deep Power-down (enable) event RDPD; // Resume from Deep Power-down event RA; // Read Array //event RAL; // Read Array (Low frequency) event BE4; // Block Erase 4KB event BE32; // Block Erase 32KB event BE64; // Block Erase 64KB event CE; // Chip Erase event BP; // byte /page program //event SBPE; // Sequential Byte Program Mode Erase event SBP; // Sequential Byte Program event WE; // Write Enable event WD; // Write Disable event PS; // Protect Sector event UPS; // Un-Protect Sector event RSPR; // Read Sector Protection Register event RSR; // Read Status Register event WSR; // Write Status Register event MIR; // Manufacturer ID Read /******** Other variables/registers ******************/ reg [23:0] temp_addr; // to store mem address temporarily reg [23:0] current_address; // to store mem address reg [7:0] temp_data; // temp read data from memory reg [7:0] data_in; // data in for byte programming reg [7:0] read_data; // register in which opcode/data is read-in reg [7:0] read_dummy; // register in which dont care data is stored reg [3:0] stat_reg_temp; // WSR temp value for global protec/unprotect reg [7:0] pp_address; // specifies the page address for BP/PP reg SO_reg; // Signal out reg reg SO_on; // Signal out enable signal reg SPRL; // Sector Protection Register Locked reg SPM; // Sequential Program Mode Status reg EPE; // Erase/Program Error reg WPP; // Write Protection Pin Status reg [1:0] SWP; // Software Protection Status reg WEL; // Write Enable Latch Status reg RDYnBSY; // Ready/Busy Status reg lock; // to lock SPRL bit of status reg reg unlock; // to unlock SPRL bit of status reg reg global_protect; // global protection reg global_unprotect; // global unprotect reg protect; // to protect Sector reg bits reg unprotect; // to unprotect Sector reg bits reg protected; // check protection status of sector reg reg SPRL_val; // WSR temp value for SPRL integer i,j,k,l; // integers for accessing memory integer pp; // specifies no of bytes need to write in memory integer pp_j; // holds no of bytes received for page program integer pp_i; // holds no of bits received for each byte in page program integer dummy; // counter for receiving 8 dummy bit from SO integer delay; // waits for Chip Erase to complete real tperiod; // time period - on period real tperiod1; // time period - off period reg freq_error; // frequency limit exceeds indication // ****************** Initial Block **************** // `ifdef def_321 assign HOLDB = 1'b1; `endif initial begin // Memory Initialization //To pre-load Memory (in Hex format), use parameter MEMORY_FILE = <filename>, //where <filename> is the name of the pre-load file. //If PRELOAD = 0, the Memory is initialized to Erased state (all data = FF). //If PRELOAD = 1, the Memory is initialized to PreLoad state (data in pre-load file). for(i=0; i<BLOCK64; i=i+1) // Block64K access begin for(j=0; j<2; j=j+1) // Block32K access begin for(k=0; k<8; k=k+1) // Block4K access begin for(l=0; l < 12'hfff; l=l+1) begin memory[l] = 8'b11111111; end end end end // Memory Initialization for preloading condition if(PRELOAD==1) begin $readmemh (MEMORY_FILE, memory); end // Status register initialization SPRL = 1'b0; SPM = 1'b0; EPE = 1'b0; WPP = 1'b0; SWP = 2'b11; WEL = 1'b0; RDYnBSY = 1'b0; // device is ready status_reg[7] = SPRL; status_reg[6] = SPM; status_reg[5] = EPE; // reserved status_reg[4] = WPP; status_reg[3:2] = SWP; status_reg[1] = WEL; status_reg[0] = RDYnBSY; //status_reg = {1'b1,1'b0,1'b0,1'b0,2'b11,2'b0}; sector_reg = 64'hFFFFFFFFFFFFFFFF; // Stand-by mode initialization current_address = 24'b0; data_in = 8'b0; stat_reg_temp = 4'b0; deep_power_down = 1'b0; status_read = 1'b0; rd_dummy = 1'b0; seq_byte_start = 1'b0; SO_on = 1'b0; global_protect = 1'b0; global_unprotect = 1'b0; SPRL_val = 1'b0; lock = 1'b0; unlock = 1'b0; dummy = 0; deep_power_down = 1'b0; status_read = 1'b0; erasing_block4 = 1'b0; erasing_block32 = 1'b0; erasing_block64 = 1'b0; erasing_chip = 1'b0; rd_dummy = 1'b0; byte_prog = 1'b0; seq_byte_prog = 1'b0; seq_byte_start = 1'b0; end // end of initial // ********************** Drive SO ********************* // bufif1 (SO, SO_reg, SO_on); //SO will be driven only if SO_on is High // global protection and unprotection on sectors always@(global_protect or global_unprotect) begin if(global_protect==1'b1) sector_reg = 64'hFFFFFFFFFFFFFFFF; else if(global_unprotect==1'b1) sector_reg[SECTOR-1:0] = 'b0; end // ********************* Status register ********************* // always @(WPB or lock or unlock) //SPRL bit locking & Unlocking begin if(WPB==1'b1 && SPRL==1'b0 && lock==1'b1) SPRL = 1'b1; else if(WPB==1'b1 && SPRL==1'b1 && unlock==1'b1) SPRL = 1'b0; // S/W Locked else if(WPB==1'b0 && SPRL==1'b0 && lock==1'b1) SPRL = 1'b1; else if(WPB==1'b0 && SPRL==1'b1 && unlock==1'b1) SPRL = 1'b1; // H/W Locked end always @(WPB) // Write Protect (WP!) Pin Status begin WPP = WPB; end always @(sector_reg) // Software Protection Status begin if(sector_reg[SECTOR-1:0]=='d0) SWP = 2'b00; else if((|sector_reg==1'b1) && (§or_reg==1'b0)) SWP = 2'b01; else if(§or_reg==1'b1) SWP = 2'b11; end always @(SPRL or SPM or EPE or WPP or SWP or WEL or RDYnBSY) begin status_reg = {SPRL,SPM,EPE,WPP,SWP,WEL,RDYnBSY}; end // ******* to receive opcode and to switch to respective blocks ******* // always @(negedge CSB) // the device will now become active begin : get_opcode_ //@(negedge SCK); get_opcode; // get opcode here if (deep_power_down == 1'b1) // Can be only after background has been enabled case (read_data) 8'hAB: // Resume from Deep Power-down begin $display("Opcode(%h) for Resume from Deep Power-down received",read_data); -> RDPD; end default : begin $display ("Opcode %h is not allowed: device in Deep Power-down", read_data); disable get_opcode_; end endcase else begin case (read_data) // based on opcode, trigger an action 8'h0B : // Read Array begin $display("Opcode(%h) for Read Array received",read_data); rd_dummy = 1'b1; -> RA; end 8'h03 : // Read Array (low freq) begin // Comment out this to clean up sim output //$display("Opcode(%h) for Read Array (Low Freq) received",read_data); rd_dummy = 1'b0; -> RA; end 8'h20 : // Block erase 4 KB begin $display("Opcode(%h) for 4 KB Block erase received",read_data); -> BE4; end 8'h52 : // Block erase 32 KB begin $display("Opcode(%h) for 32 KB Block erase received",read_data); -> BE32; end 8'hD8 : // Block erase 64 KB begin $display("Opcode(%h) for 64 KB Block erase received",read_data); -> BE64; end 8'h60 : // Chip erase begin $display("Opcode(%h) for Chip erase received",read_data); -> CE; end 8'hC7 : // Chip erase begin $display("Opcode(%h) for Chip erase received",read_data); -> CE; end 8'h02 : // Byte Program begin $display("Opcode(%h) Byte Program received",read_data); -> BP; end 8'hAD : // Sequential Byte Program Mode Erase begin if(DEVICE=="AT25DF041A" || DEVICE=="AT26DF081A" || DEVICE=="AT26DF161A") begin $display("Opcode(%h) Sequential Byte Program received",read_data); -> SBP; end else if(DEVICE=="AT26DF321") $display("Sequential Byte Program is not supported for device %s",DEVICE); end 8'hAF : // Sequential Byte Program Mode begin if(DEVICE=="AT25DF041A" || DEVICE=="AT26DF081A" || DEVICE=="AT26DF161A") begin $display("Opcode(%h) Sequential Byte Program received",read_data); -> SBP; end else if(DEVICE=="AT26DF321") $display("Sequential Byte Program is not supported for device %s",DEVICE); end 8'h06 : // Write Enable begin $display("Opcode(%h) for Write Enable received",read_data); -> WE; end 8'h04 : // Write Disable begin $display("Opcode(%h) for Write Disable received",read_data); -> WD; end 8'h36 : // Protect Sector begin $display("Opcode(%h) for Protect Sector received",read_data); -> PS; end 8'h39 : // Unprotect Sector begin $display("Opcode(%h) for Unprotect Sector received",read_data); -> UPS; end 8'h3C : // Read Sector Protection Register begin $display("Opcode(%h) for Read Sector Protection Register received",read_data); -> RSPR; end 8'h05 : // Read Status Register begin $display("Opcode(%h) for Status Register Read received",read_data); -> RSR; end 8'h01 : // Write Status Register begin $display("Opcode(%h) for Write Status Register received",read_data); -> WSR; end 8'h9F : // Read Manufacturer and Device ID begin $display("Opcode(%h) for Read Manufacturer and Device ID received",read_data); -> MIR; end 8'hB9 : // Deep Power-down begin $display("Opcode(%h) for Deep Power-down received",read_data); -> EDPD; end default : begin $display ("Unrecognized opcode %h", read_data); disable get_opcode_; end endcase end end // *********************** TASKS / FUNCTIONS ************************** // // get_opcode is a task to get 8 bits of opcode. // It obtains 8 bits of data obtained on SI task get_opcode; integer i; begin for (i=8; i>0; i = i-1) begin @(posedge SCK); read_data[i-1] = SI; if(HOLDB==1'b0) wait (HOLDB); end i=7; end endtask // get_data is a task to get 8 bits of data. This data could be an address, // data or anything. It just obtains 8 bits of data obtained on SI task get_data; integer i; begin for (i=7; i>=0; i = i-1) begin @(posedge SCK); read_data[i] = SI; if(HOLDB==1'b0) wait (HOLDB); end i=7; end endtask // task read_out_array is to read from main Memory task read_out_array ; input [23:0] read_addr; integer i; begin temp_data = memory [read_addr]; i = 7; while (CSB == 1'b0) // continue transmitting, while, CSB is Low begin @(negedge SCK); SO_reg = 1'bx; if(HOLDB==1'b0) begin #tHLQZ SO_on = 1'b0; wait (HOLDB); #tHHQX; end #tV SO_reg = temp_data[i]; SO_on = 1'b1; if (i == 0) begin if (VERBOSE) $display ("Data: %h read from memory location %h",temp_data,read_addr); read_addr = read_addr + 1; // next byte i = 7; if (read_addr >= (MEMSIZE-1)) read_addr = 0; // Note that rollover occurs at end of memory, temp_data = memory [read_addr]; end else i = i - 1; // next bit end // reading over, because CSB has gone high end endtask // Sector protection task protect_sector; input [23:0] protect_address; begin $display("Entered Protect Sector task"); if (DEVICE == "AT26DF321" && protect==1'b1) begin if(protect_address[23:16]==8'b00111111) sector_reg[63] = 1'b1; else if(protect_address[23:16]==8'b00111110) sector_reg[62] = 1'b1; else if(protect_address[23:16]==8'b00111101) sector_reg[61] = 1'b1; else if(protect_address[23:16]==8'b00111100) sector_reg[60] = 1'b1; else if(protect_address[23:16]==8'b00111011) sector_reg[59] = 1'b1; else if(protect_address[23:16]==8'b00111010) sector_reg[58] = 1'b1; else if(protect_address[23:16]==8'b00111001) sector_reg[57] = 1'b1; else if(protect_address[23:16]==8'b00111000) sector_reg[56] = 1'b1; else if(protect_address[23:16]==8'b00110111) sector_reg[55] = 1'b1; else if(protect_address[23:16]==8'b00110110) sector_reg[54] = 1'b1; else if(protect_address[23:16]==8'b00110101) sector_reg[53] = 1'b1; else if(protect_address[23:16]==8'b00110100) sector_reg[52] = 1'b1; else if(protect_address[23:16]==8'b00110011) sector_reg[51] = 1'b1; else if(protect_address[23:16]==8'b00110010) sector_reg[50] = 1'b1; else if(protect_address[23:16]==8'b00110001) sector_reg[49] = 1'b1; else if(protect_address[23:16]==8'b00110000) sector_reg[48] = 1'b1; else if(protect_address[23:16]==8'b00101111) sector_reg[47] = 1'b1; else if(protect_address[23:16]==8'b00101110) sector_reg[46] = 1'b1; else if(protect_address[23:16]==8'b00101101) sector_reg[45] = 1'b1; else if(protect_address[23:16]==8'b00101100) sector_reg[44] = 1'b1; else if(protect_address[23:16]==8'b00101011) sector_reg[43] = 1'b1; else if(protect_address[23:16]==8'b00101010) sector_reg[42] = 1'b1; else if(protect_address[23:16]==8'b00101001) sector_reg[41] = 1'b1; else if(protect_address[23:16]==8'b00101000) sector_reg[40] = 1'b1; else if(protect_address[23:16]==8'b00100111) sector_reg[39] = 1'b1; else if(protect_address[23:16]==8'b00100110) sector_reg[38] = 1'b1; else if(protect_address[23:16]==8'b00100101) sector_reg[37] = 1'b1; else if(protect_address[23:16]==8'b00100100) sector_reg[36] = 1'b1; else if(protect_address[23:16]==8'b00100011) sector_reg[35] = 1'b1; else if(protect_address[23:16]==8'b00100010) sector_reg[34] = 1'b1; else if(protect_address[23:16]==8'b00100001) sector_reg[33] = 1'b1; else if(protect_address[23:16]==8'b00100000) sector_reg[32] = 1'b1; end if ((DEVICE == "AT26DF161A" || DEVICE == "AT26DF321") && protect==1'b1) begin if(protect_address[23:16]==8'b00011111) sector_reg[31] = 1'b1; else if(protect_address[23:16]==8'b00011110) sector_reg[30] = 1'b1; else if(protect_address[23:16]==8'b00011101) sector_reg[29] = 1'b1; else if(protect_address[23:16]==8'b00011100) sector_reg[28] = 1'b1; else if(protect_address[23:16]==8'b00011011) sector_reg[27] = 1'b1; else if(protect_address[23:16]==8'b00011010) sector_reg[26] = 1'b1; else if(protect_address[23:16]==8'b00011001) sector_reg[25] = 1'b1; else if(protect_address[23:16]==8'b00011000) sector_reg[24] = 1'b1; else if(protect_address[23:16]==8'b00010111) sector_reg[23] = 1'b1; else if(protect_address[23:16]==8'b00010110) sector_reg[22] = 1'b1; else if(protect_address[23:16]==8'b00010101) sector_reg[21] = 1'b1; else if(protect_address[23:16]==8'b00010100) sector_reg[20] = 1'b1; else if(protect_address[23:16]==8'b00010011) sector_reg[19] = 1'b1; else if(protect_address[23:16]==8'b00010010) sector_reg[18] = 1'b1; else if(protect_address[23:16]==8'b00010001) sector_reg[17] = 1'b1; else if(protect_address[23:16]==8'b00010000) sector_reg[16] = 1'b1; end if (DEVICE == "AT26DF081A" && protect==1'b1) // un-uniform sectors of AT26DF081A begin if(protect_address[23:14]==10'b00001111_00) sector_reg[15] = 1'b1; else if(protect_address[23:13]==11'b00001111_010) sector_reg[16] = 1'b1; else if(protect_address[23:13]==11'b00001111_011) sector_reg[17] = 1'b1; else if(protect_address[23:17]==9'b00001111_1) sector_reg[18] = 1'b1; end else if ((DEVICE == "AT26DF161A" || DEVICE == "AT26DF321") && protect==1'b1) begin if(protect_address[23:16]==8'b00001111) sector_reg[15] = 1'b1; end if ((DEVICE == "AT26DF081A" || DEVICE == "AT26DF161A" || DEVICE == "AT26DF321") && protect==1'b1) begin // if(protect_address[23:16]==8'b00001111) // sector_reg[15] = 1'b1; if(protect_address[23:16]==8'b00001110) sector_reg[14] = 1'b1; else if(protect_address[23:16]==8'b00001101) sector_reg[13] = 1'b1; else if(protect_address[23:16]==8'b00001100) sector_reg[12] = 1'b1; else if(protect_address[23:16]==8'b00001011) sector_reg[11] = 1'b1; else if(protect_address[23:16]==8'b00001010) sector_reg[10] = 1'b1; else if(protect_address[23:16]==8'b00001001) sector_reg[9] = 1'b1; else if(protect_address[23:16]==8'b00001000) sector_reg[8] = 1'b1; end if (DEVICE == "AT25DF041A" && protect==1'b1) // un-uniform sectors of AT25DF041A begin if(protect_address[23:15]==9'b00000111_0) sector_reg[7] = 1'b1; else if(protect_address[23:13]==11'b00000111_100) sector_reg[8] = 1'b1; else if(protect_address[23:13]==11'b00000111_101) sector_reg[9] = 1'b1; else if(protect_address[23:14]==10'b00000111_11) sector_reg[10] = 1'b1; end else if ((DEVICE == "AT26DF081A" || DEVICE == "AT26DF161A" || DEVICE == "AT26DF321") && protect==1'b1) if(protect_address[23:16]==8'b00000111) sector_reg[7] = 1'b1; if ((DEVICE == "AT25DF041A" || DEVICE == "AT26DF081A" || DEVICE == "AT26DF161A" || DEVICE == "AT26DF321") && protect==1'b1) begin // if(protect_address[23:16]==8'b00000111) // sector_reg[7] = 1'b1; if(protect_address[23:16]==8'b00000110) sector_reg[6] = 1'b1; else if(protect_address[23:16]==8'b00000101) sector_reg[5] = 1'b1; else if(protect_address[23:16]==8'b00000100) sector_reg[4] = 1'b1; else if(protect_address[23:16]==8'b00000011) sector_reg[3] = 1'b1; else if(protect_address[23:16]==8'b00000010) sector_reg[2] = 1'b1; else if(protect_address[23:16]==8'b00000001) sector_reg[1] = 1'b1; else if(protect_address[23:16]==8'b00000000) sector_reg[0] = 1'b1; end end endtask // Sector Unprotection task unprotect_sector; input [23:0] unprotect_address; begin if ((DEVICE == "AT25DF041A") && unprotect==1'b1) // sectors of AT25DF041A begin $display("Entered Unprotect sector for Device: AT25DF041A"); if(unprotect_address[23:14]==10'b00000111_11) sector_reg[10] = 1'b0; else if(unprotect_address[23:13]==11'b00000111_101) sector_reg[9] = 1'b0; else if(unprotect_address[23:13]==11'b00000111_100) sector_reg[8] = 1'b0; else if(unprotect_address[23:15]==9'b00000111_0) sector_reg[7] = 1'b0; else if(unprotect_address[23:16]==8'b00000110) sector_reg[6] = 1'b0; else if(unprotect_address[23:16]==8'b00000101) sector_reg[5] = 1'b0; else if(unprotect_address[23:16]==8'b00000100) sector_reg[4] = 1'b0; else if(unprotect_address[23:16]==8'b00000011) sector_reg[3] = 1'b0; else if(unprotect_address[23:16]==8'b00000010) sector_reg[2] = 1'b0; else if(unprotect_address[23:16]==8'b00000001) sector_reg[1] = 1'b0; else if(unprotect_address[23:16]==8'b00000000) sector_reg[0] = 1'b0; end else if (DEVICE == "AT26DF081A" && unprotect==1'b1) // sectors of AT26DF081A begin $display("Entered Unprotect sector for Device: AT26DF081A"); if(unprotect_address[23:17]==9'b00001111_1) sector_reg[18] = 1'b0; else if(unprotect_address[23:13]==11'b00001111_011) sector_reg[17] = 1'b0; else if(unprotect_address[23:13]==11'b00001111_010) sector_reg[16] = 1'b0; else if(unprotect_address[23:14]==10'b00001111_00) sector_reg[15] = 1'b0; else if(unprotect_address[23:16]==8'b00001110) sector_reg[14] = 1'b0; else if(unprotect_address[23:16]==8'b00001101) sector_reg[13] = 1'b0; else if(unprotect_address[23:16]==8'b00001100) sector_reg[12] = 1'b0; else if(unprotect_address[23:16]==8'b00001011) sector_reg[11] = 1'b0; else if(unprotect_address[23:16]==8'b00001010) sector_reg[10] = 1'b0; else if(unprotect_address[23:16]==8'b00001001) sector_reg[9] = 1'b0; else if(unprotect_address[23:16]==8'b00001000) sector_reg[8] = 1'b0; else if(unprotect_address[23:16]==8'b00000111) sector_reg[7] = 1'b0; else if(unprotect_address[23:16]==8'b00000110) sector_reg[6] = 1'b0; else if(unprotect_address[23:16]==8'b00000101) sector_reg[5] = 1'b0; else if(unprotect_address[23:16]==8'b00000100) sector_reg[4] = 1'b0; else if(unprotect_address[23:16]==8'b00000011) sector_reg[3] = 1'b0; else if(unprotect_address[23:16]==8'b00000010) sector_reg[2] = 1'b0; else if(unprotect_address[23:16]==8'b00000001) sector_reg[1] = 1'b0; else if(unprotect_address[23:16]==8'b00000000) sector_reg[0] = 1'b0; end else if ((DEVICE == "AT26DF161A") && unprotect==1'b1) // sectors of AT26DF161A begin $display("Entered Unprotect sector for Device: AT26DF161A"); if(unprotect_address[23:16]==8'b00011111) sector_reg[31] = 1'b0; else if(unprotect_address[23:16]==8'b00011110) sector_reg[30] = 1'b0; else if(unprotect_address[23:16]==8'b00011101) sector_reg[29] = 1'b0; else if(unprotect_address[23:16]==8'b00011100) sector_reg[28] = 1'b0; else if(unprotect_address[23:16]==8'b00011011) sector_reg[27] = 1'b0; else if(unprotect_address[23:16]==8'b00011010) sector_reg[26] = 1'b0; else if(unprotect_address[23:16]==8'b00011001) sector_reg[25] = 1'b0; else if(unprotect_address[23:16]==8'b00011000) sector_reg[24] = 1'b0; else if(unprotect_address[23:16]==8'b00010111) sector_reg[23] = 1'b0; else if(unprotect_address[23:16]==8'b00010110) sector_reg[22] = 1'b0; else if(unprotect_address[23:16]==8'b00010101) sector_reg[21] = 1'b0; else if(unprotect_address[23:16]==8'b00010100) sector_reg[20] = 1'b0; else if(unprotect_address[23:16]==8'b00010011) sector_reg[19] = 1'b0; else if(unprotect_address[23:16]==8'b00010010) sector_reg[18] = 1'b0; else if(unprotect_address[23:16]==8'b00010001) sector_reg[17] = 1'b0; else if(unprotect_address[23:16]==8'b00010000) sector_reg[16] = 1'b0; else if(unprotect_address[23:16]==8'b00001111) sector_reg[15] = 1'b0; else if(unprotect_address[23:16]==8'b00001110) sector_reg[14] = 1'b0; else if(unprotect_address[23:16]==8'b00001101) sector_reg[13] = 1'b0; else if(unprotect_address[23:16]==8'b00001100) sector_reg[12] = 1'b0; else if(unprotect_address[23:16]==8'b00001011) sector_reg[11] = 1'b0; else if(unprotect_address[23:16]==8'b00001010) sector_reg[10] = 1'b0; else if(unprotect_address[23:16]==8'b00001001) sector_reg[9] = 1'b0; else if(unprotect_address[23:16]==8'b00001000) sector_reg[8] = 1'b0; else if(unprotect_address[23:16]==8'b00000111) sector_reg[7] = 1'b0; else if(unprotect_address[23:16]==8'b00000110) sector_reg[6] = 1'b0; else if(unprotect_address[23:16]==8'b00000101) sector_reg[5] = 1'b0; else if(unprotect_address[23:16]==8'b00000100) sector_reg[4] = 1'b0; else if(unprotect_address[23:16]==8'b00000011) sector_reg[3] = 1'b0; else if(unprotect_address[23:16]==8'b00000010) sector_reg[2] = 1'b0; else if(unprotect_address[23:16]==8'b00000001) sector_reg[1] = 1'b0; else if(unprotect_address[23:16]==8'b00000000) sector_reg[0] = 1'b0; end else if (DEVICE == "AT26DF321" && unprotect==1'b1) // sectors of AT26DF321 begin $display("Entered Unprotect sector for Device: AT26DF321"); if(unprotect_address[23:16]==8'b00111111) sector_reg[63] = 1'b0; else if(unprotect_address[23:16]==8'b00111110) sector_reg[62] = 1'b0; else if(unprotect_address[23:16]==8'b00111101) sector_reg[61] = 1'b0; else if(unprotect_address[23:16]==8'b00111100) sector_reg[60] = 1'b0; else if(unprotect_address[23:16]==8'b00111011) sector_reg[59] = 1'b0; else if(unprotect_address[23:16]==8'b00111010) sector_reg[58] = 1'b0; else if(unprotect_address[23:16]==8'b00111001) sector_reg[57] = 1'b0; else if(unprotect_address[23:16]==8'b00111000) sector_reg[56] = 1'b0; else if(unprotect_address[23:16]==8'b00110111) sector_reg[55] = 1'b0; else if(unprotect_address[23:16]==8'b00110110) sector_reg[54] = 1'b0; else if(unprotect_address[23:16]==8'b00110101) sector_reg[53] = 1'b0; else if(unprotect_address[23:16]==8'b00110100) sector_reg[52] = 1'b0; else if(unprotect_address[23:16]==8'b00110011) sector_reg[51] = 1'b0; else if(unprotect_address[23:16]==8'b00110010) sector_reg[50] = 1'b0; else if(unprotect_address[23:16]==8'b00110001) sector_reg[49] = 1'b0; else if(unprotect_address[23:16]==8'b00110000) sector_reg[48] = 1'b0; else if(unprotect_address[23:16]==8'b00101111) sector_reg[47] = 1'b0; else if(unprotect_address[23:16]==8'b00101110) sector_reg[46] = 1'b0; else if(unprotect_address[23:16]==8'b00101101) sector_reg[45] = 1'b0; else if(unprotect_address[23:16]==8'b00101100) sector_reg[44] = 1'b0; else if(unprotect_address[23:16]==8'b00101011) sector_reg[43] = 1'b0; else if(unprotect_address[23:16]==8'b00101010) sector_reg[42] = 1'b0; else if(unprotect_address[23:16]==8'b00101001) sector_reg[41] = 1'b0; else if(unprotect_address[23:16]==8'b00101000) sector_reg[40] = 1'b0; else if(unprotect_address[23:16]==8'b00100111) sector_reg[39] = 1'b0; else if(unprotect_address[23:16]==8'b00100110) sector_reg[38] = 1'b0; else if(unprotect_address[23:16]==8'b00100101) sector_reg[37] = 1'b0; else if(unprotect_address[23:16]==8'b00100100) sector_reg[36] = 1'b0; else if(unprotect_address[23:16]==8'b00100011) sector_reg[35] = 1'b0; else if(unprotect_address[23:16]==8'b00100010) sector_reg[34] = 1'b0; else if(unprotect_address[23:16]==8'b00100001) sector_reg[33] = 1'b0; else if(unprotect_address[23:16]==8'b00100000) sector_reg[32] = 1'b0; else if(unprotect_address[23:16]==8'b00011111) sector_reg[31] = 1'b0; else if(unprotect_address[23:16]==8'b00011110) sector_reg[30] = 1'b0; else if(unprotect_address[23:16]==8'b00011101) sector_reg[29] = 1'b0; else if(unprotect_address[23:16]==8'b00011100) sector_reg[28] = 1'b0; else if(unprotect_address[23:16]==8'b00011011) sector_reg[27] = 1'b0; else if(unprotect_address[23:16]==8'b00011010) sector_reg[26] = 1'b0; else if(unprotect_address[23:16]==8'b00011001) sector_reg[25] = 1'b0; else if(unprotect_address[23:16]==8'b00011000) sector_reg[24] = 1'b0; else if(unprotect_address[23:16]==8'b00010111) sector_reg[23] = 1'b0; else if(unprotect_address[23:16]==8'b00010110) sector_reg[22] = 1'b0; else if(unprotect_address[23:16]==8'b00010101) sector_reg[21] = 1'b0; else if(unprotect_address[23:16]==8'b00010100) sector_reg[20] = 1'b0; else if(unprotect_address[23:16]==8'b00010011) sector_reg[19] = 1'b0; else if(unprotect_address[23:16]==8'b00010010) sector_reg[18] = 1'b0; else if(unprotect_address[23:16]==8'b00010001) sector_reg[17] = 1'b0; else if(unprotect_address[23:16]==8'b00010000) sector_reg[16] = 1'b0; else if(unprotect_address[23:16]==8'b00001111) sector_reg[15] = 1'b0; else if(unprotect_address[23:16]==8'b00001110) sector_reg[14] = 1'b0; else if(unprotect_address[23:16]==8'b00001101) sector_reg[13] = 1'b0; else if(unprotect_address[23:16]==8'b00001100) sector_reg[12] = 1'b0; else if(unprotect_address[23:16]==8'b00001011) sector_reg[11] = 1'b0; else if(unprotect_address[23:16]==8'b00001010) sector_reg[10] = 1'b0; else if(unprotect_address[23:16]==8'b00001001) sector_reg[9] = 1'b0; else if(unprotect_address[23:16]==8'b00001000) sector_reg[8] = 1'b0; else if(unprotect_address[23:16]==8'b00000111) sector_reg[7] = 1'b0; else if(unprotect_address[23:16]==8'b00000110) sector_reg[6] = 1'b0; else if(unprotect_address[23:16]==8'b00000101) sector_reg[5] = 1'b0; else if(unprotect_address[23:16]==8'b00000100) sector_reg[4] = 1'b0; else if(unprotect_address[23:16]==8'b00000011) sector_reg[3] = 1'b0; else if(unprotect_address[23:16]==8'b00000010) sector_reg[2] = 1'b0; else if(unprotect_address[23:16]==8'b00000001) sector_reg[1] = 1'b0; else if(unprotect_address[23:16]==8'b00000000) sector_reg[0] = 1'b0; end else $display("Unprotect Sector failed"); end endtask // Check Sector Protection task check_protection; input [23:0] check_address; begin if (DEVICE == "AT26DF321") begin if((check_address[23:16]==8'b00111111 && sector_reg[63]==1'b1) || (check_address[23:16]==8'b00111110 && sector_reg[62]==1'b1) || (check_address[23:16]==8'b00111101 && sector_reg[61]==1'b1) || (check_address[23:16]==8'b00111100 && sector_reg[60]==1'b1) || (check_address[23:16]==8'b00111011 && sector_reg[59]==1'b1) || (check_address[23:16]==8'b00111010 && sector_reg[58]==1'b1) || (check_address[23:16]==8'b00111001 && sector_reg[57]==1'b1) || (check_address[23:16]==8'b00111000 && sector_reg[56]==1'b1) || (check_address[23:16]==8'b00110111 && sector_reg[55]==1'b1) || (check_address[23:16]==8'b00110110 && sector_reg[54]==1'b1) || (check_address[23:16]==8'b00110101 && sector_reg[53]==1'b1) || (check_address[23:16]==8'b00110100 && sector_reg[52]==1'b1) || (check_address[23:16]==8'b00110011 && sector_reg[51]==1'b1) || (check_address[23:16]==8'b00110010 && sector_reg[50]==1'b1) || (check_address[23:16]==8'b00110001 && sector_reg[49]==1'b1) || (check_address[23:16]==8'b00110000 && sector_reg[48]==1'b1) || (check_address[23:16]==8'b00101111 && sector_reg[47]==1'b1) || (check_address[23:16]==8'b00101110 && sector_reg[46]==1'b1) || (check_address[23:16]==8'b00101101 && sector_reg[45]==1'b1) || (check_address[23:16]==8'b00101100 && sector_reg[44]==1'b1) || (check_address[23:16]==8'b00101011 && sector_reg[43]==1'b1) || (check_address[23:16]==8'b00101010 && sector_reg[42]==1'b1) || (check_address[23:16]==8'b00101001 && sector_reg[41]==1'b1) || (check_address[23:16]==8'b00101000 && sector_reg[40]==1'b1) || (check_address[23:16]==8'b00100111 && sector_reg[39]==1'b1) || (check_address[23:16]==8'b00100110 && sector_reg[38]==1'b1) || (check_address[23:16]==8'b00100101 && sector_reg[37]==1'b1) || (check_address[23:16]==8'b00100100 && sector_reg[36]==1'b1) || (check_address[23:16]==8'b00100011 && sector_reg[35]==1'b1) || (check_address[23:16]==8'b00100010 && sector_reg[34]==1'b1) || (check_address[23:16]==8'b00100001 && sector_reg[33]==1'b1) || (check_address[23:16]==8'b00100000 && sector_reg[32]==1'b1) || (check_address[23:16]==8'b00011111 && sector_reg[31]==1'b1) || (check_address[23:16]==8'b00011110 && sector_reg[30]==1'b1) || (check_address[23:16]==8'b00011101 && sector_reg[29]==1'b1) || (check_address[23:16]==8'b00011100 && sector_reg[28]==1'b1) || (check_address[23:16]==8'b00011011 && sector_reg[27]==1'b1) || (check_address[23:16]==8'b00011010 && sector_reg[26]==1'b1) || (check_address[23:16]==8'b00011001 && sector_reg[25]==1'b1) || (check_address[23:16]==8'b00011000 && sector_reg[24]==1'b1) || (check_address[23:16]==8'b00010111 && sector_reg[23]==1'b1) || (check_address[23:16]==8'b00010110 && sector_reg[22]==1'b1) || (check_address[23:16]==8'b00010101 && sector_reg[21]==1'b1) || (check_address[23:16]==8'b00010100 && sector_reg[20]==1'b1) || (check_address[23:16]==8'b00010011 && sector_reg[19]==1'b1) || (check_address[23:16]==8'b00010010 && sector_reg[18]==1'b1) || (check_address[23:16]==8'b00010001 && sector_reg[17]==1'b1) || (check_address[23:16]==8'b00010000 && sector_reg[16]==1'b1) || (check_address[23:16]==8'b00001111 && sector_reg[15]==1'b1) || (check_address[23:16]==8'b00001110 && sector_reg[14]==1'b1) || (check_address[23:16]==8'b00001101 && sector_reg[13]==1'b1) || (check_address[23:16]==8'b00001100 && sector_reg[12]==1'b1) || (check_address[23:16]==8'b00001011 && sector_reg[11]==1'b1) || (check_address[23:16]==8'b00001010 && sector_reg[10]==1'b1) || (check_address[23:16]==8'b00001001 && sector_reg[9] ==1'b1) || (check_address[23:16]==8'b00001000 && sector_reg[8] ==1'b1) || (check_address[23:16]==8'b00000111 && sector_reg[7] ==1'b1) || (check_address[23:16]==8'b00000110 && sector_reg[6] ==1'b1) || (check_address[23:16]==8'b00000101 && sector_reg[5] ==1'b1) || (check_address[23:16]==8'b00000100 && sector_reg[4] ==1'b1) || (check_address[23:16]==8'b00000011 && sector_reg[3] ==1'b1) || (check_address[23:16]==8'b00000010 && sector_reg[2] ==1'b1) || (check_address[23:16]==8'b00000001 && sector_reg[1] ==1'b1) || (check_address[23:16]==8'b00000000 && sector_reg[0] ==1'b1)) protected = 1'b1; else protected = 1'b0; end else if (DEVICE == "AT26DF161A") begin if((check_address[23:16]==8'b00011111 && sector_reg[31]==1'b1) || (check_address[23:16]==8'b00011110 && sector_reg[30]==1'b1) || (check_address[23:16]==8'b00011101 && sector_reg[29]==1'b1) || (check_address[23:16]==8'b00011100 && sector_reg[28]==1'b1) || (check_address[23:16]==8'b00011011 && sector_reg[27]==1'b1) || (check_address[23:16]==8'b00011010 && sector_reg[26]==1'b1) || (check_address[23:16]==8'b00011001 && sector_reg[25]==1'b1) || (check_address[23:16]==8'b00011000 && sector_reg[24]==1'b1) || (check_address[23:16]==8'b00010111 && sector_reg[23]==1'b1) || (check_address[23:16]==8'b00010110 && sector_reg[22]==1'b1) || (check_address[23:16]==8'b00010101 && sector_reg[21]==1'b1) || (check_address[23:16]==8'b00010100 && sector_reg[20]==1'b1) || (check_address[23:16]==8'b00010011 && sector_reg[19]==1'b1) || (check_address[23:16]==8'b00010010 && sector_reg[18]==1'b1) || (check_address[23:16]==8'b00010001 && sector_reg[17]==1'b1) || (check_address[23:16]==8'b00010000 && sector_reg[16]==1'b1) || (check_address[23:16]==8'b00001111 && sector_reg[15]==1'b1) || (check_address[23:16]==8'b00001110 && sector_reg[14]==1'b1) || (check_address[23:16]==8'b00001101 && sector_reg[13]==1'b1) || (check_address[23:16]==8'b00001100 && sector_reg[12]==1'b1) || (check_address[23:16]==8'b00001011 && sector_reg[11]==1'b1) || (check_address[23:16]==8'b00001010 && sector_reg[10]==1'b1) || (check_address[23:16]==8'b00001001 && sector_reg[9] ==1'b1) || (check_address[23:16]==8'b00001000 && sector_reg[8] ==1'b1) || (check_address[23:16]==8'b00000111 && sector_reg[7] ==1'b1) || (check_address[23:16]==8'b00000110 && sector_reg[6] ==1'b1) || (check_address[23:16]==8'b00000101 && sector_reg[5] ==1'b1) || (check_address[23:16]==8'b00000100 && sector_reg[4] ==1'b1) || (check_address[23:16]==8'b00000011 && sector_reg[3] ==1'b1) || (check_address[23:16]==8'b00000010 && sector_reg[2] ==1'b1) || (check_address[23:16]==8'b00000001 && sector_reg[1] ==1'b1) || (check_address[23:16]==8'b00000000 && sector_reg[0] ==1'b1)) protected = 1'b1; else protected = 1'b0; end else if (DEVICE == "AT26DF081A") // un-uniform sectors of AT26DF081A begin if((check_address[23:17]==9'b00001111_1 && sector_reg[18] ==1'b1) || (check_address[23:13]==11'b00001111_011 && sector_reg[17]==1'b1) || (check_address[23:13]==11'b00001111_010 && sector_reg[16]==1'b1) || (check_address[23:14]==10'b00001111_00 && sector_reg[15] ==1'b1) || (check_address[23:16]==8'b00001110 && sector_reg[14]==1'b1) || (check_address[23:16]==8'b00001101 && sector_reg[13]==1'b1) || (check_address[23:16]==8'b00001100 && sector_reg[12]==1'b1) || (check_address[23:16]==8'b00001011 && sector_reg[11]==1'b1) || (check_address[23:16]==8'b00001010 && sector_reg[10]==1'b1) || (check_address[23:16]==8'b00001001 && sector_reg[9] ==1'b1) || (check_address[23:16]==8'b00001000 && sector_reg[8] ==1'b1) || (check_address[23:16]==8'b00000111 && sector_reg[7] ==1'b1) || (check_address[23:16]==8'b00000110 && sector_reg[6] ==1'b1) || (check_address[23:16]==8'b00000101 && sector_reg[5] ==1'b1) || (check_address[23:16]==8'b00000100 && sector_reg[4] ==1'b1) || (check_address[23:16]==8'b00000011 && sector_reg[3] ==1'b1) || (check_address[23:16]==8'b00000010 && sector_reg[2] ==1'b1) || (check_address[23:16]==8'b00000001 && sector_reg[1] ==1'b1) || (check_address[23:16]==8'b00000000 && sector_reg[0] ==1'b1)) protected = 1'b1; else protected = 1'b0; end else if (DEVICE == "AT25DF041A") // un-uniform sectors of AT25DF041A begin if((check_address[23:14]==10'b00000111_11 && sector_reg[10]==1'b1) || (check_address[23:13]==11'b00000111_101 && sector_reg[9]==1'b1) || (check_address[23:13]==11'b00000111_100 && sector_reg[8]==1'b1) || (check_address[23:15]==9'b00000111_0 && sector_reg[7] ==1'b1) || (check_address[23:16]==8'b00000110 && sector_reg[6]==1'b1) || (check_address[23:16]==8'b00000101 && sector_reg[5]==1'b1) || (check_address[23:16]==8'b00000100 && sector_reg[4]==1'b1) || (check_address[23:16]==8'b00000011 && sector_reg[3]==1'b1) || (check_address[23:16]==8'b00000010 && sector_reg[2]==1'b1) || (check_address[23:16]==8'b00000001 && sector_reg[1]==1'b1) || (check_address[23:16]==8'b00000000 && sector_reg[0]==1'b1)) protected = 1'b1; else protected = 1'b0; end else $display("Check Sector Protection failed"); end endtask // Sending Sector Protection status task send_protection_status; integer local_i; reg [7:0] send_status; // status value, 'ff' if protected, '00' if unprotected begin if(protected==1'b1) send_status = 8'hff; else send_status = 8'h00; local_i = 7; while (CSB == 1'b0) // continue transmitting, while, CSB is Low begin @(negedge SCK); SO_reg = 1'bx; if(HOLDB==1'b0) begin #tHLQZ SO_on = 1'b0; wait (HOLDB); #tHHQX; end #tV; SO_reg = send_status[local_i]; SO_on = 1'b1; if (local_i == 0) local_i = 7; else local_i = local_i - 1; // next bit end // sending status over, because CSB has gone high end endtask // receive data for byte/page programming task page_program; begin pp_j = 0; while(CSB==1'b0) begin for (pp_i=8; pp_i>0; pp_i = pp_i-1) begin @(posedge SCK); read_data[pp_i-1] = SI; if(HOLDB==1'b0) wait (HOLDB); end int_buffer[pp_j] = read_data; pp_j = pp_j+1; $display("One byte of data: %h received for Page Program",read_data); end end endtask // Byte program for devices. also used for page program task byte_program; input [23:0] write_address; input [7:0] write_data; begin memory [write_address] = write_data; $display ("One Byte of data %h written in memory in location %h", write_data, write_address); end endtask // Erase a 4kB block task erase_4kb; input [23:0] erase_address; reg [11:0] erase4_i; reg [23:0] block_addr4; begin block_addr4 = {erase_address[23:12],12'b0000_0000_0000}; $display ("4kB Block with start address %h is going to be erased", block_addr4); for(erase4_i=12'b0; erase4_i < 12'b1111_1111_1111; erase4_i=erase4_i+1) begin memory [block_addr4 + erase4_i] = 8'hff; end end endtask // Erase a 32kB block task erase_32kb; input [23:0] erase_address; reg [14:0] erase32_i; reg [23:0] block_addr32; begin block_addr32 = {erase_address[23:15],15'b0000_0000_0000_000}; $display ("32kB Block with start address %h is going to be erased", block_addr32); for(erase32_i=15'b0; erase32_i < 15'b1111_1111_1111_111; erase32_i=erase32_i+1) begin memory [block_addr32 + erase32_i] = 8'hff; end end endtask // Erase a 64kB block task erase_64kb; input [23:0] erase_address; reg [15:0] erase64_i; reg [23:0] block_addr64; begin block_addr64 = {erase_address[23:16],16'b0000_0000_0000_0000}; $display ("64kB Block with start address %h is going to be erased", block_addr64); for(erase64_i=0; erase64_i < 16'b1111_1111_1111_1111; erase64_i=erase64_i+1) begin memory [block_addr64 + erase64_i] = 8'hff; end end endtask // Chip Erase task erase_chip; reg [23:0] erase_i; begin $display ("Chip Erase is going to be started"); for(erase_i=0; erase_i < (MEMSIZE-1); erase_i=erase_i+1) begin memory [erase_i] = 8'hff; end end endtask // ******************* Execution of Opcodes ********************* // // ************* Deep Power-down ***************** // always @(EDPD) begin : EDPD_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device is busy. Deep Power-down command cannot be issued"); disable EDPD_ ; end // if it comes here, means, the above if was false. //if (freq_error==1'b1) //$display("WARNING: Frequency should be less than %d Mhz for SPI interface. Deep Power-down is not allowed.",fSCK); @ (posedge CSB); RDYnBSY = 1'b1; #tEDPD deep_power_down = 1'b1; RDYnBSY = 1'b0; $display ("Device %s enters into Deep Power-down mode. Send 'Resume from Deep Power-down' to resume", DEVICE); end // ************* Resume from Deep Power-down ***************** // always @(RDPD) begin : RDPD_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device is busy. Deep Power-down command cannot be issued"); disable EDPD_ ; end // if it comes here, means, the above if was false. //if (freq_error==1'b1) //$display("WARNING: Frequency should be less than %d Mhz for SPI interface. Resume from Deep Power-down is not allowed.",fSCK); @ (posedge CSB); RDYnBSY = 1'b1; #tRDPD deep_power_down = 1'b0; RDYnBSY = 1'b0; $display ("Device %s Resumes from Deep Power-down mode", DEVICE); end // ************* Manufacturing ID Read ******************** // always @(MIR) begin: MIR_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device is busy. Manufacturing ID Read cannot be issued"); disable EDPD_ ; end // if it comes here, means, the above if was false. //if (freq_error==1'b1) //$display("WARNING: Frequency should be less than %d Mhz for SPI interface. Manufacturing ID Read is not allowed.",fSCK); j = 32; while (CSB == 1'b0) begin @(negedge SCK); SO_reg = 1'bx; if(HOLDB==1'b0) begin #tHLQZ SO_on = 1'b0; wait (HOLDB); #tHHQX; end #tV; if (j > 0) begin SO_reg = MAN_ID[j-1]; j = j-1; SO_on = 1'b1; if(j == 0) begin $display ("Manufacture ID and Device ID of Device %s sent", DEVICE); j = 32; end end end // output next bit on next falling edge of SCK $display ("Manufacture ID and Device ID of Device %s sent", DEVICE); end // ************ Read Status Register ******************** // always @(RSR) begin: RSR_ //if (freq_error==1'b1) //$display("WARNING: Frequency should be less than %d Mhz for SPI interface. Status Register Read is not allowed.",fSCK); status_read = 1'b1; // reading status_reg j = 8; while (CSB == 1'b0) begin @(negedge SCK); SO_reg = 1'bx; if(HOLDB==1'b0) begin #tHLQZ SO_on = 1'b0; wait (HOLDB); #tHHQX; end #tV; if (j > 0) begin SO_on = 1'b1; SO_reg = status_reg[j-1]; j = j-1; if (j == 0) begin j = 8; $display ("Status register content of Device %s transmitted", DEVICE); end end end // output next bit on next falling edge of SCK status_read = 1'b0; // status_reg read is over end // ************ Write Status Register ******************** // always @(WSR) begin : WSR_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device %s is busy. Write Status Register is not allowed", DEVICE); disable WSR_; end // if it comes here, means, the above if was false. if (freq_error==1'b1) $display("WARNING: Frequency should be less than %d Mhz for SPI interface. Write Status Register is not allowed.",fSCK); get_data; SPRL_val = read_data [7]; stat_reg_temp = read_data [5:2]; @ (posedge CSB); if(WEL==1'b1) begin if(WPB==1'b0 && SPRL==1'b0 && SPRL_val==1'b1) $display("SPRL Hardware locked"); else if(WPB==1'b1 && SPRL==1'b0 && SPRL_val==1'b1) $display("SPRL Software locked"); else if(WPB==1'b0 && SPRL==1'b1 && SPRL_val==1'b1) $display("SPRL Hardware locked. Lock cannot be done"); else if(WPB==1'b1 && SPRL==1'b1 && SPRL_val==1'b1) $display("SPRL Software locked. Lock cannot be done"); else if(WPB==1'b0 && SPRL==1'b1 && SPRL_val==1'b0) $display("SPRL Hardware locked. Unlock cannot be done"); else if(WPB==1'b1 && SPRL==1'b1 && SPRL_val==1'b0) $display("Sector Protection Register UnLocked"); else $display("SPRL in unlocked state"); if(stat_reg_temp==4'b1111 && SPRL==1'b0) global_protect = 1'b1; else if(stat_reg_temp==4'b0000 && SPRL==1'b0) global_unprotect = 1'b1; else if(SPRL==1'b1 && (stat_reg_temp==4'b0000 || stat_reg_temp==4'b1111)) begin $display("SPRL locked. Global Protect/Unprotect cannot be done"); global_protect = 1'b0; global_unprotect = 1'b0; end if(SPRL==1'b0 && global_protect==1'b1) $display("Global Protection issued for Sector protection register"); else if(SPRL==1'b0 && global_unprotect==1'b1) $display("Global Unprotect issued for Sector protection register"); else if(SPRL==1'b1 && (global_protect==1'b1 || global_unprotect==1'b1)) $display("SPRL locked. Global Protect/Unprotect cannot be done"); if(SPRL==1'b0 && SPRL_val==1'b1) begin RDYnBSY = 1'b1; lock = 1'b1; #tWRSR; end else if(SPRL==1'b1 && SPRL_val==1'b0) begin RDYnBSY = 1'b1; unlock = 1'b1; #tWRSR; end else if(global_protect==1'b1 || global_unprotect==1'b1) begin RDYnBSY = 1'b1; #tWRSR; end end else $display ("WEL bit not set. Write Status Register is not allowed"); lock = 1'b0; unlock = 1'b0; RDYnBSY = 1'b0; global_protect = 1'b0; global_unprotect = 1'b0; WEL = 1'b0; $display ("Write Status Register operation completed"); end // ************ Write Enable ******************** // always @(WE) begin : WE_ if (freq_error==1'b1) $display("WARNING: Frequency should be less than %d MHz for SPI interface. Write Enable is not allowed.",fSCK); @ (posedge CSB); WEL = 1'b1; $display ("Write Enable Latch Set"); end // ************ Write Disable ******************** // always @(WD) begin : WD_ if (freq_error==1'b1) $display("WARNING: Frequency should be less than %d MHz for SPI interface. Write Disable is not allowed.",fSCK); @ (posedge CSB); WEL = 1'b0; seq_byte_start = 1'b0; SPM = 1'b0; $display ("Write Enable Latch Reset"); end // ******************** Read Array ********************** // always @(RA) begin : RA_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device %s is busy. Read Array is not allowed", DEVICE); disable RA_; end // if it comes here, means, the above if was false. if (freq_error==1'b1) $display ("WARNING: Frequency should be less than %d MHz for SPI interface. Read Array is not allowed",fSCK); get_data; temp_addr [23:16] = read_data [7:0]; get_data; temp_addr [15:8] = read_data [7:0]; get_data; temp_addr [7:0] = read_data [7:0]; current_address = temp_addr; if(rd_dummy==1'b1 && CSB==1'b0) // for SCK freq, receive 8 dummy bits begin for (dummy = 7; dummy >= 0; dummy = dummy - 1) // these are dont-care, so discarded begin @(posedge SCK); read_dummy[dummy] = SI; if(HOLDB==1'b0) wait (HOLDB); end read_dummy = 8'b0; end read_out_array(current_address); // read continuously from memory untill CSB deasserted current_address = 24'b0; end // ****************** Protect Sector ****************** // always @(PS) begin : PS_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device %s is busy. Protect Sector is not allowed", DEVICE); disable PS_ ; end // if it comes here, means, the above if was false. if (freq_error==1'b1) $display ("WARNING: Frequency should be less than %d MHz for SPI interface. Protect Sector is not allowed",fSCK); get_data; temp_addr [23:16] = read_data [7:0]; get_data; temp_addr [15:8] = read_data [7:0]; get_data; temp_addr [7:0] = read_data [7:0]; current_address = temp_addr; @ (posedge CSB); if(WEL==1'b1 && SPRL==1'b0) begin RDYnBSY = 1'b1; protect = 1'b1; protect_sector(current_address); #tSECP; $display ("Sector for Address %h is Protected", current_address); end else $display ("WEL bit not set or Sector Protection Register Locked. Protect Sector is not allowed"); WEL = 1'b0; RDYnBSY = 1'b0; protect = 1'b0; current_address = 24'b0; end // ****************** Un-Protect Sector ****************** // always @(UPS) begin : UPS_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device %s is busy. Un-Protect Sector is not allowed", DEVICE); disable UPS_ ; end // if it comes here, means, the above if was false. if (freq_error==1'b1) $display ("WARNING: Frequency should be less than %d MHz for SPI interface. Un-Protect Sector is not allowed",fSCK); get_data; temp_addr [23:16] = read_data [7:0]; get_data; temp_addr [15:8] = read_data [7:0]; get_data; temp_addr [7:0] = read_data [7:0]; current_address = temp_addr; @ (posedge CSB); if(WEL==1'b1 && SPRL==1'b0) begin RDYnBSY = 1'b1; unprotect = 1'b1; unprotect_sector(current_address); #tSECUP; $display ("Sector for Address %h is UnProtected", current_address); end else $display ("WEL bit not set or Sector Protection Register Locked. Un-Protect Sector is not allowed"); unprotect = 1'b0; WEL = 1'b0; RDYnBSY = 1'b0; current_address = 24'b0; end // ****************** Read Sector Protection Register ****************** // always @(RSPR) begin : RSPR_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device %s is busy. Read Sector Protection Register is not allowed", DEVICE); disable RSPR_ ; end // if it comes here, means, the above if was false. if (freq_error==1'b1) $display ("WARNING: Frequency should be less than %d MHz for SPI interface. Read Sector Protection Register is not allowed",fSCK); get_data; temp_addr [23:16] = read_data [7:0]; get_data; temp_addr [15:8] = read_data [7:0]; get_data; temp_addr [7:0] = read_data [7:0]; current_address = temp_addr; check_protection(current_address); if(protected==1'b1) $display ("Sector for Address %h is Protected", current_address); else $display ("Sector for Address %h is UnProtected", current_address); send_protection_status; // sending the Sector Protection Register content in SO current_address = 24'b0; $display ("Read Sector Protection Register completed"); end // ********************* Byte Program ********************* // always @(BP) begin : BP_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device %s is busy. Byte Program is not allowed", DEVICE); disable BP_ ; end // if it comes here, means, the above if was false. if (freq_error==1'b1) $display ("WARNING: Frequency should be less than %d MHz for SPI interface. Byte Program is not allowed",fSCK); // to receive 3 bytes of address get_data; temp_addr [23:16] = read_data [7:0]; get_data; temp_addr [15:8] = read_data [7:0]; get_data; temp_addr [7:0] = read_data [7:0]; current_address = temp_addr; /* // to receive 1 bytes of data get_data; data_in [7:0] = read_data [7:0]; */ page_program; // page program - receives data if(pp_i < 8) // page program should not proceed if CSB deasserted at intermediate points begin $display ("Chip Select deasserted in non-even point. Byte/Page Program is not allowed"); WEL = 1'b0; EPE = 1'b1; disable BP_ ; end if(WEL==1'b0) begin $display ("WEL bit not set. Byte Program is not allowed"); disable BP_ ; end check_protection(current_address); if(protected==1'b1) begin $display("Sector for Address %h is Protected. Byte Program cannot be performed", current_address); WEL = 1'b0; disable BP_ ; end else begin $display ("Sector for Address %h is UnProtected, Byte Program can be performed", current_address); // @ (posedge CSB); RDYnBSY = 1'b1; byte_prog = 1'b1; pp_address = current_address[7:0]; for(pp = 0; pp < pp_j; pp = pp+1) begin data_in = int_buffer[pp]; byte_program({current_address[23:8],pp_address}, data_in); pp_address = pp_address + 1'b1; end $display("Byte write completed"); #tPP; pp = 0; pp_j = 0; pp_i = 0; WEL = 1'b0; RDYnBSY = 1'b0; byte_prog = 1'b0; current_address = 24'b0; pp_address = 8'b0; data_in = 8'b0; end end // ********************* Sequential Byte Program ********************* // always @(SBP) begin : SBP_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device %s is busy. Sequential Byte Program is not allowed", DEVICE); disable SBP_ ; end // if it comes here, means, the above if was false. if (freq_error==1'b1) $display ("WARNING: Frequency should be less than %d MHz for SPI interface. Sequential Byte Program is not allowed",fSCK); if(seq_byte_start==1'b0) begin // to receive 3 bytes of address get_data; temp_addr [23:16] = read_data [7:0]; get_data; temp_addr [15:8] = read_data [7:0]; get_data; temp_addr [7:0] = read_data [7:0]; current_address = temp_addr; end SPM = 1'b1; // Entered Sequential Byte Programing mode if(seq_byte_start==1'b1) // to increment address when entering sequential mode begin if(current_address < (MEMSIZE-1)) current_address = current_address + 1'b1; else if(current_address == (MEMSIZE-1)) begin $display ("Sequential Byte Program for device: %s reaches end of memory (%h). No Wrapping allowed. Sequential Byte Program is not allowed", DEVICE, MEMSIZE-1); WEL = 1'b0; SPM = 1'b0; seq_byte_start = 1'b0; disable SBP_ ; end end // to receive 1 bytes of data get_data; data_in [7:0] = read_data [7:0]; if(WEL==1'b0) begin $display ("WEL bit not set. Sequential Byte Program is not allowed"); seq_byte_start = 1'b0; SPM = 1'b0; disable SBP_ ; end check_protection(current_address); if(protected==1'b1) begin $display("Sector for Address %h is Protected. Sequential Byte Program cannot be performed", current_address); seq_byte_start = 1'b0; WEL = 1'b0; SPM = 1'b0; disable SBP_ ; end else begin $display ("Sector for Address %h is UnProtected, Sequential Byte Program can be performed", current_address); @ (posedge CSB); RDYnBSY = 1'b1; seq_byte_prog = 1'b1; byte_program(current_address, data_in); $display("Sequential Byte write completed"); #tBP; RDYnBSY = 1'b0; seq_byte_prog = 1'b0; data_in = 8'b0; seq_byte_start = 1'b1; end end // ********************* 4kB Block Erase ********************* // always @(BE4) begin : BE4_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device %s is busy. 4KB Block Erase is not allowed", DEVICE); disable BE4_ ; end // if it comes here, means, the above if was false. if (freq_error==1'b1) $display ("WARNING: Frequency should be less than %d MHz for SPI interface. 4KB Block Erase is not allowed",fSCK); get_data; temp_addr [23:16] = read_data [7:0]; get_data; temp_addr [15:8] = read_data [7:0]; get_data; temp_addr [7:0] = read_data [7:0]; current_address = temp_addr; if(WEL==1'b0) begin $display ("WEL bit not set. 4KB Block Erase is not allowed"); disable BE4_ ; end check_protection(current_address); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 4KB Block Erase cannot be performed", current_address); WEL = 1'b0; disable BE4_ ; end else begin $display ("Sector for Address %h is UnProtected, 4KB Block Erase can be performed", current_address); @ (posedge CSB); RDYnBSY = 1'b1; erasing_block4 = 1'b1; erase_4kb(current_address); #tBLKE4; $display ("4kB Block with start address %h erased", {current_address[23:12],12'b0}); WEL = 1'b0; RDYnBSY = 1'b0; current_address = 24'b0; erasing_block4 = 1'b0; end end // ********************* 32kB Block Erase ********************* // always @(BE32) begin : BE32_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device %s is busy. 32KB Block Erase is not allowed", DEVICE); disable BE32_ ; end // if it comes here, means, the above if was false. if (freq_error==1'b1) $display ("WARNING: Frequency should be less than %d MHz for SPI interface. 32KB Block Erase is not allowed",fSCK); get_data; temp_addr [23:16] = read_data [7:0]; get_data; temp_addr [15:8] = read_data [7:0]; get_data; temp_addr [7:0] = read_data [7:0]; current_address = temp_addr; if(WEL==1'b0) begin $display ("WEL bit not set. 32KB Block Erase is not allowed"); disable BE32_ ; end if(DEVICE == "AT25DF041A" && current_address[23:15]==9'b0000_0111_1) begin check_protection({current_address[23:16],2'b11,14'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 32KB Block Erase cannot be performed", {current_address[23:16],2'b11,14'b0}); EPE = 1'b1; WEL = 1'b0; disable BE32_ ; end check_protection({current_address[23:16],3'b100,13'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 32KB Block Erase cannot be performed", {current_address[23:16],3'b100,13'b0}); EPE = 1'b1; WEL = 1'b0; disable BE32_ ; end check_protection({current_address[23:16],3'b101,13'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 32KB Block Erase cannot be performed", {current_address[23:16],3'b101,13'b0}); EPE = 1'b1; WEL = 1'b0; disable BE32_ ; end end else if(DEVICE == "AT26DF081A" && current_address[23:15]==9'b0000_1111_0) begin check_protection({current_address[23:16],2'b00,15'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 32KB Block Erase cannot be performed", {current_address[23:16],2'b00,15'b0}); EPE = 1'b1; WEL = 1'b0; disable BE32_ ; end check_protection({current_address[23:16],3'b010,13'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 32KB Block Erase cannot be performed", {current_address[23:16],3'b010,13'b0}); EPE = 1'b1; WEL = 1'b0; disable BE32_ ; end check_protection({current_address[23:16],3'b011,13'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 32KB Block Erase cannot be performed", {current_address[23:16],3'b011,13'b0}); EPE = 1'b1; WEL = 1'b0; disable BE32_ ; end end else check_protection(current_address); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 32KB Block Erase cannot be performed", current_address); WEL = 1'b0; disable BE32_ ; end else begin $display ("Sector for Address %h is UnProtected, 32KB Block Erase can be performed", current_address); @ (posedge CSB); RDYnBSY = 1'b1; erasing_block32 = 1'b1; erase_32kb(current_address); #tBLKE32; $display ("32KB Block with start address %h erased", {current_address[23:15],15'b0}); WEL = 1'b0; RDYnBSY = 1'b0; current_address = 24'b0; erasing_block32 = 1'b0; end end // ********************* 64kB Block Erase ********************* // always @(BE64) begin : BE64_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device %s is busy. 64KB Block Erase is not allowed", DEVICE); disable BE64_ ; end // if it comes here, means, the above if was false. if (freq_error==1'b1) $display ("WARNING: Frequency should be less than %d MHz for SPI interface. 64KB Block Erase is not allowed",fSCK); get_data; temp_addr [23:16] = read_data [7:0]; get_data; temp_addr [15:8] = read_data [7:0]; get_data; temp_addr [7:0] = read_data [7:0]; current_address = temp_addr; if(WEL==1'b0) begin $display ("WEL bit not set. 64KB Block Erase is not allowed"); disable BE64_ ; end if(DEVICE == "AT25DF041A" && current_address[23:16]==8'b0000_0111) begin check_protection({current_address[23:16],1'b0,15'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 64KB Block Erase cannot be performed", {current_address[23:16],1'b0,15'b0}); EPE = 1'b1; WEL = 1'b0; disable BE64_ ; end check_protection({current_address[23:16],2'b11,14'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 64KB Block Erase cannot be performed", {current_address[23:16],2'b11,14'b0}); EPE = 1'b1; WEL = 1'b0; disable BE64_ ; end check_protection({current_address[23:16],3'b100,13'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 64KB Block Erase cannot be performed", {current_address[23:16],3'b100,13'b0}); EPE = 1'b1; WEL = 1'b0; disable BE64_ ; end check_protection({current_address[23:16],3'b101,13'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 64KB Block Erase cannot be performed", {current_address[23:16],3'b101,13'b0}); EPE = 1'b1; WEL = 1'b0; disable BE64_ ; end end else if(DEVICE == "AT26DF081A" && current_address[23:16]==8'b0000_1111) begin check_protection({current_address[23:16],2'b00,15'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 64KB Block Erase cannot be performed", {current_address[23:16],2'b00,15'b0}); EPE = 1'b1; WEL = 1'b0; disable BE64_ ; end check_protection({current_address[23:16],1'b1,14'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 64KB Block Erase cannot be performed", {current_address[23:16],1'b1,14'b0}); EPE = 1'b1; WEL = 1'b0; disable BE64_ ; end check_protection({current_address[23:16],3'b010,13'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 64KB Block Erase cannot be performed", {current_address[23:16],3'b010,13'b0}); EPE = 1'b1; WEL = 1'b0; disable BE64_ ; end check_protection({current_address[23:16],3'b011,13'b0}); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 64KB Block Erase cannot be performed", {current_address[23:16],3'b011,13'b0}); EPE = 1'b1; WEL = 1'b0; disable BE64_ ; end end else check_protection(current_address); if(protected==1'b1) begin $display("Sector for Address %h is Protected. 64KB Block Erase cannot be performed", current_address); WEL = 1'b0; disable BE64_ ; end else begin $display ("Sector for Address %h is UnProtected, 64KB Block Erase can be performed", current_address); @ (posedge CSB); RDYnBSY = 1'b1; erasing_block64 = 1'b1; erase_64kb(current_address); #tBLKE64; $display ("64kB Block with start address %h erased", {current_address[23:16],16'b0}); WEL = 1'b0; RDYnBSY = 1'b0; current_address = 24'b0; erasing_block64 = 1'b0; end end // ********************* Chip Erase ********************* // always @(CE) begin : CE_ if (RDYnBSY == 1'b1) // device is already busy begin $display ("Device %s is busy. Chip Erase is not allowed", DEVICE); disable CE_ ; end // if it comes here, means, the above if was false. if (freq_error==1'b1) $display ("WARNING: Frequency should be less than %d MHz for SPI interface. Chip Erase is not allowed",fSCK); if(WEL==1'b0) begin $display ("WEL bit not set. Chip Erase is not allowed"); disable CE_ ; end if(SWP==2'b00) begin $display("All Sectors in the chip are UnProtected. Chip Erase can be performed"); @ (posedge CSB); RDYnBSY = 1'b1; erasing_chip = 1'b1; erase_chip; for(delay =0; delay < tmult; delay = delay+1) #tCHPEn; WEL = 1'b0; RDYnBSY = 1'b0; erasing_chip = 1'b0; end else if(SWP!=2'b00) begin $display("Some or all Sectors in the chip is Protected. Chip Erase cannot be performed"); EPE = 1'b1; disable CE_ ; end $display ("Chip Erase Completed"); end // ******** Posedge CSB. Stop all reading, recvng. commands/addresses etc. ********* // always @(posedge CSB) begin disable RA_; // Read Array (low freq and normal freq) disable MIR_; // MIR will stop, if CSB goes high disable RSR_; // Status reading should stop. disable get_opcode; // Stop opcode retrieval disable get_data; // Stop address/data retrieval disable read_out_array; // send data in SO disable send_protection_status; // Send Protection status disable page_program; temp_data = 8'b0; temp_addr = 24'b0; rd_dummy = 1'b0; status_read = 1'b0; protected = 1'b0; read_data = 8'b0; EPE = 1'b0; #tDIS SO_on = 1'b0; // SO is now in high-impedance SO_reg = 1'b0; end // ********************** Frequeny Checking ********************** // always @ (negedge SCK) begin tperiod <= $time; tperiod1 <= tperiod; end //always @(tperiod or tperiod1) always @(negedge SCK) begin if ((tperiod - tperiod1) < (tSCKH + tSCKH)) begin //freq_error = 1'b1; //$display("Frequency exceeds max limit (14285 ms). Time period detected is %t", (tperiod -tperiod1)); end else freq_error = 1'b0; end // always // **************************************************************** // endmodule
Go to most recent revision | Compare with Previous | Blame | View Log