基于Verilog的mx25L1605A(Serial Flash)模型

更新时间:2024-07-11 17:09:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

/*---------------------------------------------------------------------------- *

* 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

else if ( si_reg[ 7:0 ] == WRDI ) begin

//$display( $stime, \ write_disable;

//$display( $stime, \ state <= `STANDBY_STATE; end

else if ( si_reg[ 7:0 ] == RDID ) begin

//$display( $stime, \ read_id;

//$display( $stime, \

state <= `STANDBY_STATE; end

else if ( si_reg[ 7:0 ] == RDSR ) begin

//$display( $stime, \ read_status ( status_reg );

//$display( $stime, \

state <= `STANDBY_STATE; end

else if ( si_reg[ 7:0 ] == WRSR ) begin

//$display( $stime, \ write_status;

//$display( $stime, \

state <= `STANDBY_STATE; end

else if ( si_reg[ 7:0 ] == READ ) begin

$display( $stime, \ dummy_cycle( 24 ); // to get 24 bits address read_data;

//$display( $stime, \

state <= `STANDBY_STATE; end

else if ( si_reg[ 7:0 ] == FASTREAD ) begin

//$display( $stime, \ dummy_cycle( 24 ); // to get 24 bits address fast_read_data;

//$display( $stime, \ state <= `STANDBY_STATE; end

//else if ( si_reg[ 7:0 ] == PARALLELMODE ) begin

// //$display( $stime, \ // parallel_mode;

// //$display( $stime, \ // state <= `STANDBY_STATE; //end

else if ( si_reg[ 7:0 ] == SE ) begin

//$display( $stime, \ dummy_cycle( 24 ); // to get 24 bits address sector_erase;

//$display( $stime, \

state <= `STANDBY_STATE; end

else if ( si_reg[ 7:0 ] == BE ) begin

//$display( $stime, \ dummy_cycle( 24 ); // to get 24 bits address block_erase;

//$display( $stime, \

state <= `STANDBY_STATE; end

else if ( si_reg[ 7:0 ] == CE1 || si_reg[ 7:0 ] == CE2 ) begin //$display( $stime, \ chip_erase;

//$display( $stime, \ state <= `STANDBY_STATE; end

else if ( si_reg[ 7:0 ] == PP ) begin

//$display( $stime, \ dummy_cycle( 24 ); // to get 24 bits address setup_addr( si_reg, segment_addr, offset_addr ); page_program( segment_addr, offset_addr ); update_array( segment_addr, offset_addr );

//$display( $stime, \ state <= `STANDBY_STATE; end

else if ( si_reg[ 7:0 ] == DP ) begin

//$display( $stime, \ deep_power_down;

//$display( $stime, \ state <= `STANDBY_STATE; end

//else if ( si_reg[ 7:0 ] == EN4K ) begin

// //$display( $stime, \ // enter_4kb_sector;

// //$display( $stime, \ // state <= `STANDBY_STATE;

Function ...\

Function ...\

Function ...\

Function ...\

//end //else if ( si_reg[ 7:0 ] == EX4K ) begin

// //$display( $stime, \ // exit_4kb_sector;

// //$display( $stime, \ // state <= `STANDBY_STATE; //end else if ( si_reg[ 7:0 ] == RDP || si_reg[ 7:0 ] == RES ) begin

//$display( $stime, \Enter Release from Deep Power Dwon release_from_deep_power_dwon;

//$display( $stime, \Leave Release from Deep Power Dwon state <= `STANDBY_STATE; end else if ( si_reg[ 7:0 ] == REMS ) begin

//$display( $stime, \Enter Read Electronic Manufacturer & ID dummy_cycle ( 16 ); // 2 dummy cycle dummy_cycle ( 8 ); // 1 AD

read_electronic_manufacturer_device_id;

//$display( $stime, \Leave Read Electronic Manufacturer & ID state <= `STANDBY_STATE; end

else begin

state <= #1 `BAD_CMD_STATE; end end `BAD_CMD_STATE: begin

//SO <= #tSHQZ 1'bz; SO_reg <= #tSHQZ 1'bz;

state <= #(tC-1) `BAD_CMD_STATE; end

default: begin

SO_reg <= #tAA 1'bx;

state <= #(tC-1) `STANDBY_STATE; end endcase

end // else begin

end // always @( posedge SCLK or posedge CS ) begin

////////////////////////////////////////////////////////////////////// // Module Task Declaration

//////////////////////////////////////////////////////////////////////

/*---------------------------------------------------------------*/

/* Description: define a wait dummy cycle task /* INPUT /* cnum: cycle number /*---------------------------------------------------------------*/ task dummy_cycle; input [31:0] cnum;

begin

repeat( cnum ) begin

