OpenCores
URL https://opencores.org/ocsvn/oms8051mini/oms8051mini/trunk

Subversion Repositories oms8051mini

[/] [oms8051mini/] [trunk/] [verif/] [agents/] [spi/] [atmel/] [AT45DBXXX_v2.0.3.v] - Rev 17

Go to most recent revision | Compare with Previous | Blame | View Log

/************************************************************************
 
        Verilog model for Atmel Devices
          AT45DBXXX  parameterizable 
 
            Developed for Atmel By:
                Jason G Brown
                Glenn Donovan
                 Jeff Gladu
 
              January 24, 2002
 
************************************************************************/
 
/************************************************************************
Development History:
 
  AT45DBXXX model : Sanjay Churiwala, May-June 1999
  Parameterized   : Niranjan Vaish, June 1999
 
Revision History:
 
1.0    : Niranjan Vaish   : Parametrized model for AT45DBXXX devices.
1.1    : Niranjan Vaish   : Updated RDY_BUSYB driving register.
2.0    : Niranjan Vaish   : 2M, 4M and 8M also offer Page Erase and Block Erase.
2.0.1  : Niranjan Vaish   : buffer1 and buffer2 were not declared correctly.
2.0.2  : Niranjan Vaish   : Additional parametrization has been done.
2.0.3  : WPI Project Team : Removed Burst Mode.
 
*************************************************************************/
 
 
/*************************************************************************
 Define the configuration which you want to use.
*************************************************************************/
//`define device4M 1  // This model will work like AT45DB041
`define device32M 1  // This model will work like AT45DB321
 
 
/*************************************************************************/
 
`ifdef device1M
module AT45DB011 (CSB, SCK, SI, WPB, RESETB, RDY_BUSYB, SO);
`endif
 
`ifdef device2M
module AT45DB021 (CSB, SCK, SI, WPB, RESETB, RDY_BUSYB, SO);
`endif
 
`ifdef device4M
module AT45DB041 (CSB, SCK, SI, WPB, RESETB, RDY_BUSYB, SO);
`endif
 
`ifdef device8M
module AT45DB081 (CSB, SCK, SI, WPB, RESETB, RDY_BUSYB, SO);
`endif
 
`ifdef device16M
module AT45DB161 (CSB, SCK, SI, WPB, RESETB, RDY_BUSYB, SO);
`endif
 
`ifdef device32M
module AT45DB321 (CSB, SCK, SI, WPB, RESETB, RDY_BUSYB, SO);
`endif
 
input CSB, SCK, SI, WPB, RESETB;
output SO, RDY_BUSYB;
 
/*************************************************************************
Device configuration parameters :
*************************************************************************/
 
`ifdef device1M
parameter DEVICE = "AT45DB011";
parameter MEMSIZE = 135168; // no of byte_news = PAGESIZE * PAGES
parameter PAGESIZE = 264; // no of byte_news per page
parameter PAGES = 512; // no of pages
parameter STATUS3 = 1;  // this and next two lines are for
                               //bits 3 to 5 of status register
parameter STATUS4 = 0;
parameter STATUS5 = 0;
parameter BUFFERS = 1; // no. of buffers
parameter BADDRESS = 9; // no of bits needed to access a byte_new within a page
parameter PADDRESS = 9; // no of bits needed to access a page
parameter PROTECTED = 256; // no of pages that can be Protected, using WPB
`endif
 
`ifdef device2M
parameter DEVICE = "AT45DB021";
parameter MEMSIZE = 270336; // no of byte_news = PAGESIZE * PAGES
parameter PAGESIZE = 264; // no of byte_news per page
parameter PAGES = 1024; // no of pages
parameter STATUS3 = 0;  // this and next two lines are for
                               //bits 3 to 5 of status register
parameter STATUS4 = 1;
parameter STATUS5 = 0;
parameter BUFFERS = 2; // no. of buffers
parameter BADDRESS = 9; // no of bits needed to access a byte_new within a page
parameter PADDRESS = 10; // no of bits needed to access a page
parameter PROTECTED = 256; // no of pages that can be Protected, using WPB
`endif
 
`ifdef device4M
parameter DEVICE = "AT45DB041";
parameter MEMSIZE = 540672; // no of byte_news = PAGESIZE * PAGES
parameter PAGESIZE = 264; // no of byte_news per page
parameter PAGES = 2048; // no of pages
parameter STATUS3 = 1;  // this and next two lines are for
                               //bits 3 to 5 of status register
parameter STATUS4 = 1;
parameter STATUS5 = 0;
parameter BUFFERS = 2; // no. of buffers
parameter BADDRESS = 9; // no of bits needed to access a byte_new within a page
parameter PADDRESS = 11; // no of bits needed to access a page
parameter PROTECTED = 256; // no of pages that can be Protected, using WPB
`endif
 
`ifdef device8M
parameter DEVICE = "AT45DB081";
parameter MEMSIZE = 1081344; // no of byte_news = PAGESIZE * PAGES
parameter PAGESIZE = 264; // no of byte_news per page
parameter PAGES = 4096; // no of pages
parameter STATUS3 = 0;  // this and next two lines are for
                               //bits 3 to 5 of status register
parameter STATUS4 = 0;
parameter STATUS5 = 1;
parameter BUFFERS = 2; // no. of buffers
parameter BADDRESS = 9; // no of bits needed to access a byte_new within a page
parameter PADDRESS = 12; // no of bits needed to access a page
parameter PROTECTED = 256; // no of pages that can be Protected, using WPB
`endif
 
`ifdef device16M
parameter DEVICE = "AT45DB161";
parameter MEMSIZE = 2162688; // no of byte_news = PAGESIZE * PAGES
parameter PAGESIZE = 528; // no of byte_news per page
parameter PAGES = 4096; // no of pages
parameter STATUS3 = 1;  // this and next two lines are for
                               //bits 3 to 5 of status register
parameter STATUS4 = 0;
parameter STATUS5 = 1;
parameter BUFFERS = 2; // no. of buffers
parameter BADDRESS = 10; // no of bits needed to access a byte_new within a page
parameter PADDRESS = 12; // no of bits needed to access a page
parameter PROTECTED = 256; // no of pages that can be Protected, using WPB
`endif
 
 
 
`ifdef device32M
parameter DEVICE = "AT45DB321";
//parameter MEMSIZE = 4194304; // no of byte_news = PAGESIZE * PAGES
parameter MEMSIZE = 4325376; // no of byte_news = PAGESIZE * PAGES
parameter PAGESIZE = 528; // no of byte_news per page
parameter PAGES = 8192; // no of pages
parameter STATUS3 = 0;  // this and next two lines are for 
                               //bits 3 to 5 of status register
