/*---------------------------------------------------------------------------- *
* mx25L1605A.v - 16M-BIT CMOS Serial Flash *
* COPYRIGHT 2005 BY Macronix International Corporation *
*----------------------------------------------------------------------------- * Creation Date: 2005/5/ * Doc : REV.0.00, MAY. 11, 2005 * VERSION : V 0.01
* Note : This model do not include test mode * Description :
* module flash_16m -> behavior model for the 16M serial flash *----------------------------------------------------------------------------- */
`timescale 1ns / 1ps
// Define controller state
`define STANDBY_STATE 0 `define ACTION_STATE 1 `define CMD_STATE 2 `define BAD_CMD_STATE 3
`define SECTOR_ERASE_TIME 90_000_000 // 90 ms `define BLOCK_ERASE_TIME 1_000_000_000 // 1 s `define CHIP_ERASE_TIME 32_000_000 // 32 s `define PROG_TIME 1_400_000 // 1.4 ms // Time delay to write instruction
`define PUW_TIME 10_000_000 // 10 ms
`define MX25L1605A //MX25L4005
`ifdef MX25L4005
`define FLASH_ADDR 19 `define SECTOR_ADDR 7 `define BLOCK_ADDR 4 `else
`ifdef MX25L1605A
`define FLASH_ADDR 21 `define SECTOR_ADDR 9 `define BLOCK_ADDR 5 `endif `endif
`define FLASH_TYPE 0
module flash_16m( SCLK, CS, SI, SO, WP, HOLD);
//--------------------------------------------------------------------- // Declaration of ports (input,output, inout)
//--------------------------------------------------------------------- input SCLK, // Signal of Clock Input CS, // Chip select (Low active) SI, // Serial Data Input
WP, // Write Protection:connect to GND HOLD; //
output SO; // Serial Data Output
//--------------------------------------------------------------------- // Declaration of parameter (parameter)
//---------------------------------------------------------------------
parameter FLASH_SIZE = 1 << `FLASH_ADDR, // 2M bytes SECTOR_SIZE = 1 << 12, // 4K bytes BLOCK_SIZE = 1 << 16, // 64K bytes
tAA = 12, // Access Time [ns],tAA = tSKH + tCLQ
tC = 14, // Clock Cycle Time,tC = tSKH + tSKL
//tSKH = 9, // Clock High Time //tSKL = 9, // Clock Low Time
tSHQZ = 6, // CS High to SO Float Time [ns] tCLQV = 1, // Clock Low to Output Valid tDP = 3_000, // 3 us tRES1 = 3_000, // 3 us tRES2 = 1_800, // 1.8 us
tW_SRWD = 15_000_000, // 15 ms tW_BP = 500_000_000, // 500 ms tW_WIP = 30_000_000, // 30 ms tW_WEL = 30_000_000; // 30 ms
parameter [7:0] ID_MXIC = 8'hc2; `ifdef MX25L4005
parameter [7:0] ID_Device = 8'h13; // MX25L4005 `else
`ifdef MX25L1605A
parameter [7:0] ID_Device = 8'h14; // MX25L1605A `endif `endif
parameter [7:0] WREN = 8'h06, //WriteEnable = 8'h06, WRDI = 8'h04, //WriteDisable = 8'h04, RDID = 8'h9F, //ReadID = 8'h9f, RDSR = 8'h05, //ReadStatus = 8'h05, WRSR = 8'h01, //WriteStatus = 8'h01, READ = 8'h03, //ReadData = 8'h03,
FASTREAD = 8'h0b, //FastReadData = 8'h0b,
PARALLELMODE = 8'h55, //PallelMode = 8'h55, SE = 8'h20, //SectorErase = 8'h20 BE = 8'hd8, //BlockErase = 8'hd8
CE1 = 8'h60, //ChipErase = 8'h60,//8'hc7 CE2 = 8'hc7, //ChipErase = 8'h60,//8'hc7 PP = 8'h02, //PageProgram = 8'h02, DP = 8'hb9, //DeepPowerDown = 8'hb9, EN4K = 8'ha5, //Enter4kbSector= 8'ha5, EX4K = 8'hb5, //Exit4kbSector = 8'hb5,
RDP = 8'hab, //ReleaseFromDeepPowerDwon = 8'hab, RES = 8'hab, //ReadElectricID = 8'hab,
REMS = 8'h90; //ReadElectricManufacturerDeviceID = 90;
/******************************************************/ wire[7:0] dataspi; reg[`FLASH_ADDR - 1:0] addrspi;
/******************************************************/
//--------------------------------------------------------------------- // Declaration of internal-register (reg)
//---------------------------------------------------------------------
// memory array
reg [7:0] ROM_ARRAY[ 0:FLASH_SIZE-1 ]; reg [7:0] status_reg; // Status Register
reg [256*8-1:0] si_reg; // temp reg to store serial in reg [23:0] address; //
reg [256*8-1:0] psi_reg; // temp reg to store serial in reg [256*8-1:0] dummy_A; // page size
reg [12:0] segment_addr; // A[20:8] segment address reg [7:0] offset_addr; // A[7:0] means 256 bytes
reg [`SECTOR_ADDR - 1:0] sector; // means 512 sectors
reg [2:0] state, rState;
reg ENB_S0,ENB_P0,ENB_S1,ENB_P1; reg SO_reg;
reg PO_reg6,PO_reg5,PO_reg4,PO_reg3,PO_reg2,PO_reg1,PO_reg0; reg
latch_SO,latch_PO6,latch_PO5,latch_PO4,latch_PO3,latch_PO2,latch_PO1,latch_PO0; reg pp_p;
reg pmode; // parallel mode
reg dpmode; // deep power down mode reg enter4kbmode; // enter 4kb mode reg chip_erase_oe;
integer i,chip_erase_count; wire wp_reg = WP;
assign SO = pp_p ? 8'bz : SO_reg; always @(SO) begin latch_SO = SO; //latch_PO6 = PO6; end
/*-------------------------------------------------------*/
/* initial variable value */ /*-------------------------------------------------------*/ initial begin
pp_p = 1'b0; enter4kbmode = 1'b0; dpmode = 1'b0; pmode = 1'b0; chip_erase_oe = 1'b0; chip_erase_count = 0;
status_reg = 8'b0000_0000;
{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; i = 0; end
/*-------------------------------------------------------*/
/* latch signal SI into si_reg */ /*-------------------------------------------------------*/ always @( posedge SCLK ) begin if ( $time > `PUW_TIME ) begin if ( CS == 1'b0 ) begin
{ si_reg[ 256*8-1:0 ] } = { si_reg[ 256*8-2:0 ], SI }; end end end
/*-------------------------------------------------------*/
/* chip erase process */ /*-------------------------------------------------------*/ always @( posedge chip_erase_oe ) begin
chip_erase_count = 0; for ( chip_erase_count = 0;chip_erase_count<=`CHIP_ERASE_TIME;chip_erase_count=chip_erase_count+1) begin #1000; end
//WIP : write in process bit chip_erase_count = 0;
for( chip_erase_count = 0; chip_erase_count < FLASH_SIZE; chip_erase_count = chip_erase_count+1 ) begin
ROM_ARRAY[ chip_erase_count ] <= 8'hff; end
chip_erase_count = 0; //WIP : write in process bit status_reg[0] <= 1'b0;//WIP //WEL : write enable latch status_reg[1] <= 1'b0;//WEL chip_erase_oe = 1'b0; end
/*-------------------------------------------------------*/
/* Finite state machine to control Flash operation */ /*-------------------------------------------------------*/ always @( posedge SCLK or posedge CS ) begin if ( CS == 1'b1 ) begin // Chip Disable state <= #(tC-1) `STANDBY_STATE; SO_reg <= #tCLQV 1'bz; end
else begin // Chip Enable case ( state )
`STANDBY_STATE: begin SO_reg <= #tCLQV 1'bz; dummy_cycle( 6 );
state <= #(tC-1) `CMD_STATE; end
`CMD_STATE: begin //每8个SCLK进入`CMD_STATE一次 #1;
if ( si_reg[ 7:0 ] == WREN ) begin
//$display( $stime, \ write_enable;
//$display( $stime, \ state <= `STANDBY_STATE; end