@( posedge SCLK ); end end endtask

/*---------------------------------------------------------------*/

/* Description: setup segment address and offset address from /* 4-byte serial input. /* INPUT /* si: 4-byte serial input /* OUTPUT /* segment: segment address /* offset : offset address /*---------------------------------------------------------------*/ task setup_addr;

input [23:0] si;

output [13:0] segment; output [7:0] offset;

*/

*/ */ */

*/

*/ */

*/ */ */

begin #1;

{ offset[ 7:0 ] } = { si_reg[ 7:0 ] }; { segment[ 13:0 ] } = { si_reg[ 23:8 ] }; end endtask

/*---------------------------------------------------------------*/

/* Description: setup sector address */

/* INPUT */ /* si: 2-byte serial input */

/* OUTPUT */ /* sector: sector address */ /*---------------------------------------------------------------*/ task setup_sector; input [23:0] si;

output [`SECTOR_ADDR -1:0] sector; // A[`SECTOR_ADDR -1:16] defines a sector

begin #1;

{ sector[`SECTOR_ADDR -1:0 ] } = { si_reg[ 11:4 ] }; end endtask

/*---------------------------------------------------------------*/

/* Description: define a write enable task */ /*---------------------------------------------------------------*/ task write_enable; begin

//$display( $stime, \ forever begin

@( posedge SCLK or posedge CS ); if ( CS == 1'b1 ) begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode status_reg[1] = 1'b1;

//$display( $stime, \ if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0};

end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0};

end

end

disable write_enable; //disable描述,退出forever end

else begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} {1'b1,1'b0,1'b0,1'b0};

end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} {1'b0,1'b1,1'b0,1'b0};

end end end end end endtask

/*---------------------------------------------------------------*/

/* Description: define a write disable task (WRDI) */ /*---------------------------------------------------------------*/ task write_disable; begin

//$display( $stime, \

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end end forever begin

@( posedge SCLK or posedge CS ); if ( CS == 1'b1 ) begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} {1'b1,1'b0,1'b0,1'b0};

end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} {1'b0,1'b1,1'b0,1'b0};

=

=

=

=

end

status_reg[1] = 1'b0;

//$display( $stime, \ end

disable write_disable; end

else begin end end end endtask

/*---------------------------------------------------------------*/

/* Description: define a read id task (WRID) */ /*---------------------------------------------------------------*/ task read_id;

reg [ 23:0 ] dummy_ID; integer dummy_count; begin

dummy_ID = {ID_MXIC,8'h20,ID_Device}; dummy_count = 0; if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end

forever begin

@( negedge SCLK or posedge CS ); if ( CS == 1'b1 ) begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} {1'b1,1'b0,1'b0,1'b0};

end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} {1'b0,1'b1,1'b0,1'b0};

end

SO_reg <= #tCLQV 1'bz; //SO = #tCLQV 1'bz; end

disable read_id; end

= = else begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode if ( pmode == 1'b0) begin // check parallel mode (2)

{ SO_reg, dummy_ID } <= #tCLQV { dummy_ID, dummy_ID[ 23 ] };

end

else begin

if ( dummy_count == 0 ) begin

SO_reg <= #tCLQV ID_MXIC; dummy_count = 1; end

else if ( dummy_count == 1 ) begin SO_reg <= #tCLQV 8'h00; dummy_count = 2; end

else if ( dummy_count == 2 ) begin SO_reg <= #tCLQV ID_Device; dummy_count = 0; end end end end

end // end forever end endtask

/*---------------------------------------------------------------*/

/* Description: define a read status task (WRSR) */ /*---------------------------------------------------------------*/ task read_status;

input [ 7:0 ] s_reg;

reg [ 7:0 ] dummy_reg; integer dummy_count; begin

dummy_reg = s_reg; dummy_count = 8;

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end end

forever begin

@( negedge SCLK or posedge CS ); if ( CS == 1'b1 ) begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0};

end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0};

end

SO_reg <= #tCLQV 1'bz; //SO = #tCLQV 1'bz; end

disable read_status; end

else begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode if ( pmode == 1'b0 ) begin if (dummy_count) begin

{ SO_reg, dummy_reg } <= #tCLQV { dummy_reg, dummy_reg[ 7 ] };

dummy_count = dummy_count - 1; end

else begin

dummy_reg = s_reg;

{ SO_reg, dummy_reg } <= #tCLQV { dummy_reg, dummy_reg[ 7 ] };

dummy_count = 7; end end

else begin

SO_reg <= #tCLQV s_reg; end end end

end // end forever end endtask

/*---------------------------------------------------------------*/

/* Description: define a write status task */ /*---------------------------------------------------------------*/

task write_status;

integer dummy_count; begin

dummy_count=0;

//$display( $stime, \

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end end forever begin

@( posedge SCLK or posedge CS ); if ( CS == 1'b1 ) begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end

if ( !(wp_reg ==1'b0 && status_reg[7]==1'b1) ) begin // do work on not PM (2)

if ( status_reg[1] == 1'b1 ) begin //WEL:Write Enable Latch (3) if ( dummy_count == 8 ) begin

if( (status_reg[7] == si_reg[7] ) && (status_reg[5:2] == si_reg[5:2] )) begin

//WIP:Write Enable Latch status_reg[0] <= 1'b1;

status_reg[0] <= #tW_WEL 1'b0; //WEL:Write Enable Latch

status_reg[1] <= #tW_WEL 1'b0; end else begin

//SRWD:Status Register Write Protect status_reg[7] <= #tW_BP si_reg[7]; status_reg[5:2] <= #tW_BP si_reg[5:2]; //WIP:Write Enable Latch status_reg[0] <= 1'b1;

status_reg[0] <= #tW_BP 1'b0; //WEL:Write Enable Latch

status_reg[1] <= #tW_BP 1'b0;

end end

else begin

//WIP:Write Enable Latch status_reg[0] <= 1'b1;

status_reg[0] <= #tW_WIP 1'b0; //WEL:Write Enable Latch

status_reg[1] <= #tW_WEL 1'b0; end end

else begin // do not work on WEL = 1'b0 //WEL:Write Enable Latch

status_reg[1] <= #tW_WEL 1'b0; end end else begin

//WEL:Write Enable Latch status_reg[1] = 1'b0;

//$display( $stime, \ end end

disable write_status; end

else begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode dummy_count = dummy_count + 1; end end

end // end forever end endtask

/*---------------------------------------------------------------*/

/* Description: define a read data task */ /*---------------------------------------------------------------*/

task read_data;

reg [`FLASH_ADDR - 1:0] rom_addr; // rom_addr = {segment, offset} integer dummy_count, tmp_int; reg [7:0] out_buf;

begin

dummy_count = 8;

rom_addr = si_reg[23:0]; addrspi = rom_addr; /////////////////////*****************************************

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b0,1'b1,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b0,1'b0,1'b1}; end

#1 out_buf = dataspi; /////////////////////ROM_ARRAY[ rom_addr ]; end

forever begin

@( negedge SCLK or posedge CS ); if ( CS == 1'b1 ) begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0};

end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0};

end

SO_reg <= #tCLQV 1'bz; end

disable read_data; end

else if ( status_reg[0] == 1'b0 ) begin //WIP:write in rpocess bit = 0 (1)

if ( dpmode == 1'b0) begin //do work on non deep power down mode

if ( dummy_count ) begin

{ SO_reg, out_buf } <= #tCLQV { out_buf, out_buf[6] };

dummy_count = dummy_count - 1; end

else begin

rom_addr = rom_addr + 1; addrspi = rom_addr; /////////////////////*****************************************

#1 out_buf = dataspi; //////////////////// ROM_ARRAY[ rom_addr ];

{ SO_reg, out_buf } <= #tCLQV { out_buf, out_buf[6] };

dummy_count = 7 ; end end end

end // end forever end endtask

/*---------------------------------------------------------------*/

/* Description: define a fast read data task */

/* 0B AD1 AD2 AD3 X */ /*---------------------------------------------------------------*/ task fast_read_data;

reg [`FLASH_ADDR - 1:0] rom_addr; // rom_addr = {segment, offset} integer dummy_count, tmp_int; reg [7:0] out_buf; begin

dummy_count = 8;

rom_addr = si_reg[23:0];

if ( dpmode == 1'b0) begin //do work on non deep power down mode out_buf = ROM_ARRAY[ rom_addr ]; if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end end

dummy_cycle( 8 ); forever begin

@( negedge SCLK or posedge CS ); if ( CS == 1'b1 ) begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode SO_reg <= #tCLQV 1'bz; if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} {1'b1,1'b0,1'b0,1'b0};

end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} {1'b0,1'b1,1'b0,1'b0};

end end

= = disable fast_read_data; end

else if ( status_reg[0] == 1'b0 ) begin //WIP:write in rpocess bit = 0 (1)

if ( dpmode == 1'b0) begin //do work on non deep power down mode

if ( dummy_count ) begin

{ SO_reg, out_buf } <= #tCLQV { out_buf, out_buf[6] };

dummy_count = dummy_count - 1; end

else begin

rom_addr = rom_addr + 1;

out_buf = ROM_ARRAY[ rom_addr ]; { SO_reg, out_buf } <= #tCLQV { out_buf, out_buf[6] };

dummy_count = 7 ; end end end

end // end forever end endtask

/*---------------------------------------------------------------*/

/* Description: define a parallel mode task */ /*---------------------------------------------------------------*/ // task parallel_mode; // begin

// @( posedge CS ); // if( CS == 1'b1 ) begin

// if ( dpmode == 1'b0) begin //do work on non deep power down mode // //$display( $stime, \// pmode = 1;

// {ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; // //$display( $stime, \// end // end // end // endtask //

/*---------------------------------------------------------------*/

/* Description: define a block erase task */

/* D8 AD1 AD2 AD3 */ /*---------------------------------------------------------------*/

task block_erase;

reg [`BLOCK_ADDR - 1:0] block; reg [15:0] offset; // 64K Byte

reg [`FLASH_ADDR - 1:0] rom_addr;

integer i, start_addr,end_addr,start_4kb_addr,end_4kb_addr; reg bp0; reg bp1; reg bp2; reg bp3; begin

block[`BLOCK_ADDR - 1:0] = si_reg[19:16]; offset = 16'h0;

start_addr = (si_reg[19:16]<<16) + 16'h0;

end_addr = (si_reg[19:16]<<16) + 16'hf;

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end end forever begin

@( posedge CS );

if( CS == 1'b1 ) begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end

if(wp_reg==1'b0||status_reg[7]==1'b1) begin // Protected Mode end

else if(dpmode == 1'b1) begin // deep power down mode end

else begin

if ( protected_area({block[`BLOCK_ADDR - 1:0],4'b0}) == 1'b1) begin

end

else if ( 16 <= block && block <=31 && bp2==1'b1 &&

bp1==1'b0 && bp0 ==1'b1) begin end

else begin

//WIP : write in process bit status_reg[0] = 1'b1;

for( i = start_addr; i < (end_addr+1); i = i + 1 ) begin

ROM_ARRAY[ i ] <= #`BLOCK_ERASE_TIME 8'hff;

end

//WIP : write in process bit

status_reg[0] <= #`BLOCK_ERASE_TIME 1'b0;//WIP //WEL : write enable latch

status_reg[1] <= #`BLOCK_ERASE_TIME 1'b0;//WEL end end end

disable block_erase; end

end // end forever end endtask

/*---------------------------------------------------------------*/

/* Description: define a sector erase task */

/* 20(D8) AD1 AD2 AD3 */ /*---------------------------------------------------------------*/ task sector_erase;

reg [`SECTOR_ADDR - 1:0] sector; reg [15:0] offset; // 64K Byte

reg [`FLASH_ADDR - 1:0] rom_addr;

integer i, start_addr,end_addr,start_4kb_addr,end_4kb_addr; reg bp0; reg bp1; reg bp2; reg bp3; begin

sector[`SECTOR_ADDR - 1:0] = si_reg[19:12]; offset = 12'h0;

start_addr = (si_reg[19:12]<<12) + 12'h000;

end_addr = (si_reg[19:12]<<12) + 12'hfff; start_4kb_addr = 9'h000;

end_4kb_addr = 9'h1ff;

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end end forever begin

@( posedge CS );

if( CS == 1'b1 ) begin

if ( dpmode == 1'b0) begin //do work on non deep power down mode if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end

if(wp_reg==1'b0||status_reg[7]==1'b1) begin // Protected Mode end

else if(dpmode == 1'b1) begin // deep power down mode end

else begin

if ( protected_area(sector[`SECTOR_ADDR - 1:0]) == 1'b1) begin

end

else if ( 16 <= sector && sector <=31 && bp2==1'b1 && bp1==1'b0 && bp0 ==1'b1) begin end

else begin

//WIP : write in process bit status_reg[0] = 1'b1;

for( i = start_addr; i < (end_addr+1); i = i + 1 ) begin

ROM_ARRAY[ i ] <= #`SECTOR_ERASE_TIME 8'hff;

end

//WIP : write in process bit

status_reg[0] <= #`SECTOR_ERASE_TIME 1'b0;//WIP //WEL : write enable latch status_reg[1] <= #`SECTOR_ERASE_TIME

1'b0;//WEL

end end end

disable sector_erase; end

end // end forever end endtask

/*---------------------------------------------------------------*/

/* Description: define a chip erase task */

/* 60(C7) */ /*---------------------------------------------------------------*/ task chip_erase; integer i;

begin

forever begin

@( posedge CS );

if( CS == 1'b1 ) begin

if ( dpmode == 1'b0 ) begin // do work on non deep power down mode

if ( wp_reg !=1'b0 && status_reg[7]!=1'b1 ) begin// protected mode

if ( status_reg[1] == 1'b1 ) begin //WEL:Write Enable Latch if ( status_reg[2] == 1'b0 && status_reg[3] == 1'b0 && status_reg[3] == 1'b0 ) begin

// WIP : write in process bit chip_erase_oe = 1'b1; status_reg[0] <= 1'b1;

//for( i = 0; i < FLASH_SIZE; i = i+1 ) //begin

// ROM_ARRAY[ i ] <= #`CHIP_ERASE_TIME 8'hff;

//end

////WIP : write in process bit

//status_reg[0] <= #`CHIP_ERASE_TIME 1'b0;//WIP

////WEL : write enable latch

//status_reg[1] <= #`CHIP_ERASE_TIME 1'b0;//WEL

end end end

end

disable chip_erase; end // CS == 1'b1 end // end forever end endtask

/*---------------------------------------------------------------*/

/* Description: define a page program task */

/* 02 AD1 AD2 AD3 */ /*---------------------------------------------------------------*/ task page_program;

input [12:0] segment; input [7:0] offset;

reg [`FLASH_ADDR - 1:0] rom_addr; // rom_addr = {segment, offset} integer dummy_count, tmp_int, i;

begin

dummy_count = 256; // page size

//offset[7:0] = 8'h00; // the start address of the page

rom_addr[`FLASH_ADDR - 1:0] = { segment[ 12:0 ],offset[7:0] };

/*------------------------------------------------*/

/* Store 256 bytes into a temp buffer - dummy_A */ /*------------------------------------------------*/ while ( dummy_count ) begin

rom_addr[`FLASH_ADDR - 1:0 ] = { segment[ 12:0 ], offset[ 7:0 ] }; dummy_count = dummy_count - 1;

tmp_int = dummy_count << 3; /* transfer byte to bit */ { dummy_A[ tmp_int+7 ], dummy_A[ tmp_int+6 ], dummy_A[ tmp_int+5 ], dummy_A[ tmp_int+4 ], dummy_A[ tmp_int+3 ], dummy_A[ tmp_int+2 ], dummy_A[ tmp_int+1 ], dummy_A[ tmp_int ] } = ROM_ARRAY[ rom_addr ];

offset = offset + 1; end

tmp_int = 0;

sector[`SECTOR_ADDR - 1:0] = rom_addr[`FLASH_ADDR - 1:12]; address[23:0] = si_reg[23:0]; if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end

else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; pp_p = #100 1'b1; end

forever begin

@( posedge SCLK or posedge CS ); if ( CS == 1'b1 ) begin

if ( dpmode == 1'b0 ) begin // do work on non deep power down mode if ( status_reg[0] == 1'b0 ) begin //WIP

if ( wp_reg !=1'b0 && status_reg[7]!=1'b1 ) begin// protected mode

if ( status_reg[1] == 1'b1 ) begin //WEL:Write Enable Latch

if ( protected_area(sector[`SECTOR_ADDR - 1:0]) == 1'b0 ) begin // check protected area (3)

//$display( $stime, \Total write %d bits\tmp_int );

if ( pmode == 1'b0 ) begin

for( i = 1; i <= tmp_int; i=i+1 ) begin

if( dummy_A[ 256*8-i ] == 1'b1 ) begin // 1 -> 1 ,1 -> 0

dummy_A[ 256*8-i ] = si_reg[ tmp_int-i ];

end end end else begin

for( i = 1; i <= tmp_int; i=i+1 ) begin if( dummy_A[ 256*8-i ] == 1'b1 ) begin // 1 -> 1 ,1 -> 0

dummy_A[ 256*8-i ] = psi_reg[ tmp_int-i ];

end end

// for( i = 1; i <= tmp_int; i=i+8 ) begin

// if( dummy_A[ 256*8-i-0 ] == 1'b1 ) begin

// dummy_A[ 256*8-i-0 ] = psi_reg[ tmp_int-i-0 ];

// end

// if( dummy_A[ 256*8-i-1 ] == 1'b1 ) begin

// dummy_A[ 256*8-i-1 ] = psi_reg[ tmp_int-i-1 ];

// end

// if( dummy_A[ 256*8-i-2 ] == 1'b1 ) begin

// dummy_A[ 256*8-i-2 ] = psi_reg[ tmp_int-i-2 ];

// end

// if( dummy_A[ 256*8-i-3 ] == 1'b1 ) begin

psi_reg[ tmp_int-i-3 ];

1'b1 ) begin

psi_reg[ tmp_int-i-4 ];

1'b1 ) begin

psi_reg[ tmp_int-i-5 ];

1'b1 ) begin

psi_reg[ tmp_int-i-6 ];

1'b1 ) begin

psi_reg[ tmp_int-i-7 ];

{1'b1,1'b0,1'b0,1'b0};

// dummy_A[ 256*8-i-3 ] = // end

// if( dummy_A[ 256*8-i-4 ] == // dummy_A[ 256*8-i-4 ] = // end

// if( dummy_A[ 256*8-i-5 ] == // dummy_A[ 256*8-i-5 ] = // end

// if( dummy_A[ 256*8-i-6 ] == // dummy_A[ 256*8-i-6 ] = // end

// if( dummy_A[ 256*8-i-7 ] == // dummy_A[ 256*8-i-7 ] = // end // end end end end end

if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} =

{1'b0,1'b1,1'b0,1'b0};

end end end

pp_p = #90 1'b0;

disable page_program; end

else if (status_reg[0] == 1'b0)begin // count how many bits been shifted if ( dpmode == 1'b0 ) begin // do work on non deep power down mode if ( pmode == 1'b0 ) begin tmp_int = tmp_int + 1; end else begin

{ psi_reg[ 256*8-1:0 ] } = { psi_reg[ 256*8-2:0 ],latch_SO}; tmp_int = tmp_int + 8; end end end

end // end forever end endtask

/*---------------------------------------------------------------*/

/* Description: define a deep power down (DP) */ /*---------------------------------------------------------------*/ task deep_power_down; begin

//$display( $stime, \ if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end

forever begin

@( posedge CS );

if( CS == 1'b1 ) begin

if ( dpmode == 1'b0 ) begin // do work on non deep power down mode (1) if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end

dpmode <= #tDP 1'b1;

//$display( $stime, \ end

disable deep_power_down; end

end // end forever end endtask

// /*---------------------------------------------------------------*/

// /* Description: define a enter 4kb sector task */ // /*---------------------------------------------------------------*/ // task enter_4kb_sector; // begin

// //$display( $stime, \// forever begin

// @( posedge CS );

// if( CS == 1'b1 ) begin

// if ( dpmode == 1'b0 ) begin // do work on non deep power down mode (1) // if (status_reg[0] == 1'b0) begin // WIP (2) // enter4kbmode = 1;

// //$display( $stime, \New Enter 4kb Sector Register = %b\enter4kbmode );

// disable enter_4kb_sector; // end // end // end

// end // end forever // end // endtask //

// /*---------------------------------------------------------------*/

// /* Description: define a exit 4kb sector task */ // /*---------------------------------------------------------------*/ // task exit_4kb_sector; // begin

// //$display( $stime, \// forever begin

// @( posedge CS );

// if( CS == 1'b1 ) begin

// if ( dpmode == 1'b0 ) begin // do work on non deep power down mode (1) // if (status_reg[0] == 1'b0) begin // WIP (2) // enter4kbmode = 0;

// //$display( $stime, \New Enter 4kb Sector Register = %b\

enter4kbmode );

// disable exit_4kb_sector; // end // end // end

// end // end forever // end // endtask //

/*---------------------------------------------------------------*/

/* Description: define a release from deep power dwon task (RDP)*/ /*---------------------------------------------------------------*/ task release_from_deep_power_dwon; begin

//$display( $stime, \ forever begin

@( posedge SCLK or posedge CS ); if( CS == 1'b1 ) begin

dpmode <= #tRES2 1'b0;

//$display( $stime, \ disable release_from_deep_power_dwon; end

else begin

//$display( $stime, \ dummy_cycle( 23 ); read_electronic_id;

//$display( $stime, \ disable release_from_deep_power_dwon; end

end // end forever end endtask

/*---------------------------------------------------------------*/

/* Description: define a read electronic ID (RES) */

/* AB X X X */ /*---------------------------------------------------------------*/ task read_electronic_id;

reg [ 7:0 ] dummy_ID; begin

//$display( $stime, \ if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end

else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end

dummy_ID = ID_Device; forever begin

@( negedge SCLK or posedge CS ); if( CS == 1'b1 ) begin if (pmode == 0) begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b1,1'b0,1'b0,1'b0}; end else begin

{ENB_S0,ENB_P0,ENB_S1,ENB_P1} = {1'b0,1'b1,1'b0,1'b0}; end

{SO_reg,PO_reg6,PO_reg5,PO_reg4,PO_reg3,PO_reg2,PO_reg1,PO_reg0} <= #tCLQV {1'bz,1'bz,1'bz,1'bz,1'bz,1'bz,1'bz,1'bz}; dpmode <= #tRES2 1'b0;

//$display( $stime, \ disable read_electronic_id; end

else begin

if ( pmode == 1'b0 ) begin

{ SO_reg, dummy_ID } <= #tCLQV { dummy_ID, dummy_ID[ 7 ] };

end

else begin

SO_reg <= #tCLQV ID_Device; end end

end // end forever end endtask

/*-----------------------------------------------------------------*/

/* Description: define a read electronic manufacturer & device ID */ /*-----------------------------------------------------------------*/

task read_electronic_manufacturer_device_id; reg [ 15:0 ] dummy_ID; integer dummy_count; begin

//$width(negedge SCLK,1);

//$period( posedge SCLK, tCY ); // SCLK _/~ -> _/~ if ( si_reg[0]==1'b0 ) begin

dummy_ID = {ID_MXIC,ID_Device+1}; end

else begin

dummy_ID = {ID_Device,ID_MXIC}; end

dummy_count = 0; forever begin

@( negedge SCLK or posedge CS ); if ( CS == 1'b1 ) begin

if ( dpmode == 1'b0 ) begin // do work on non deep power down mode SO_reg <= #tCLQV 1'bz; end

disable read_electronic_manufacturer_device_id; end

else begin

if ( dpmode == 1'b0 ) begin // do work on non deep power down mode if ( pmode == 1'b0) begin // check parallel mode (2)

{ SO_reg, dummy_ID } <= #tCLQV { dummy_ID, dummy_ID[ 15 ] };

end else begin

if ( dummy_count == 0 ) begin

SO_reg = #tCLQV dummy_ID[15:8]; dummy_count = 1; end

else begin

SO_reg = #tCLQV dummy_ID[7:0]; dummy_count = 0; end end end end

end // end forever end endtask

/*---------------------------------------------------------------*/

/* Description: define a program chip task */

/* INPUT */ /* segment: segment address */ /* offset : offset address */ /*---------------------------------------------------------------*/ task update_array;

input [12:0] segment; input [7:0] offset;

reg [`FLASH_ADDR - 1:0] rom_addr; // rom_addr = {segment, offset} integer dummy_count, tmp_int;

reg [`SECTOR_ADDR - 1:0] sector; begin

dummy_count = 256;

/*------------------------------------------------*/

/* Store 256 bytes back to ROM Page */ /*------------------------------------------------*/

if ( dpmode == 1'b0 ) begin // do work on non deep power down mode (1) if (status_reg[0] == 1'b0) begin // WIP (2)

sector[`SECTOR_ADDR - 1:0] = rom_addr[`FLASH_ADDR - 1:12]; if ( wp_reg !=1'b0 || status_reg[7]!=1'b1 ) begin // protected mode (3) if ( status_reg[1] == 1'b1 ) begin // WEL:Write Enable Latch (4) if ( protected_area(sector[`SECTOR_ADDR - 1:0]) == 1'b0 ) begin // check protected area (5)

// initial start rom addrress offset = 8'h00;

rom_addr[`FLASH_ADDR - 1:0] = { segment[12:0], offset[7:0] };

// in write operation status_reg[0]<= 1'b1;

// not in write operation after PROG_TIME status_reg[0]<= #`PROG_TIME 1'b0; // WEL : write enable latch

status_reg[1]<= #`PROG_TIME 1'b0; while ( dummy_count ) begin

rom_addr[`FLASH_ADDR - 1:0] = { segment[12:0], offset[7:0] };

dummy_count = dummy_count - 1;

tmp_int = dummy_count << 3; /* byte to bit */ ROM_ARRAY[ rom_addr ] <= #`PROG_TIME { dummy_A[ tmp_int+7 ], dummy_A[ tmp_int+6 ],

dummy_A[ tmp_int+5 ], dummy_A[ tmp_int+4 ],

dummy_A[ tmp_int+3 ], dummy_A[ tmp_int+2 ],

dummy_A[ tmp_int+1 ], dummy_A[ tmp_int ] };

offset = offset + 1;

end

end // end protected area

end // end WEL:Write Enable Latch end end end end endtask

/*---------------------------------------------------------------*/

/* Description: define a protected_area area function */

/* INPUT */ /* sector : sector address */ /*---------------------------------------------------------------*/ function protected_area; input [7:0] sector; begin

`ifdef MX25L4005

if (status_reg[5:2]==4'b0000) begin protected_area = 1'b0; end

else if (status_reg[5:2]==4'b0001) begin

if (sector[`SECTOR_ADDR - 1:4] == 7) begin protected_area = 1'b1; end else begin

protected_area = 1'b0; end end

else if (status_reg[5:2]==4'b0010) begin

if (sector[`SECTOR_ADDR - 1:4] >= 6 && sector[`SECTOR_ADDR - 1:4] <= 7) begin

protected_area = 1'b1; end else begin

protected_area = 1'b0; end end

else if (status_reg[5:2]==4'b0011) begin

if (sector[`SECTOR_ADDR - 1:4] >= 4 && sector[`SECTOR_ADDR - 1:4] <= 7) begin

protected_area = 1'b1; end else begin

protected_area = 1'b0;

end end

else if (status_reg[5:2]==4'b0100) begin protected_area = 1'b1; end

else if (status_reg[5:2]==4'b0101) begin protected_area = 1'b1; end

else if (status_reg[5:2]==4'b0110) begin protected_area = 1'b1; end

else if (status_reg[5:2]==4'b0111) begin protected_area = 1'b1; end else begin

protected_area = 1'b1; end `else

`ifdef MX25L1605A

if (status_reg[5:2]==4'b0000) begin protected_area = 1'b0; end

else if (status_reg[5:2]==4'b0001) begin

if (sector[`SECTOR_ADDR - 1:4] == 31) begin protected_area = 1'b1; end else begin

protected_area = 1'b0; end end

else if (status_reg[5:2]==4'b0010) begin

if (sector[`SECTOR_ADDR - 1:4] >= 30 && sector[`SECTOR_ADDR - 1:4] <= 31) begin

protected_area = 1'b1; end else begin

protected_area = 1'b0; end end

else if (status_reg[5:2]==4'b0011) begin

if (sector[`SECTOR_ADDR - 1:4] >= 28 && sector[`SECTOR_ADDR - 1:4] <= 31) begin

protected_area = 1'b1; end

else begin

protected_area = 1'b0; end end

else if (status_reg[5:2]==4'b0100) begin

if (sector[`SECTOR_ADDR - 1:4] >= 24 && sector[`SECTOR_ADDR - 1:4] <= 31) begin

protected_area = 1'b1; end else begin

protected_area = 1'b0; end end

else if (status_reg[5:2]==4'b0101) begin if (sector[`SECTOR_ADDR - 1:4] >= 16 && sector[`SECTOR_ADDR - 1:4] <= 31) begin

protected_area = 1'b1; end else begin protected_area = 1'b0; end end

else if (status_reg[5:2]==4'b0110) begin protected_area = 1'b1; end

else if (status_reg[5:2]==4'b0111) begin protected_area = 1'b1; end else begin

protected_area = 1'b1; end `endif `endif end

endfunction

////////////////////////////////////////////////////////////////////// // AC Timing Check Section

////////////////////////////////////////////////////////////////////// specify

//====================================================== // AC Timing Parameter

//====================================================== specparam tCYC = 14, // Clock Cycle Time [ns]

tCH = 7, // Clock High Time (min) [ns] tCL = 7, // Clock Low Time (min) [ns]

tSLCH = 5, // CS Lead Clock Time (min) [ns] tCHSL = 5, // CS Lag Clock Time (min) [ns] tSHSL = 100, // CS High Time (min) [ns] tDVCH = 2, // SI Setup Time (min) [ns] tCHDX = 5; // SI Hold Time (min) [ns]

//====================================================== // Timing Check

//====================================================== $period( posedge SCLK , tCYC ); // SCLK _/~ -> _/~ $period( negedge SCLK , tCYC ); // SCLK ~\\_ -> ~\\_ $width ( posedge SCLK , tCH ); // SCLK _/~~\\_ $width ( negedge SCLK , tCL ); // SCLK ~\\__/~ $width ( posedge CS , tSHSL ); // CS _/~\\_

$setuphold( posedge SCLK &&& ~CS, SI, tDVCH, tCHDX ); $setup ( CS, posedge SCLK &&& ~CS, tSLCH ); $hold ( negedge SCLK &&& ~CS, CS, tCHSL );

endspecify endmodule

tCH = 7, // Clock High Time (min) [ns] tCL = 7, // Clock Low Time (min) [ns]

tSLCH = 5, // CS Lead Clock Time (min) [ns] tCHSL = 5, // CS Lag Clock Time (min) [ns] tSHSL = 100, // CS High Time (min) [ns] tDVCH = 2, // SI Setup Time (min) [ns] tCHDX = 5; // SI Hold Time (min) [ns]

//====================================================== // Timing Check

//====================================================== $period( posedge SCLK , tCYC ); // SCLK _/~ -> _/~ $period( negedge SCLK , tCYC ); // SCLK ~\\_ -> ~\\_ $width ( posedge SCLK , tCH ); // SCLK _/~~\\_ $width ( negedge SCLK , tCL ); // SCLK ~\\__/~ $width ( posedge CS , tSHSL ); // CS _/~\\_

$setuphold( posedge SCLK &&& ~CS, SI, tDVCH, tCHDX ); $setup ( CS, posedge SCLK &&& ~CS, tSLCH ); $hold ( negedge SCLK &&& ~CS, CS, tCHSL );

endspecify endmodule

本文来源:https://www.bwwdw.com/article/nko.html

Top