parameter STATUS4 = 1;
parameter STATUS5 = 1;
parameter BUFFERS = 2; // no. of buffers
parameter BADDRESS = 10; // no of bits needed to access a byte_new within a page
parameter PADDRESS = 13; // no of bits needed to access a page
parameter PROTECTED = 256; // no of pages that can be Protected, using WPB
`endif
 
/********************************************************************
Timing Parameters :
More timing parameters given as specparam within the specify block
********************************************************************/
 
`ifdef device1M
parameter tDIS = 25;
parameter tV = 30;
parameter tXFR = 200000;
parameter tEP = 20000000;
parameter tP = 15000000;
parameter tPE = 10000000;
parameter tBE = 15000000;
parameter tCAR = 200;
`endif
 
`ifdef device2M
parameter tDIS = 25;
parameter tV = 30;
parameter tXFR = 250000;
parameter tEP = 20000000;
parameter tP = 14000000;
parameter tPE = 10000000; // Correct it
parameter tBE = 15000000; // Correct it
parameter tCAR = 200;
`endif
 
`ifdef device4M
parameter tDIS = 25;
parameter tV = 30;
parameter tXFR = 250000;
parameter tEP = 20000000;
parameter tP = 14000000;
parameter tPE = 10000000;
parameter tBE = 15000000;
parameter tCAR = 200;
`endif
 
`ifdef device8M
parameter tDIS = 25;
parameter tV = 30;
parameter tXFR = 200000;
parameter tEP = 20000000;
parameter tP = 14000000;
parameter tPE = 10000000; // Correct it
parameter tBE = 15000000; // Correct it
parameter tCAR = 200;
`endif
 
`ifdef device16M
parameter tDIS = 25;
parameter tV = 30;
parameter tXFR = 350000;
parameter tEP = 20000000;
parameter tP = 15000000;
parameter tPE = 10000000;
parameter tBE = 15000000;
parameter tCAR = 200;
`endif
 
`ifdef device32M
`ifdef ATFLASH_SPDUP
parameter tDIS = 25;
parameter tV = 30;
parameter tXFR = 35000;
parameter tEP = 20000;
parameter tP = 15000;
parameter tPE = 10000;
parameter tBE = 15000;
parameter tCAR = 200;
`else
parameter tDIS = 25;
parameter tV = 30;
parameter tXFR = 350000;
parameter tEP = 20000000;
parameter tP = 15000000;
parameter tPE = 10000000;
parameter tBE = 15000000;
parameter tCAR = 200;
`endif
`endif
 
 
/**********************************************************************
Memory PreLoading Parameters:
============================= 
These parameters are related to Memory-Preloading. Since, we had to declare
multiple memories, due to Verilog limitation; for PreLoading also, one may
have to preload multiple memories.
Any of the memories can be preloaded, in either Hex format, or, in Binary 
To load a memory (say memory0) in Hex format, define parameter: mem0_h
To load a memory (say memory0) in Binary format, define parameter: mem0_b
If none of the parameters are specified, the memory will be initialized to
    Erase state.
If both of the parameters are specified, the hex file will be used.
If any of the memory locations are initialized, the status of all the page
   will be Not-Erased.
**********************************************************************/
`ifdef SPI_PRELOAD_FNAME
parameter mem0_h = `SPI_PRELOAD_FNAME;
`else
parameter mem0_h = "";
`endif
parameter mem1_h = "";
parameter mem2_h = "";
parameter mem3_h = "";
parameter mem4_h = "";
parameter mem5_h = "";
parameter mem6_h = "";
parameter mem7_h = "";
 
parameter mem0_b = "";
parameter mem1_b = "";
parameter mem2_b = "";
parameter mem3_b = "";
parameter mem4_b = "";
parameter mem5_b = "";
parameter mem6_b = "";
parameter mem7_b = "";
 
/********* Memory And Access Related Declarations *****************/
// Verilog seems to be having a restriction due to which, large
// memory-registers can not be used. Hence, declaring 8 smaller,
// equal size memories.
 
reg [7:0] memory0 [540671:0] ;
reg [7:0] memory1 [1081343:540672] ;
reg [7:0] memory2 [1622015:1081344] ;
reg [7:0] memory3 [2162687:1622016] ;
reg [7:0] memory4 [2703359:2162688] ;
reg [7:0] memory5 [3244031:2703360] ;
reg [7:0] memory6 [3784703:3244032] ;
reg [7:0] memory7 [4325375:3784704] ;
 
reg [7:0] buffer1 [PAGESIZE-1:0] ; //Buffer 1
reg [7:0] buffer2 [PAGESIZE-1:0] ; //Buffer 2
 
reg [PADDRESS-1:0] page ; // page address
reg [BADDRESS-1:0] byte_new ; // byte_new address
reg [7:0] status ; // status reg
reg [PAGES-1:0] page_status;  // 0 means page-erased, otherwise not erased
 
 
/********* Events to trigger some task based on opcode ***********/
     event  MMPR ;  // Main Memory Page Read
     event  B1R ;   // Buffer 1 Read
     event  B2R ;   // Buffer 2 Read
     event  MMPTB1T ;   // Main Memory Page To Buffer 1 Transfer
     event  MMPTB2T ;   // Main Memory Page To Buffer 2 Transfer
     event  MMPTB1C ;   // Main Memory Page To Buffer 1 Compare
     event  MMPTB2C ;   // Main Memory Page To Buffer 2 Compare
     event  B1W ;   // Buffer 1 Write
     event  B2W ;   // Buffer 2 Write
     event  B1TMMPPWBIE ;   // Buffer 1 To Main Memory Page Prog 
                                     //With Built-In Erase 
     event  B2TMMPPWBIE ;   // Buffer 2 To Main Memory Page Prog 
                                     //With Built-In Erase 
     event  B1TMMPPWOBIE ;   // Buffer 1 To Main Memory Page Prog 
                                     //WithoOut Built-In Erase 
     event  B2TMMPPWOBIE ;   // Buffer 2 To Main Memory Page Prog 
                                     //WithoOut Built-In Erase 
     event  PE ;   // Page Erase
     event  BE ;   // Block Erase
     event  MMPPB1 ;   // Main Memory Page Prog. Through Buffer 1
     event  MMPPB2 ;   // Main Memory Page Prog. Through Buffer 2
     event  APRB1 ;   // Auto Page Rewrite Through Buffer 1
     event  APRB2 ;   // Auto Page Rewrite Through Buffer 2
     event  SR ;   // Status Register Read
     event  RWOPR ; // This is basically same as MMPR, except that rollover
                    // at the end of a page does not occur;
 
/********* Registers to track the current operation of the device ********/
reg status_read;
reg updating_buffer1;
reg updating_buffer2;
reg updating_memory;
reg comparing;
reg erasing_page;
reg erasing_block;
reg skip; // reg to denote whether or no an extra clock needs to be skipped.
          // This skipping is needed only for Inactive Clock Low. 
 
 
/******** Other variables/registers/events ******************/
reg [7:0] read_data; // temp. register in which data is read-in
reg [7:0] temp_reg1; // temp. register to store temporary data
reg [7:0] temp_reg2; // temp. register to store temporary data
reg [PADDRESS-1:0] temp_page; // temp register to store page-address
reg SO_reg , SO_on ; 
reg RDYBSY_reg;
integer j;
integer page_boundary_low, page_boundary_high, current_address;
integer mem_no; // this will keep track of the actual memory to be used.
reg mem_initialized;
 
 
/********* Drive SO ***********************/
bufif1 (SO, SO_reg, SO_on); //SO will be driven only if SO_on is High
bufif1 (RDY_BUSYB, 1'b0, RDYBSY_reg); //RDYBUSYB will be driven only if RDYBSY_reg is High
 
 
/********* Initialize **********************/
initial
begin  
    // start with erased state
    // Memory Initialization
  mem_initialized = 1'b0;
 
  for (j=0; j<540672; j=j+1)   // Pre-initiazliation to Erased
  begin                        // state is useful if a user wants to
    memory0[j] = 8'hff;        // initialize just a few locations.
    memory1[j+540672] = 8'hff; 
    memory2[j+1081344] = 8'hff; 
    memory3[j+1622016] = 8'hff;
    memory4[j+2162688] = 8'hff;
    memory5[j+2703360] = 8'hff;
    memory6[j+3244032] = 8'hff;
    memory7[j+3784704] = 8'hff;
  end
 
   // Now preload, if needed
  if (mem0_h != "")
  begin  
     $readmemh (mem0_h, memory0);
     mem_initialized = 1'b1;
  end
  else if (mem0_b != "")
  begin  
     $readmemb (mem0_b, memory0);
     mem_initialized = 1'b1;
  end
 
  if (mem1_h != "")
  begin  
     $readmemh (mem1_h, memory1);
     mem_initialized = 1'b1;
  end
  else if (mem1_b != "")
  begin  
     $readmemb (mem1_b, memory1);
     mem_initialized = 1'b1;
  end
 
  if (mem2_h != "")
  begin  
     $readmemh (mem2_h, memory2);
     mem_initialized = 1'b1;
  end
  else if (mem2_b != "")
  begin  
     $readmemb (mem2_b, memory2);
     mem_initialized = 1'b1;
  end
 
  if (mem3_h != "")
  begin  
     $readmemh (mem3_h, memory3);
     mem_initialized = 1'b1;
  end
  else if (mem3_b != "")
  begin  
     $readmemb (mem3_b, memory3);
     mem_initialized = 1'b1;
  end
 
  if (mem4_h != "")
  begin  
     $readmemh (mem4_h, memory4);
     mem_initialized = 1'b1;
  end
  else if (mem4_b != "")
  begin  
     $readmemb (mem4_b, memory4);
     mem_initialized = 1'b1;
  end
 
  if (mem5_h != "")
  begin  
     $readmemh (mem5_h, memory5);
     mem_initialized = 1'b1;
  end
  else if (mem5_b != "")
  begin  
     $readmemb (mem5_b, memory5);
     mem_initialized = 1'b1;
  end
 
  if (mem6_h != "")
  begin  
     $readmemh (mem6_h, memory6);
     mem_initialized = 1'b1;
  end
  else if (mem6_b != "")
  begin  
     $readmemb (mem6_b, memory6);
     mem_initialized = 1'b1;
  end
 
  if (mem7_h != "")
  begin  
     $readmemh (mem7_h, memory7);
     mem_initialized = 1'b1;
  end
  else if (mem7_b != "")
  begin  
     $readmemb (mem7_b, memory7);
     mem_initialized = 1'b1;
  end
 
  if (mem_initialized == 1'b1)
  for (j=0; j<PAGES; j=j+1)
    page_status[j] = 1'b1; // memory was initialized, so, Pages are Not Erased.
  else
  for (j=0; j<PAGES; j=j+1)
    page_status[j] = 1'b0;
 
  // Now initialize all registers
  status[7] = 1'b1; // device is ready to start with
  status[6] = 1'bx; // compare bit is unknown
  status[5] = STATUS5;
  status[4] = STATUS4;
  status[3] = STATUS3;
  status[2:0] = 3'bx; // these reserved bits are also unknown
 
  // There is no activity at this time
  status_read = 1'b0;
  updating_buffer1 = 1'b0;
  updating_buffer2 = 1'b0;
  updating_memory = 1'b0;
  comparing = 1'b0;
  erasing_page = 1'b0;
  erasing_block = 1'b0;
 
  // All o/ps are High-impedance
  SO_on = 1'b0;
  RDYBSY_reg = 1'b0;
 
end
 
 
always @(negedge CSB)  // the device will now become active
begin : get_opcode
   if (SCK == 1'b0)
   begin
      skip = 1'b1;
 
   end
   else 
   begin
      skip = 1'b0;
      // If the opcode is related to SPI Mode 0/3, no skipping is needed. So, skip
      // will be reset to "0".
      // If opcode is related to Inactive Clock Low/high, skipping might or might
      // not be needed, depending on the value of SCK at negedge of CSB. So, in
      // such situations, skip will retain its value.
    end
 
   get_data;  // get opcode here
 
   case (status[5:3]) 
     3'b001:  // 1M Memory
         case (read_data)
           // Illegal Opcode for 1M memory. It has only one buffer.
           8'h56, 8'hd6, 8'h55, 8'h61, 8'h87, 8'h86, 8'h89, 8'h85, 8'h59: 
              begin
                $display("Unrecognized opcode %h", read_data);
                disable get_opcode;
              end
         endcase
   endcase
 
   case (read_data)   // based on opcode, trigger an action
     8'h52 : -> MMPR ;  // Main Memory Page Read
     8'hd2 : begin
               skip = 1'b0;
               -> MMPR ;  // Main Memory Page Read
             end
     8'h54 : -> B1R ;   // Buffer 1 Read
     8'hd4 : begin
               skip = 1'b0;
               -> B1R ;   // Buffer 1 Read
             end
     8'h56 : -> B2R ;   // Buffer 2 Read
     8'hd6 : begin
               skip = 1'b0;
               -> B2R ;   // Buffer 2 Read
             end
     8'h53 : -> MMPTB1T ;   // Main Memory Page To Buffer 1 Transfer
     8'h55 : -> MMPTB2T ;   // Main Memory Page To Buffer 2 Transfer
     8'h60 : -> MMPTB1C ;   // Main Memory Page To Buffer 1 Compare
     8'h61 : -> MMPTB2C ;   // Main Memory Page To Buffer 2 Compare
     8'h84 : -> B1W ;   // Buffer 1 Write
     8'h87 : -> B2W ;   // Buffer 2 Write
     8'h83 : -> B1TMMPPWBIE ;   // Buffer 1 To Main Memory Page Prog 
                                               //With Built-In Erase 
     8'h86 : -> B2TMMPPWBIE ;   // Buffer 2 To Main Memory Page Prog 
                                               //With Built-In Erase 
     8'h88 : -> B1TMMPPWOBIE ;   // Buffer 1 To Main Memory Page Prog 
                                               //WithoOut Built-In Erase 
     8'h89 : -> B2TMMPPWOBIE ;   // Buffer 2 To Main Memory Page Prog 
                                               //WithoOut Built-In Erase 
     8'h81 : -> PE ;   // Page Erase
     8'h50 : -> BE ;   // Block Erase
     8'h82 : -> MMPPB1 ;   // Main Memory Page Prog. Through Buffer 1
     8'h85 : -> MMPPB2 ;   // Main Memory Page Prog. Through Buffer 2
     8'h58 : -> APRB1 ;   // Auto Page Rewrite Through Buffer 1
     8'h59 : -> APRB2 ;   // Auto Page Rewrite Through Buffer 2
     8'h57 : -> SR ;   // Status Register Read
     8'hd7 : begin
               skip = 1'b0;
               -> SR ;   // Status Register Read
             end
     8'h68 : -> RWOPR ;
     8'hE8 : begin
               skip = 1'b0;
               -> RWOPR ;
             end
     default : $display ("Unrecognized opcode %h", read_data);
   endcase
end
 
 
/******* Main Memory Page Read ********************/
 
always @(MMPR)
begin : MMPR_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Main Memory Page Read is not allowed");
     disable MMPR_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress and byte_new-address, according to 
        // the parameters.
   compute_page_address;
   compute_byte_new_address;
      // next 8 bits always contain byte_new-address[7:0], and, so is
      // not dependent on parameters
   get_data;
   byte_new[7:0] = read_data[7:0];
 
   for (j=0; j<4; j=j+1)
      get_data ;  // these 32 bits are dont-care, and so have been discarded.
 
   compute_address;
   if (skip == 1'b1)
     @(posedge SCK); // skip one SCK
   read_out (mem_no, current_address, page_boundary_low, page_boundary_high);
end
 
 
/******* Buffer 1 Read ********************/
 
always @(B1R)
begin : B1R_
   get_data; // first 8 bits are dont care
   get_data;
        // For buffers, PageAddress can be assumed as "0".
        // This will allow us to share code with MMPR;
   page [PADDRESS-1:0] = 'h0;
 
   compute_byte_new_address;
      // next 8 bits always contain byte_new-address[7:0], and, so is
      // not dependent on parameters
   get_data;
   byte_new[7:0] = read_data[7:0];
 
   compute_address;
   get_data; // next 8 bits are dont care
   if (skip == 1'b1)
     @(posedge SCK); // skip one SCK
   read_out (1, current_address, page_boundary_low, page_boundary_high);
end
 
 
 
/******* Buffer 2 Read ********************/
 
always @(B2R)
begin : B2R_
   get_data; // first 8 bits are dont care
   get_data;
        // For buffers, PageAddress can be assumed as "0".
        // This will allow us to share code with MMPR;
   page [PADDRESS-1:0] = 'h0;
 
   compute_byte_new_address;
 
      // next 8 bits always contain byte_new-address[7:0], and, so is
      // not dependent on parameters
   get_data;
   byte_new[7:0] = read_data[7:0];
 
   compute_address;
   get_data; // next 8 bits are don't care
   if (skip == 1'b1)
     @(posedge SCK); // skip one SCK
   read_out (2, current_address, page_boundary_low, page_boundary_high);
end
 
 
/******* Main Memory Page To Buffer 1 Transfer *****************/
 
always @(MMPTB1T)
begin : MMPTB1T_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Main Memory To Buffer Transfer is not allowed");
     disable MMPTB1T_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
 
   get_data; // This is dont_care
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
   transfer_to_buffer (1, page_boundary_low);
   updating_buffer1 = 1'b1;
   #tXFR RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   updating_buffer1 = 1'b0;
end
 
 
/******* Main Memory Page To Buffer 2 Transfer *****************/
 
always @(MMPTB2T)
begin : MMPTB2T_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Main Memory To Buffer Transfer is not allowed");
     disable MMPTB2T_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
 
   get_data; // This is dont_care
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
   transfer_to_buffer (2, page_boundary_low);
   updating_buffer2 = 1'b1;
   #tXFR RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   updating_buffer2 = 1'b0;
end
 
 
/******* Main Memory Page To Buffer 1 Compare *****************/
 
always @(MMPTB1C)
begin : MMPTB1C_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Main Memory To Buffer Compare is not allowed");
     disable MMPTB1C_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
 
   get_data; // This is dont_care
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
   compare_with_buffer (1, page_boundary_low);
   comparing = 1'b1;
   #tXFR RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   comparing = 1'b0;
end
 
 
 
/******* Main Memory Page To Buffer 2 Compare *****************/
 
always @(MMPTB2C)
begin : MMPTB2C_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Main Memory To Buffer Compare is not allowed");
     disable MMPTB2C_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
 
   get_data; // This is dont_care
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
   compare_with_buffer (2, page_boundary_low);
   comparing = 1'b1;
   #tXFR RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   comparing = 1'b0;
end
 
 
/*******    Buffer 1 Write *****************/
 
always @(B1W)
begin : B1W_
   get_data; // dont care bits
   get_data;
            // got some address bits, depending on device parameters
   compute_byte_new_address;
   get_data;
   byte_new[7:0] = read_data [7:0];
 
   page[PADDRESS-1:0] = 'h0; // buffer is equivalent to just one page
 
   compute_address; 
 
   write_data (1);
 
end
 
 
/*******    Buffer 2 Write *****************/
 
always @(B2W)
begin : B2W_
   get_data; // dont care bits
   get_data;
            // got some address bits, depending on device parameters
   compute_byte_new_address;
   get_data;
   byte_new[7:0] = read_data [7:0];
 
   page[PADDRESS-1:0] = 'h0; // buffer is equivalent to just one page
 
   compute_address; 
 
   write_data (2);
 
end
 
 
/******* Buffer 1 To Main Memory Page Prog With Built In Erase *******/
 
always @(B1TMMPPWBIE)
begin : B1TMMPPWBIE_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Buffer To Main Memory Page Prog. is not allowed");
     disable B1TMMPPWBIE_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
 
   get_data; // This is dont_care
 
   if ((WPB == 1'b0) && (page < PROTECTED))
   begin
     $display ("Cann't write: Page No. %d is Protected, becase WPB is Low", page);        
     disable B1TMMPPWBIE_ ;
   end
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
   write_to_memory (1, page_boundary_low);
   updating_memory = 1'b1;
   #tEP RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   updating_memory = 1'b0;
end
 
 
/******* Buffer 2 To Main Memory Page Prog With Built In Erase *******/
 
always @(B2TMMPPWBIE)
begin : B2TMMPPWBIE_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Buffer To Main Memory Page Prog. is not allowed");
     disable B2TMMPPWBIE_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
 
   get_data; // This is dont_care
 
   if ((WPB == 1'b0) && (page < PROTECTED))
   begin
     $display ("Cann't write: Page No. %d is Protected, becase WPB is Low", page);        
     disable B2TMMPPWBIE_ ;
   end
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
   write_to_memory (2, page_boundary_low);
   updating_memory = 1'b1;
   #tEP RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   updating_memory = 1'b0;
end
 
 
/******* Buffer 1 To Main Memory Page Prog WithOut Built In Erase *******/
 
always @(B1TMMPPWOBIE)
begin : B1TMMPPWOBIE_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Buffer To Main Memory Page Prog. is not allowed");
     disable B1TMMPPWOBIE_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
 
   get_data; // This is dont_care
 
   if ((WPB == 1'b0) && (page < PROTECTED))
   begin
     $display ("Cann't write: Page No. %d is Protected, becase WPB is Low", page);        
     disable B1TMMPPWOBIE_ ;
   end
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   if (page_status[page] == 1'b0) // page is already erased
   begin
      RDYBSY_reg = 1'b1; // device is busy
      status[7] = 1'b0;
      write_to_memory (1, page_boundary_low);
      updating_memory = 1'b1;
      #tP RDYBSY_reg = 1'b0; // device is now ready
      status[7] = 1'b1;
      updating_memory = 1'b0;
   end
   else
      $display ("Trying to write into Page %d which is not erased", page);
end
 
 
/******* Buffer 2 To Main Memory Page Prog WithOut Built In Erase *******/
 
always @(B2TMMPPWOBIE)
begin : B2TMMPPWOBIE_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Buffer To Main Memory Page Prog. is not allowed");
     disable B2TMMPPWOBIE_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
 
   get_data; // This is dont_care
 
   if ((WPB == 1'b0) && (page < PROTECTED))
   begin
     $display ("Cann't write: Page No. %d is Protected, becase WPB is Low", page);        
     disable B2TMMPPWOBIE_ ;
   end
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   if (page_status[page] == 1'b0) // page is already erased
   begin
      RDYBSY_reg = 1'b1; // device is busy
      status[7] = 1'b0;
      updating_memory = 1'b1;
      write_to_memory (2, page_boundary_low);
      #tP RDYBSY_reg = 1'b0; // device is now ready
      status[7] = 1'b1;
      updating_memory = 1'b0;
   end
   else
      $display ("Trying to write into Page %d which is not erased", page);
end
 
 
/******* Page Erase *******/
 
always @(PE)
begin : PE_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Page Erase is not allowed");
     disable PE_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
 
   get_data; // This is dont_care
 
   if ((WPB == 1'b0) && (page < PROTECTED))
   begin
     $display ("Cann't Erase: Page No. %d is Protected, becase WPB is Low", page);        
     disable PE_ ;
   end
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
   erase_page ( page_boundary_low);
   erasing_page = 1'b1;
   #tPE RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   erasing_page = 1'b0;
end
 
 
/******* Block Erase *******/
 
always @(BE)
begin : BE_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Block Erase is not allowed");
     disable BE_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
   page [2:0] = 3'h0; // lowest page of the block
 
   get_data; // This is dont_care
 
   if ((WPB == 1'b0) && (page < PROTECTED))
   begin
     $display ("Cann't Erase: Block starting at Page No. %d is Protected, becase WPB is Low", page);        
     disable BE_ ;
   end
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
 
   for (j=page_boundary_low; j<(page_boundary_low+8*PAGESIZE); j=j+PAGESIZE)
      erase_page ( j ); // erase 8 pages, i.e. a block
 
   for (j=0; j<8; j=j+1) // erase_page will only change the status of one-page 
     page_status[page+j] = 1'b0; // hence, changing the remaining ones explicitly
 
   erasing_block = 1'b1;
   #tBE RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   erasing_block = 1'b0;
end
 
/******* Main Memory Page Prog Through Buffer 1 *******/
 
always @(MMPPB1)
begin : MMPPB1_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Main Memory Page Prog. is not allowed");
     disable MMPPB1_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress/ByteAddress according to the parameters
   compute_page_address;
   compute_byte_new_address;
   temp_reg2[7:0] = read_data [7:0];
   get_data; 
   byte_new[7:0] = read_data[7:0];
   temp_page = page; // page value has been stored for main memory page program
 
 
   page[PADDRESS-1:0] = 'h0; // Buffer is 0 pages
 
   compute_address; // this computes where to write in buffer
 
   write_data (1); // this will write to buffer
                   // it will proceed to next step, when, posedge of CSB.
                   // This is complicated, and, hence, explained here:
                   // At posedge of CSB, the write_data will get disabled.
                   // At this time, writing to buffer needs to stop, and,
                   // writing into memory should start.
 
   page[PADDRESS-1:0] = temp_page[PADDRESS-1:0]; // page address in Main Memory to which
                                                 // data needs to be written
   if ((WPB == 1'b0) && (page < PROTECTED))
   begin
     $display ("Cann't Write: Page No. %d is Protected, becase WPB is Low", page);        
     disable MMPPB1_ ;
   end
 
   compute_address; // even if byte_new-address is junk, we only need Page_Low_Boundary
 
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
   write_to_memory (1, page_boundary_low);
   updating_memory = 1'b1;
   #tEP RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   updating_memory = 1'b0;
end
 
 
/******* Main Memory Page Prog Through Buffer 2 *******/
 
always @(MMPPB2)
begin : MMPPB2_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Main Memory Page Prog. is not allowed");
     disable MMPPB2_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress/ByteAddress according to the parameters
   compute_page_address;
   compute_byte_new_address;
   temp_reg2[7:0] = read_data [7:0];
   get_data; 
   // Third byte_new is always for byte_new address[7:0]
   byte_new[7:0] = read_data[7:0];
 
   temp_page = page; // page value has been stored for main memory page program
 
   page[PADDRESS-1:0] = 'h0; // Buffer is 0 pages
 
   compute_address; // this computes where to write in buffer
 
   write_data (2); // this will write to buffer
                   // it will proceed to next step, when, posedge of CSB.
                   // This is complicated, and, hence, explained here:
                   // At posedge of CSB, the write_data will get disabled.
                   // At this time, writing to buffer needs to stop, and,
                   // writing into memory should start.
 
   page[PADDRESS-1:0] = temp_page[PADDRESS-1:0]; // page address in Main Memory to which
                                                 // data needs to be written
   if ((WPB == 1'b0) && (page < PROTECTED))
   begin
     $display ("Cann't Write: Page No. %d is Protected, becase WPB is Low", page);        
     disable MMPPB2_ ;
   end
 
   compute_address; // even if byte_new-address is junk, we only need Page_Low_Boundary
 
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
   write_to_memory (2, page_boundary_low);
   updating_memory = 1'b1;
   #tEP RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   updating_memory = 1'b0;
end
 
 
/******* Auto Page Rewrite Through Buffer 1 *****************/
 
always @(APRB1)
begin : APRB1_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Auto Page Rewrite is not allowed");
     disable APRB1_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
 
   get_data; // This is dont_care
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   transfer_to_buffer (1, page_boundary_low);
   updating_buffer1 = 1'b1;
 
   if ((WPB == 1'b0) && (page < PROTECTED))
   begin
     $display ("Cann't ReWrite: Page No. %d is Protected, becase WPB is Low", page);        
     #tEP updating_buffer1 = 1'b0;
     disable APRB1_ ;
   end
 
   updating_memory = 1'b1;
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
   #tEP RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   updating_buffer1 = 1'b0;
   updating_memory = 1'b0;
   // NOTE:
   // We dont need to rewrite the data back into main-memory, as the 
   //        data is already available in the main-memory
   // This task was exactly same as MMPTB1T, except the delay-value
   //      We could have easily used the same code as MMPTB1T, using 
   //      an if condition for delay-selection. However, still doing
   //      this way, so that the code for each opcode is independent
   //      of anything else.
end
 
 
/******* Auto Page Rewrite Through Buffer 2 *****************/
 
always @(APRB2)
begin : APRB2_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Auto Page Rewrite is not allowed");
     disable APRB2_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress according to the parameters
   compute_page_address;
 
   get_data; // This is dont_care
 
   compute_address; // even though, byte_new-address could be junk,
                    // we are only interested in Low page-boundaries,
                    // which can be obtained correctly
   @ (posedge CSB);
   transfer_to_buffer (2, page_boundary_low);
   updating_buffer2 = 1'b1;
 
   if ((WPB == 1'b0) && (page < PROTECTED))
   begin
     $display ("Cann't ReWrite: Page No. %d is Protected, becase WPB is Low", page);        
     #tEP updating_buffer2 = 1'b0;
     disable APRB2_ ;
   end
 
   RDYBSY_reg = 1'b1; // device is busy
   status[7] = 1'b0;
   updating_memory = 1'b1;
   #tEP RDYBSY_reg = 1'b0; // device is now ready
   status[7] = 1'b1;
   updating_buffer2 = 1'b0;
   updating_memory = 1'b0;
   // NOTE:
   // We dont need to rewrite the data back into main-memory, as the 
   //        data is already available in the main-memory
   // This task was exactly same as MMPTB2T, except the delay-value
   //      We could have easily used the same code as MMPTB2T, using 
   //      an if condition for delay-selection. However, still doing
   //      this way, so that the code for each opcode is independent
   //      of anything else.
end
 
 
/********* Status Register Read ********************/
 
always @(SR)
begin: SR_
  status_read = 1'b1; // reading status_reg
  j = 8;
   if (skip == 1'b1)
     @(posedge SCK); // skip one SCK
  while (CSB == 1'b0)
  begin
    @(negedge SCK);
    #tV ;
    if (j > 0) 
       j = j-1;
    else
       j = 7;
    SO_reg=status[j];
    SO_on = 1'b1;
    SO_reg = status[j];
  end // output next bit on next falling edge of SCK
  status_read = 1'b0; // status_reg read is over
 
end
 
always @(negedge RDYBSY_reg) // this block to take care of situations,
                             // where status gets changed, while, it
                             // is being read.
                             // Applicable only in cases, where, device gets
                             // ready, from busy.
   if (status_read == 1'b1)  
      SO_reg = status[j];    // No harm, even if we have done this for other bits
                             // of status_reg
 
 
/******* Main Memory Continuous Read ********************/
 
always @(RWOPR)
begin : RWOPR_
   if (RDYBSY_reg == 1'b1) // device is already busy
   begin
     $display ("Device is busy. Main Memory Page Read is not allowed");
     disable RWOPR_ ;     
   end
         // if it comes here, means, the above if was false.
   get_data;
   temp_reg1[7:0] = read_data [7:0];
   get_data;
 
        // Now that the two byte_news have been obtained, distribute it 
        // within PageAddress and byte_new-address, according to 
        // the parameters.
   compute_page_address;
   compute_byte_new_address;
 
      // next 8 bits always contain byte_new-address[7:0], and, so is
      // not dependent on parameters
   get_data;
   byte_new[7:0] = read_data[7:0];
 
   for (j=0; j<4; j=j+1)
      get_data ;  // these 32 bits are dont-care, and so have been discarded.
 
   compute_address;
   if (skip == 1'b1)
     @(posedge SCK); // skip one SCK
   read_out_array ;
end
 
 
/******** Posedge CSB. Stop all reading, recvng. commands/addresses etc. *********/
 
always @(posedge CSB)
begin
  disable MMPR_; // MMPR will stop, if CSB goes high
  disable RWOPR_; // RWOPR will stop, if CSB goes high
 
  disable B1R_; // B1R will stop, if CSB goes high
 
  disable B2R_; // B2R will stop, if CSB goes high
 
  disable B1W_; // B1W will stop, if CSB goes high
 
  disable B2W_; // B2W will stop, if CSB goes high
 
  disable SR_; // Status reading should stop.
  status_read = 1'b0; 
 
  disable read_out; // Stop reading, NOW
  disable read_out_array; 
  disable get_data; // Stop data retrieval
  disable write_data; // Stop writing to buffers, NOW
 
  #tDIS SO_on = 1'b0;  // SO is now in high-impedance
end
 
 
/******** RESETB asserted. ******************/
 
always @(negedge RESETB)
begin 
                               // stop doing whatever you were doing
  disable get_opcode;
  disable MMPR_;
  disable B1R_;
  disable B2R_;
  disable MMPTB1T_;
  disable MMPTB2T_;
  disable MMPTB1C_;
  disable MMPTB2C_;
  disable B1W_;
  disable B2W_;
  disable B1TMMPPWBIE_;
  disable B2TMMPPWBIE_;
  disable B1TMMPPWOBIE_;
  disable B2TMMPPWOBIE_;
  disable PE_;
  disable BE_;
  disable MMPPB1_;
  disable MMPPB2_;
  disable APRB1_;
  disable APRB2_;
                            // if you were in the middle of some prog. that part
                            //                  is now unknown.
  if (updating_buffer1 == 1'b1)
  begin
    $display("RESETB asserted, when, updating Buffer1. Corrupting Buffer1");
    corrupt_buffer (1);
    updating_buffer1 = 1'b0;
  end
 
  if (updating_buffer2 == 1'b1)
  begin
    $display("RESETB asserted, when, updating Buffer2. Corrupting Buffer1");
    corrupt_buffer (2);
    updating_buffer2 = 1'b0;
  end
 
  if (comparing == 1'b1)
  begin
    $display("RESETB asserted, when, comparing. Corrupting Status Bit 6");
    status[6] = 1'bx; // unknown
    comparing = 1'b0;
  end
 
  if (updating_memory == 1'b1)
  begin
    $display("RESETB asserted, when, updating memory. Corrupting Memory Page");
    corrupt_memory ;
    updating_memory = 1'b0;
  end
 
  if (erasing_page == 1'b1)
  begin
    $display("RESETB asserted, when, erasing page. Corrupting Memory Page");
    corrupt_memory ;
    erasing_page = 1'b0;
  end
 
  if (erasing_block == 1'b1)
  begin
    $display("RESETB asserted, when, erasing block. Corrupting Memory Block");
    corrupt_block ;
    erasing_block = 1'b0;
  end
 
 // SO also, needs to go to high-state, as well as the device needs to be Ready.
 SO_on = 1'b0; 
 RDYBSY_reg = 1'b0;
 
end
 
 
/************************ TASKS / FUNCTIONS **************************/
 
/* get_data is a task to get 8 bits of data. This data could be an opcode,
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;
   end
end
 
endtask
 
 
/* compute_address is a task which to compute the current address, 
as well as obtain the page boundaries */
 
task compute_address;
 
begin
  page_boundary_low = page * PAGESIZE; 
  page_boundary_high = page_boundary_low + (PAGESIZE - 1);
  current_address = page_boundary_low + byte_new;
  if (current_address < 540672)
      mem_no = 10;
  else if (current_address < 1081344)
      mem_no = 11;
  else if (current_address < 1622016)
      mem_no = 12;
  else if (current_address < 2162688)
      mem_no = 13;
  else if (current_address < 2703360)
      mem_no = 14;
  else if (current_address < 3244032)
      mem_no = 15;
  else if (current_address < 3784704)
      mem_no = 16;
  else mem_no = 17;
end
 
endtask
 
/* read_out will read the output on SO pin. It can read contents of mainmemory, or,
either of the two buffers */
 
task read_out ;
input mem_type;
input add;
input low;
input high;
 
integer mem_type;
integer add;
integer low;
integer high;
 
integer i;
 
begin
  if (mem_type == 1)
     temp_reg1 = buffer1 [add];
  else if (mem_type == 2)
     temp_reg1 = buffer2 [add];
 
  else if (mem_type == 10)
     temp_reg1 = memory0 [add];
  else if (mem_type == 11)
     temp_reg1 = memory1 [add];
  else if (mem_type == 12)
     temp_reg1 = memory2 [add];
  else if (mem_type == 13)
     temp_reg1 = memory3 [add];
  else if (mem_type == 14)
     temp_reg1 = memory4 [add];
  else if (mem_type == 15)
     temp_reg1 = memory5 [add];
  else if (mem_type == 16)
     temp_reg1 = memory6 [add];
  else if (mem_type == 17)
     temp_reg1 = memory7 [add];
  else
     $display ("Int Error 1. This message should never appear. Something is wrong");
 
   i = 7;
   while (CSB == 1'b0) // continue transmitting, while, CSB is Low
   begin : CONTINUE_READING
      @(negedge SCK) ;
      #tV SO_reg = temp_reg1[i];
          SO_on = 1'b1; 
      if (i == 0) 
        begin
          add = add + 1; // next byte_new
          i = 7;
          if (add > high)
              add = low; // Page rollover
 
          if (mem_type == 1)
             temp_reg1 = buffer1 [add];
          else if (mem_type == 2)
             temp_reg1 = buffer2 [add];
 
          else if (mem_type == 10)
             temp_reg1 = memory0 [add];
          else if (mem_type == 11)
             temp_reg1 = memory1 [add];
          else if (mem_type == 12)
             temp_reg1 = memory2 [add];
          else if (mem_type == 13)
             temp_reg1 = memory3 [add];
          else if (mem_type == 14)
             temp_reg1 = memory4 [add];
          else if (mem_type == 15)
             temp_reg1 = memory5 [add];
          else if (mem_type == 16)
             temp_reg1 = memory6 [add];
          else if (mem_type == 17)
             temp_reg1 = memory7 [add];
 
        end
      else
        i = i - 1; // next bit
 
   end // reading over, because CSB has gone high
end
 
endtask
 
/* task read_out_array is to read from main Memory, either in 
          Continuous Mode, or, in Burst Mode */
 
task read_out_array ;
 
integer i;
integer temp_mem;
integer temp_current;
integer temp_high;
integer temp_low;
integer temp_add;
 
begin
  temp_mem = mem_no;
  temp_high = page_boundary_high;
  temp_low = page_boundary_low;
  temp_add = current_address;
 
  if (temp_mem == 10)
     temp_reg1 = memory0 [temp_add];
  else if (temp_mem == 11)
     temp_reg1 = memory1 [temp_add];
  else if (temp_mem == 12)
     temp_reg1 = memory2 [temp_add];
  else if (temp_mem == 13)
     temp_reg1 = memory3 [temp_add];
  else if (temp_mem == 14)
     temp_reg1 = memory4 [temp_add];
  else if (temp_mem == 15)
     temp_reg1 = memory5 [temp_add];
  else if (temp_mem == 16)
     temp_reg1 = memory6 [temp_add];
  else if (temp_mem == 17)
     temp_reg1 = memory7 [temp_add];
  else
     $display ("Int Error 1. This message should never appear. Something is wrong");
 
   i = 7;
   while (CSB == 1'b0) // continue transmitting, while, CSB is Low
   begin : CONTINUE_READING
      @(negedge SCK) ;
      #tV SO_reg = temp_reg1[i];
          SO_on = 1'b1; 
      if (i == 0) 
        begin
          temp_add = temp_add + 1; // next byte_new
          i = 7;
          if (temp_add >= MEMSIZE)
          begin
              temp_add = 0; // Note that rollover occurs at end of memory,
              temp_high = PAGESIZE - 1; // and not at the end of the page
              temp_low = 0;
          end
          if (temp_add > temp_high) // going to next page
          begin
             temp_high = temp_high + PAGESIZE;
             temp_low = temp_low + PAGESIZE;
          end
 
          if (temp_add > 3784703)  // this block is a kludge to take
             temp_mem = 17;        // care of multiple memory declarations
          else if (temp_add > 3244031) // in the model, due to limitation
             temp_mem = 16;            // of Verilog
          else if (temp_add > 2703359)
             temp_mem = 15;
          else if (temp_add > 2162687)
             temp_mem = 14;
          else if (temp_add > 1622015)
             temp_mem = 13;
          else if (temp_add > 1081343)
             temp_mem = 12;
          else if (temp_add > 540671)
             temp_mem = 11;
          else temp_mem = 10;
 
          if (temp_mem == 10)
             temp_reg1 = memory0 [temp_add];
          else if (temp_mem == 11)
             temp_reg1 = memory1 [temp_add];
          else if (temp_mem == 12)
             temp_reg1 = memory2 [temp_add];
          else if (temp_mem == 13)
             temp_reg1 = memory3 [temp_add];
          else if (temp_mem == 14)
             temp_reg1 = memory4 [temp_add];
          else if (temp_mem == 15)
             temp_reg1 = memory5 [temp_add];
          else if (temp_mem == 16)
             temp_reg1 = memory6 [temp_add];
          else if (temp_mem == 17)
             temp_reg1 = memory7 [temp_add];
 
        end
      else
        i = i - 1; // next bit
   end // reading over, because CSB has gone high
end
 
endtask
 
 
/* transfer_to_buffer will transfer data into a buffer from a page of
main memory */
 
/* transfer_to_buffer will transfer data into a buffer from a page of
main memory */
 
task transfer_to_buffer ;
input buf_type;
input low;
 
integer buf_type;
integer low;
 
integer i;
 
begin
       // Intentionally written this way: i.e. the for loop is within all if.
       // Writing in alternative way would cause shorter code, but, significant
       // increase in simulation time.
  if (buf_type == 1)
  begin
    if (mem_no == 10)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer1[i] = memory0[low+i];
    else if (mem_no == 11)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer1[i] = memory1[low+i];
    else if (mem_no == 12)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer1[i] = memory2[low+i];
    else if (mem_no == 13)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer1[i] = memory3[low+i];
    else if (mem_no == 14)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer1[i] = memory4[low+i];
    else if (mem_no == 15)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer1[i] = memory5[low+i];
    else if (mem_no == 16)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer1[i] = memory6[low+i];
    else if (mem_no == 17)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer1[i] = memory7[low+i];
    else $display ("Should Never reach here. Something is wrong");
  end
 
  else if (buf_type == 2)
  begin
    if (mem_no == 10)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer2[i] = memory0[low+i];
    else if (mem_no == 11)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer2[i] = memory1[low+i];
    else if (mem_no == 12)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer2[i] = memory2[low+i];
    else if (mem_no == 13)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer2[i] = memory3[low+i];
    else if (mem_no == 14)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer2[i] = memory4[low+i];
    else if (mem_no == 15)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer2[i] = memory5[low+i];
    else if (mem_no == 16)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer2[i] = memory6[low+i];
    else if (mem_no == 17)
       for (i=0 ; i < PAGESIZE; i = i+1)
          buffer2[i] = memory7[low+i];
    else $display ("Should Never reach here. Something is wrong");
  end
 
  else
     $display ("Int Error 2. This message should never appear. Something is wrong");
 
end
 
endtask
 
 
/* compare_with_buffer will compare data into a buffer against a page of
main memory */
 
task compare_with_buffer ;
input buf_type;
input low;
 
integer buf_type;
integer low;
 
integer i, k;
reg [7:0] tmp1, tmp2;
 
begin
 
  status[6] = 1'b0;
  if (buf_type == 1)
    for (i=0 ; i < PAGESIZE; i = i+1)
    begin : LOOP1
       if (mem_no == 10)
          tmp1 = memory0[low+i];
       else if (mem_no == 11)
          tmp1 = memory1[low+i];
       else if (mem_no == 12)
          tmp1 = memory2[low+i];
       else if (mem_no == 13)
          tmp1 = memory3[low+i];
       else if (mem_no == 14)
          tmp1 = memory4[low+i];
       else if (mem_no == 15)
          tmp1 = memory5[low+i];
       else if (mem_no == 16)
          tmp1 = memory6[low+i];
       else if (mem_no == 17)
          tmp1 = memory7[low+i];
       else $display ("should never reach here. Something went wrong");
       tmp2 = buffer1[i];
       for (k=0; k < 8; k = k+1)
           if (tmp1[k] !== tmp2[k])
           begin  // detected miscompare. No need for further comparison
             status[6] = 1'b1;
             disable LOOP1;
           end
    end
  else if (buf_type == 2)
    for (i=0 ; i < PAGESIZE; i = i+1)
    begin : LOOP2
       if (mem_no == 10)
          tmp1 = memory0[low+i];
       else if (mem_no == 11)
          tmp1 = memory1[low+i];
       else if (mem_no == 12)
          tmp1 = memory2[low+i];
       else if (mem_no == 13)
          tmp1 = memory3[low+i];
       else if (mem_no == 14)
          tmp1 = memory4[low+i];
       else if (mem_no == 15)
          tmp1 = memory5[low+i];
       else if (mem_no == 16)
          tmp1 = memory6[low+i];
       else if (mem_no == 17)
          tmp1 = memory7[low+i];
       else $display ("should never reach here. Something went wrong");
       tmp2 = buffer2[i];
       for (k=0; k < 8; k = k+1)
           if (tmp1[k] !== tmp2[k])
           begin  // detected miscompare. No need for further comparison
             status[6] = 1'b1;
             disable LOOP2;
           end
    end
  else
     $display ("Int error 3. This message should never appear. Something is wrong");
 
end
 
endtask
 
 
/* write_data will gat data from SI, and, write into device */
 
task write_data ;
input buf_type;
 
integer buf_type;
 
integer i;
 
begin
 
   while (CSB == 1'b0)
   begin
     for (i=7; i>=0; i=i-1)
     begin
       @(posedge SCK);
       temp_reg1[i] = SI;
     end // Complete byte_new recvd. Now transfer the byte_new to memory/buffer
 
   if (buf_type == 1)  // Buffer 1
      buffer1[current_address] = temp_reg1;
   else if (buf_type == 2) // Buffer 2
      buffer2[current_address] = temp_reg1;
   else
     $display ("Int error 4. This message should never appear. Something is wrong");
 
   current_address = current_address + 1;
   if (current_address > page_boundary_high)
       current_address = page_boundary_low;
 
   end // continue writing. Note that parts of a byte_new will not be written.
 
end
 
endtask
 
 
/* write_to_memory will transfer data from a buffer into a page of
main memory */
 
task write_to_memory ;
input buf_type;
input low;
 
integer buf_type;
integer low;
 
integer i;
 
begin
 
  if (buf_type == 1)
  begin
    if (mem_no == 10)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory0[low+i] = buffer1[i];
    else if (mem_no == 11)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory1[low+i] = buffer1[i];
    else if (mem_no == 12)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory2[low+i] = buffer1[i];
    else if (mem_no == 13)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory3[low+i] = buffer1[i];
    else if (mem_no == 14)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory4[low+i] = buffer1[i];
    else if (mem_no == 15)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory5[low+i] = buffer1[i];
    else if (mem_no == 16)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory6[low+i] = buffer1[i];
    else if (mem_no == 17)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory7[low+i] = buffer1[i];
    else $display ("should never reach here. Something is wrong");
  end
  else if (buf_type == 2)
  begin
    if (mem_no == 10)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory0[low+i] = buffer2[i];
    else if (mem_no == 11)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory1[low+i] = buffer2[i];
    else if (mem_no == 12)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory2[low+i] = buffer2[i];
    else if (mem_no == 13)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory3[low+i] = buffer2[i];
    else if (mem_no == 14)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory4[low+i] = buffer2[i];
    else if (mem_no == 15)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory5[low+i] = buffer2[i];
    else if (mem_no == 16)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory6[low+i] = buffer2[i];
    else if (mem_no == 17)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory7[low+i] = buffer2[i];
    else $display ("should never reach here. Something is wrong");
  end
  else 
    $display ("Int error 4. This message should never appear. Something is wrong");
 
   page_status[page] = 1'b1; // this page is now not erased
end
 
endtask
 
 
/* erase_page will erase a page of main memory */
 
task erase_page ;
input low;
 
integer low;
 
integer i;
 
begin
    if (mem_no == 10)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory0[low+i] = 8'hff;
    else if (mem_no == 11)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory1[low+i] = 8'hff;
    else if (mem_no == 12)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory2[low+i] = 8'hff;
    else if (mem_no == 13)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory3[low+i] = 8'hff;
    else if (mem_no == 14)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory4[low+i] = 8'hff;
    else if (mem_no == 15)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory5[low+i] = 8'hff;
    else if (mem_no == 16)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory6[low+i] = 8'hff;
    else if (mem_no == 17)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory7[low+i] = 8'hff;
    else $display ("should never reach here. Something is wrong");
 
   page_status[page] = 1'b0; // this page is now erased
end
 
endtask
 
 
/* corrupt_buffer will corrupt the entire buffer */
 
task corrupt_buffer ;
input buf_type;
 
integer buf_type;
 
integer i;
 
begin
 
  if (buf_type == 1)
    for (i=0 ; i < PAGESIZE; i = i+1)
       buffer1[i] = 8'hx;
  else if (buf_type == 2)
    for (i=0 ; i < PAGESIZE; i = i+1)
       buffer2[i] = 8'hx;
  else
     $display ("Int Error 2. This message should never appear. Something is wrong");
 
end
 
endtask
 
 
/* corrupt_memory will corrupt a page of memory */
 
task corrupt_memory ;
 
integer i;
 
begin
    if (mem_no == 10)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory0[page_boundary_low+i] = 8'hx;
    else if (mem_no == 11)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory1[page_boundary_low+i] = 8'hx;
    else if (mem_no == 12)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory2[page_boundary_low+i] = 8'hx;
    else if (mem_no == 13)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory3[page_boundary_low+i] = 8'hx;
    else if (mem_no == 14)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory4[page_boundary_low+i] = 8'hx;
    else if (mem_no == 15)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory5[page_boundary_low+i] = 8'hx;
    else if (mem_no == 16)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory6[page_boundary_low+i] = 8'hx;
    else if (mem_no == 17)
       for (i=0 ; i < PAGESIZE; i = i+1)
          memory7[page_boundary_low+i] = 8'hx;
    else $display ("should never reach here. something is wrong");
 
   page_status[page] = 1'b1; // Actually, sometimes, the status of this page is
                             // unknown. But, using UnErased, is also OK here.
                             // Because, either way, user has to erase, in order
                             // to Program the page
end
 
endtask
 
 
/* corrupt_block will corrupt a block (i.e. 8 pages) of memory */
 
task corrupt_block ;
 
integer i;
 
begin
    if (mem_no == 10)
       for (i=0 ; i < PAGESIZE*8; i = i+1)
          memory0[page_boundary_low+i] = 8'hx; // corrupted 8 pages
    else if (mem_no == 11)
       for (i=0 ; i < PAGESIZE*8; i = i+1)
          memory1[page_boundary_low+i] = 8'hx; // corrupted 8 pages
    else if (mem_no == 12)
       for (i=0 ; i < PAGESIZE*8; i = i+1)
          memory2[page_boundary_low+i] = 8'hx; // corrupted 8 pages
    else if (mem_no == 13)
       for (i=0 ; i < PAGESIZE*8; i = i+1)
          memory3[page_boundary_low+i] = 8'hx; // corrupted 8 pages
    else if (mem_no == 14)
       for (i=0 ; i < PAGESIZE*8; i = i+1)
          memory4[page_boundary_low+i] = 8'hx; // corrupted 8 pages
    else if (mem_no == 15)
       for (i=0 ; i < PAGESIZE*8; i = i+1)
          memory5[page_boundary_low+i] = 8'hx; // corrupted 8 pages
    else if (mem_no == 16)
       for (i=0 ; i < PAGESIZE*8; i = i+1)
          memory6[page_boundary_low+i] = 8'hx; // corrupted 8 pages
    else if (mem_no == 17)
       for (i=0 ; i < PAGESIZE*8; i = i+1)
          memory7[page_boundary_low+i] = 8'hx; // corrupted 8 pages
    else $display ("should never reach here. Something is wrong");
 
    for (i=0 ; i < 8; i = i+1)
       page_status[page+i] = 1'b1; // Actually, sometimes, the status of this page is
                                   //   unknown. But, using UnErased, is also OK here.
                                   //   Because, either way, user has to erase, in order
                                   //   to Program the page
end
 
endtask
 
 
/* Task to compute page address */
 
task compute_page_address;
begin
   page = 0; // zero out the redundant bits of 'page'
   case (PADDRESS) 
      13 : begin
             page [12:6] = temp_reg1[6:0] ;
             page [5:0] = read_data[7:2] ;
           end
      12 : begin
             if (status[5:3] == 3'b100)
             begin
               page [11:7] = temp_reg1[4:0] ;
               page [6:0] = read_data[7:1] ;
             end
             if (status[5:3] == 3'b101)
             begin
               page [11:6] = temp_reg1[5:0] ;
               page [5:0] = read_data[7:2] ;
             end
           end
      11 : begin
             page [10:7] = temp_reg1[3:0] ;
             page [6:0] = read_data[7:1] ;
           end
      10 : begin
             page [9:7] = temp_reg1[2:0] ;
             page [6:0] = read_data[7:1] ;
           end
       9 : begin
             page [8:7] = temp_reg1[1:0] ;
             page [6:0] = read_data[7:1] ;
           end
   endcase
end
endtask
 
/* Task to compute starting byte_new address */
 
task compute_byte_new_address;
begin
   case (BADDRESS)
      10 : byte_new[9:8] = read_data[1:0] ;
       9 : byte_new[8]   = read_data[0] ;
   endcase
end
endtask
 
/* SPECIFY BLOCK */
 
specify  /* all timing checks */
 
`ifdef device1M
specparam tSCK = 77  ; // SCK time-period. 10e9/fSCK
specparam tWH = 35;
specparam tWL = 35;
specparam tCS = 250;
specparam tCSS = 250;
specparam tCSH = 250;
specparam tCSB = 200;
specparam tSU = 10;
specparam tH = 20;
specparam tHO = 0;
specparam tRST = 10000;
specparam tREC = 1000;
specparam tBAR = 200;
specparam tCAR1 = 200; // this is same as tCAR, but, is needed twice
specparam tBRBD = 1000;
`endif
 
`ifdef device2M
specparam tSCK = 77  ; // SCK time-period. 10e9/fSCK
specparam tWH = 35;
specparam tWL = 35;
specparam tCS = 250;
specparam tCSS = 250;
specparam tCSH = 250;
specparam tCSB = 200;
specparam tSU = 10;
specparam tH = 20;
specparam tHO = 0;
specparam tRST = 10000;
specparam tREC = 1000;
specparam tBAR = 200;
specparam tCAR1 = 200; // this is same as tCAR, but, is needed twice
specparam tBRBD = 1000;
`endif
 
`ifdef device4M
specparam tSCK = 77  ; // SCK time-period. 10e9/fSCK
specparam tWH = 35;
specparam tWL = 35;
specparam tCS = 250;
specparam tCSS = 250;
specparam tCSH = 250;
specparam tCSB = 200;
specparam tSU = 10;
specparam tH = 20;
specparam tHO = 0;
specparam tRST = 10000;
specparam tREC = 1000;
specparam tBAR = 200;
specparam tCAR1 = 200; // this is same as tCAR, but, is needed twice
specparam tBRBD = 1000;
`endif
 
`ifdef device8M
specparam tSCK = 77  ; // SCK time-period. 10e9/fSCK
specparam tWH = 35;
specparam tWL = 35;
specparam tCS = 250;
specparam tCSS = 250;
specparam tCSH = 250;
specparam tCSB = 200;
specparam tSU = 10;
specparam tH = 20;
specparam tHO = 0;
specparam tRST = 10000;
specparam tREC = 1000;
specparam tBAR = 200;
specparam tCAR1 = 200; // this is same as tCAR, but, is needed twice
specparam tBRBD = 1000;
`endif
 
`ifdef device16M
specparam tSCK = 77  ; // SCK time-period. 10e9/fSCK
specparam tWH = 35;
specparam tWL = 35;
specparam tCS = 250;
specparam tCSS = 250;
specparam tCSH = 250;
specparam tCSB = 200;
specparam tSU = 10;
specparam tH = 20;
specparam tHO = 0;
specparam tRST = 10000;
specparam tREC = 1000;
specparam tBAR = 200;
specparam tCAR1 = 200; // this is same as tCAR, but, is needed twice
specparam tBRBD = 1000;
`endif
 
`ifdef device32M
specparam tSCK = 77  ; // SCK time-period. 10e9/fSCK
specparam tWH = 35;
specparam tWL = 35;
specparam tCS = 250;
specparam tCSS = 250;
specparam tCSH = 250;
specparam tCSB = 200;
specparam tSU = 10;
specparam tH = 20;
specparam tHO = 0;
specparam tRST = 10000;
specparam tREC = 1000;
specparam tBAR = 200;
specparam tCAR1 = 200; // this is same as tCAR, but, is needed twice
specparam tBRBD = 1000;
`endif
 
  // SCK related
  $period(posedge SCK, tSCK); // SCK period is checked between
  $period(negedge SCK, tSCK); // rise-to-rise, as well as fall-to-fall
  $width(posedge SCK, tWH); // High PulseWidth
  $width(negedge SCK, tWL); // Low PulseWidth
 
  // CSB related
  $width(posedge CSB, tCS); // CSB Min. High
  $setup(CSB,posedge SCK, tCSS); // CSB setup time
  $hold(posedge SCK, CSB, tCSH); // CSB hold time
 
  // SI related. Being checked, only when CSB is Low
   $setup(SI, posedge SCK &&& ~CSB, tSU); // SI setup time
   $hold(posedge SCK &&& ~CSB, SI, tH); // SI hold time
 
  // RESETB related
  $width(negedge RESETB, tRST); // RESETB Low Width
  $recovery(posedge SCK, RESETB, tREC); // RESETB Recovery 
 
endspecify
 
endmodule
 
//`include "test_sequence2.v"
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.