w25q128jv.v 79 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683
  1. /******************************************************************************
  2. Winbond Electronics Corporation
  3. Verilog Simulation for W25Q128JV series Serial Flash Memory
  4. V0.2
  5. Copyright (c) 2001-2016 Winbond Electronics Corporation
  6. All Rights Reserved.
  7. Notes:
  8. Versions:
  9. 09/19/2016 Initial Version
  10. 08/23/2017 V0.2 Modified Protection Area & Updated specs
  11. ******************************************************************************/
  12. `timescale 1ns / 1ns
  13. module W25Q128JV (CSn, CLK, DIO, DO, WPn, HOLDn);
  14. input CSn, CLK;
  15. inout DIO;
  16. inout WPn;
  17. inout HOLDn;
  18. inout DO;
  19. parameter NUM_PAGES = 65536;
  20. parameter NUM_SEC_PAGES = 3;
  21. parameter PAGESIZE = 256;
  22. parameter SECTORSIZE = 4096;
  23. parameter HALFBLOCKSIZE = 32768;
  24. parameter BLOCKSIZE = 65536;
  25. parameter NUM_BLOCKS = NUM_PAGES * PAGESIZE / BLOCKSIZE;
  26. parameter NUM_LOCKBITS = NUM_BLOCKS - 2 + 32;
  27. parameter MANUFACTURER = 8'hEF;
  28. parameter DEVICE_ID = 8'h17;
  29. parameter JEDEC_ID_HI = 8'h40;
  30. parameter JEDEC_ID_HI_QPI = 8'h70;
  31. parameter JEDEC_ID_LO = 8'h18;
  32. parameter UNIQUE_ID = 64'h0102030405060708;
  33. parameter ADDRESS_MASK = (NUM_PAGES * PAGESIZE) - 1; // Note that NUM_PAGES must be a power of 2 for this simulation to work properly.
  34. `define MEM_FILENAME "/home/bart/Documents/FPGA/FPGC6/Verilog/memory/spi.txt" //todo relative path // Memory contents file(s)
  35. `define SECSI_FILENAME "SECSI.TXT"
  36. `define SFDP_FILENAME "SFDP.TXT"
  37. `define SREG_FILENAME "SREG.TXT"
  38. // The following registers define the main memory spaces of the
  39. // device.
  40. //
  41. reg [7:0] memory [0:(NUM_PAGES * PAGESIZE) - 1]; // Main Memory Array
  42. reg [7:0] page_latch [0:PAGESIZE-1]; // Page Latch for Program Sector commands.
  43. reg [7:0] secsi[0:(NUM_SEC_PAGES * (SECTORSIZE/PAGESIZE) * PAGESIZE) - 1]; // Security Sector Array
  44. reg [7:0] sfdp[0:PAGESIZE]; // Serial Flash Discoverable Parameter
  45. reg lock_array[0:NUM_LOCKBITS]; // 510 blocks + 32 sectors
  46. reg [23:0] status_reg; // Status Register
  47. reg [23:0] status_reg_shadow; // Status Register Shadow Register
  48. reg status_reg_otp [23:0]; // Status Register OTP Bits
  49. reg [23:0] byte_address; // Page address used for reading pages.
  50. reg [23:0] prog_byte_address; // Page address used for writing pages.
  51. reg [8:0] prog_byte_number;
  52. reg [7:0] mode_reg; // Mode Register
  53. reg [7:0] wrap_reg; // burst-wrap register
  54. reg [7:0] read_param_reg; // Read parameters register
  55. reg [7:0] read_param_reg_shadow; // Shadow register
  56. reg flag_prog_page; // Flag used to start the program process for sram 0
  57. reg flag_prog_secsi_page; // Flag used to program a SECSI page
  58. reg flag_erase_sector; // Flag used to erase a sector (4KB)
  59. reg flag_erase_secsi_sector;
  60. reg flag_erase_half_block; // Flag to erase half a block (32KB)
  61. reg flag_erase_block; // Flag used to erase a block (64KB)
  62. reg flag_erase_bulk; // Flag used to erase the chip
  63. reg flag_power_up_exec;
  64. reg flag_power_down;
  65. reg flag_power_up_sig_read;
  66. reg flag_write_status_reg;
  67. reg flag_suspend; // Flag used to start an erase suspend process.
  68. reg flag_resume; // Flag used to resume from and erase suspend
  69. reg flag_suspend_enabled; // Flag used to stop the erase process.
  70. reg flag_slow_read_reg;
  71. reg flag_volatile_sr_write; // flag for volatile status register write.
  72. wire flag_slow_read = flag_slow_read_reg;
  73. reg flag_read_op_reg;
  74. wire #1 flag_read_op = flag_read_op_reg; // Delay avoids race condition
  75. reg flag_qpi_mode; // flag used for QPI Mode.
  76. reg flag_enable_reset; // flag used to enable the software reset command.
  77. reg flag_reset; // flag to execute the chip reset routine
  78. reg flag_reset_condition; // Flag to stop delay loops
  79. reg flag_set_read_param; // Flag to set read parameters
  80. reg timing_error; // Register for identifying timing errors when they occur
  81. reg [7:0] in_byte; // These two variables are used for debug purposes.
  82. reg [7:0] out_byte;
  83. // Logic output for WPn pin.
  84. //
  85. reg WPn_Reg, WPn_Output_Enable_reg;
  86. wire WPn_Output_Enable = WPn_Output_Enable_reg;
  87. // Logic output for HOLDn pin.
  88. //
  89. reg HOLDn_Reg, HOLDn_Output_Enable;
  90. // Logic output for DO pin.
  91. //
  92. reg DO_Reg, DO_Output_Enable, temp_DO_Output_Enable;
  93. // Logic output for DIO pin.
  94. //
  95. reg DIO_Reg, DIO_Output_Enable_reg, temp_DIO_Output_Enable_reg;
  96. wire DIO_Output_Enable = DIO_Output_Enable_reg;
  97. // Flag to signal that HOLDn goes active while CSn is low
  98. reg HOLDn_Active;
  99. // The following are working variables for the simulation program
  100. //
  101. reg [7:0] cmd_byte;
  102. reg [7:0] null_reg;
  103. reg [7:0] temp;
  104. integer x;
  105. integer fileno;
  106. reg [15:0] file_sector;
  107. reg [15:0] file_length;
  108. // The following macro's define the supported commands in this
  109. // Simulation
  110. //
  111. `define CMD_WRITE_DISABLE 8'h04
  112. `define CMD_WRITE_ENABLE 8'h06
  113. `define CMD_READ_STATUS 8'h05
  114. `define CMD_WRITE_STATUS 8'h01
  115. `define CMD_READ_STATUS2 8'h35
  116. `define CMD_WRITE_STATUS2 8'h31
  117. `define CMD_READ_STATUS3 8'h15
  118. `define CMD_WRITE_STATUS3 8'h11
  119. `define CMD_READ_DATA 8'h03
  120. `define CMD_READ_DATA_FAST 8'h0b
  121. `define CMD_READ_DATA_FAST_WRAP 8'h0c
  122. `define CMD_READ_DATA_FAST_DUAL 8'h3b
  123. `define CMD_READ_DATA_FAST_DUAL_IO 8'hbb
  124. `define CMD_READ_DATA_FAST_QUAD 8'h6b
  125. `define CMD_READ_DATA_FAST_QUAD_IO 8'heb
  126. `define CMD_READ_OCTAL_FAST_QUAD_IO 8'he3
  127. `define CMD_READ_WORD_FAST_QUAD_IO 8'he7
  128. `define CMD_PAGE_PROGRAM 8'h02
  129. `define CMD_PAGE_PROGRAM_QUAD 8'h32
  130. `define CMD_BLOCK_ERASE 8'hD8
  131. `define CMD_HALF_BLOCK_ERASE 8'h52
  132. `define CMD_SECTOR_ERASE 8'h20
  133. `define CMD_BULK_ERASE 8'hC7
  134. `define CMD_BULK_ERASE2 8'h60
  135. `define CMD_DEEP_POWERDOWN 8'hB9
  136. `define CMD_READ_SIGNATURE 8'hAB
  137. `define CMD_READ_ID 8'h90
  138. `define CMD_READ_ID_DUAL 8'h92
  139. `define CMD_READ_ID_QUAD 8'h94
  140. `define CMD_READ_JEDEC_ID 8'h9f
  141. `define CMD_READ_UNIQUE_ID 8'h4b
  142. `define CMD_SUSPEND 8'h75
  143. `define CMD_RESUME 8'h7A
  144. `define CMD_SET_BURST_WRAP 8'h77
  145. `define CMD_MODE_RESET 8'hff
  146. `define CMD_DISABLE_QPI 8'hff
  147. `define CMD_ENABLE_QPI 8'h38
  148. `define CMD_ENABLE_RESET 8'h66
  149. `define CMD_CHIP_RESET 8'h99
  150. `define CMD_SET_READ_PARAM 8'hC0
  151. `define CMD_SREG_PROGRAM 8'h42
  152. `define CMD_SREG_ERASE 8'h44
  153. `define CMD_SREG_READ 8'h48
  154. `define CMD_WRITE_ENABLE_VSR 8'h50
  155. `define CMD_READ_SFDP 8'h5A
  156. `define CMD_INDIVIDUAL_LOCK 8'h36
  157. `define CMD_INDIVIDUAL_UNLOCK 8'h39
  158. `define CMD_READ_BLOCK_LOCK 8'h3D
  159. `define CMD_GLOBAL_BLOCK_LOCK 8'h7E
  160. `define CMD_GLOBAL_BLOCK_UNLOCK 8'h98
  161. // Status register definitions
  162. //
  163. `define STATUS_HLD_RST 24'h800000
  164. `define STATUS_DRV1 24'h400000
  165. `define STATUS_DRV0 24'h200000
  166. `define STATUS_WPS 24'h040000
  167. `define STATUS_SUS 24'h008000
  168. `define STATUS_CMP 24'h004000
  169. `define STATUS_LB3 24'h002000
  170. `define STATUS_LB2 24'h001000
  171. `define STATUS_LB1 24'h000800
  172. `define STATUS_QE 24'h000200
  173. `define STATUS_SRP1 24'h000100
  174. `define STATUS_SRP0 24'h000080
  175. `define STATUS_SEC 24'h000040
  176. `define STATUS_TB 24'h000020
  177. `define STATUS_BP2 24'h000010
  178. `define STATUS_BP1 24'h000008
  179. `define STATUS_BP0 24'h000004
  180. `define STATUS_WEL 24'h000002
  181. `define STATUS_WIP 24'h000001
  182. `define HLD_RST 23
  183. `define DRV1 22
  184. `define DRV0 21
  185. `define WPS 18
  186. `define SUS 15
  187. `define CMP 14
  188. `define LB3 13
  189. `define LB2 12
  190. `define LB1 11
  191. `define QE 9
  192. `define SRP1 8
  193. `define SRP0 7
  194. `define SEC 6
  195. `define TB 5
  196. `define BP2 4
  197. `define BP1 3
  198. `define BP0 2
  199. `define WEL 1
  200. `define WIP 0
  201. // Required for specify block
  202. wire flag_quad_mode = status_reg[`QE];
  203. wire flag_quad_mode_cs = !flag_quad_mode & !CSn;
  204. specify
  205. specparam tReset_Suspend_Max = 1000; // Reset / Suspend Granularity. Controls maximum amount of time for model to recognize a Suspend command.
  206. // Also controls amount of time it takes to recognize a reset command
  207. // CSn timing checks
  208. specparam tSLCH = 5;
  209. $setup(negedge CSn, posedge CLK, tSLCH, timing_error);
  210. specparam tCHSL = 5;
  211. $setup(posedge CLK, negedge CSn, tCHSL, timing_error);
  212. specparam tSHSL_R = 10;
  213. specparam tSHSL_W = 50;
  214. $width(posedge CSn &&& flag_read_op, tSHSL_R, 0, timing_error);
  215. $width(posedge CSn &&& (~flag_read_op), tSHSL_W, 0, timing_error);
  216. specparam tCHSH = 3;
  217. $setup(posedge CLK, posedge CSn, tCHSH, timing_error);
  218. specparam tSHCH = 3;
  219. $setup(posedge CSn, posedge CLK, tSHCH, timing_error);
  220. // CLK timing checks
  221. specparam tCYC = 9; // Minimum CLK period for all instructions but READ_PAGE
  222. specparam tCLH = 4; // Minimum CLK high time for all instructions but READ_PAGE
  223. specparam tCLL = 4; // Minimum CLK low time for all instructions but READ_PAGE
  224. $period(posedge CLK &&& (~flag_slow_read), tCYC, timing_error);
  225. $width(posedge CLK &&& (~flag_slow_read), tCLH, 0, timing_error);
  226. $width(negedge CLK &&& (~flag_slow_read), tCLL, 0, timing_error);
  227. specparam tCYCR = 20; // Minimum CLK period READ_PAGE
  228. specparam tCRLH = 8; // Minimum CLK high time READ_PAGE
  229. specparam tCRLL = 8; // Minimum CLK low time READ_PAGE
  230. $period(posedge CLK &&& (flag_slow_read), tCYCR, timing_error);
  231. $width(posedge CLK &&& (flag_slow_read), tCRLH, 0, timing_error);
  232. $width(negedge CLK &&& (flag_slow_read), tCRLL, 0, timing_error);
  233. // DIO timing checks
  234. specparam tDVCH = 2; // DIO Data setup time
  235. specparam tCHDX = 3; // DIO Data hold time
  236. // Make sure to turn off DIO input timing checks when outputing data in dual / quad output mode.
  237. $setup(DIO, posedge CLK &&& (~DIO_Output_Enable), tDVCH, timing_error);
  238. $hold(posedge CLK, DIO &&& (~DIO_Output_Enable), tCHDX, timing_error);
  239. // WPn timing checks
  240. specparam tWHSL = 20;
  241. specparam tSHWL = 100;
  242. // Make sure to turn off WPn timing checks when outputing data in quad output mode
  243. // As well, there is no way to detect setup time of CSn and WPn relative to the Write Status Register
  244. // command. Disable timing checks
  245. //$setup(posedge WPn, negedge CSn &&& (~flag_quad_mode), tWHSL, timing_error);
  246. //$setup(posedge CSn, negedge WPn &&& (~flag_quad_mode), tSHWL, timing_error);
  247. // HOLDn timing checks
  248. specparam tHLQZ = 12;
  249. specparam tHHQX = 7;
  250. specparam tSUS = 20000;
  251. specparam tCHHL = 5;
  252. $setup(posedge CLK, negedge HOLDn &&& (flag_quad_mode_cs),tCHHL, timing_error);
  253. specparam tHLCH = 5; // Need to verify from datasheet
  254. $hold(posedge CLK, negedge HOLDn &&& (flag_quad_mode_cs),tHLCH, timing_error);
  255. specparam tCHHH = 5;
  256. $setup(posedge CLK, posedge HOLDn &&& (flag_quad_mode_cs),tCHHH, timing_error);
  257. specparam tHHCH = 5;
  258. $hold(posedge CLK, posedge HOLDn &&& (flag_quad_mode_cs), tHHCH, timing_error);
  259. endspecify
  260. parameter tCLQV = 6; // Time to DO output valid.
  261. parameter tSHQZ = 7; // Data output disable time.
  262. parameter tW = 10000000; // Write Status Register Write Time
  263. parameter tRES1 = 3000; // Release from power down time 1
  264. parameter tRES2 = 1800; // Release from power down time 2
  265. parameter tDP = 3000; // Time for device to enter deep power down.
  266. parameter tPP = 700000; // Page Program Time
  267. parameter tBP1 = 30000;
  268. parameter tSE = 45000000; // Sector Erase Time.
  269. parameter tBE1 = 120000000; // Block Erase Time. 32KB
  270. parameter tBE2 = 150000000; // Block Erase Time. 64KB
  271. parameter tCE_40 = 1000000000; // Chip Erase Time. This constant should be repeated 40 times.
  272. //parameter tSE = 100000; // Sector Erase Time.
  273. //parameter tBE1 = 1200000; // Block Erase Time. 32KB
  274. //parameter tBE2 = 1500000; // Block Erase Time. 64KB
  275. //parameter tCE_40 = 10000000; // Chip Erase Time. This constant should be repeated 40 times.
  276. /******************************************************************************
  277. The following code is the initialization code run at the beginning of the
  278. simulation.
  279. ******************************************************************************/
  280. initial
  281. begin :initialization
  282. // Erase memory array to FFh state.
  283. //for(x = 0; x < (NUM_PAGES * PAGESIZE); x=x+1)
  284. // memory[x] = 8'hff;
  285. //dump_mem();
  286. $readmemh(`MEM_FILENAME,memory);
  287. // $readmemh(`SECSI_FILENAME,secsi);
  288. // $readmemh(`SFDP_FILENAME,sfdp);
  289. // $readmemh(`SREG_FILENAME,status_reg_otp);
  290. chip_reset();
  291. end
  292. /******************************************************************************
  293. The following continuous assignment statement assigns the DIO_Reg register to the
  294. DIO inout wire and so on for the rest of the quad outputs.
  295. ******************************************************************************/
  296. assign DIO = DIO_Output_Enable_reg ? DIO_Reg : 1'bz;
  297. assign DO = DO_Output_Enable ? DO_Reg : 1'bz;
  298. assign WPn = WPn_Output_Enable_reg ? WPn_Reg : 1'bz;
  299. assign HOLDn = HOLDn_Output_Enable ? HOLDn_Reg : 1'bz;
  300. /******************************************************************************
  301. The following routine occurs when CSn goes low.
  302. The following routine reads the opcode in from the SPI port and starts command
  303. execution. All commands execute the following flow:
  304. Command Dispatch ==> Command Protocol Handler ==> Command State Machine (if necessary)
  305. Whenever CSn goes high, the Command Dispatch and Command Protocol Handler functions
  306. stop execution. The Individual Command State Machines continue to run until
  307. completion, regardless of the state of CSn.
  308. ******************************************************************************/
  309. always @(negedge CSn) // When CSn goes low, device becomes active
  310. begin :read_opcode
  311. flag_read_op_reg = 1'b1; // Assume a read command first. If write, update variable in case statement.
  312. mode_reg = mode_reg & 8'hf0;
  313. if((mode_reg & 8'h30) != 8'h20) // If we are in mode 0x20, skip inputing command byte, execute last command
  314. input_byte(cmd_byte); // Read Opcode from SPI Port
  315. if(!is_qpi(cmd_byte))
  316. begin
  317. $display("WARNING: Non-QPI command was executed in QPI mode");
  318. $stop;
  319. end
  320. if(cmd_byte != `CMD_CHIP_RESET)
  321. flag_enable_reset = 0; // Ensure that ENABLE_RESET immediately precedes CHIP_RESET
  322. case (cmd_byte) // Now dispatch the correct function
  323. // Mode and Reset commands.
  324. `CMD_SET_READ_PARAM :
  325. begin
  326. if(!status_reg[`WIP] && !flag_power_down && flag_qpi_mode)
  327. begin
  328. input_byte(read_param_reg_shadow);
  329. flag_set_read_param = 1;
  330. get_posclk_holdn;
  331. flag_set_read_param = 0;
  332. end
  333. end
  334. `CMD_ENABLE_QPI :
  335. begin
  336. if(!status_reg[`WIP] && !flag_power_down)
  337. begin
  338. if(status_reg[`QE] == 1)
  339. flag_qpi_mode = 1;
  340. end
  341. end
  342. `CMD_MODE_RESET :
  343. begin
  344. if(!flag_power_down)
  345. flag_qpi_mode = 0;
  346. end
  347. `CMD_ENABLE_RESET : // Reset can happen at any time.
  348. begin
  349. flag_enable_reset = 1;
  350. end
  351. `CMD_CHIP_RESET :
  352. begin
  353. if(flag_enable_reset == 1)
  354. begin
  355. flag_reset = 1;
  356. @(posedge CLK);
  357. flag_reset = 0;
  358. end
  359. end
  360. // Power, ID and Extended Address commands
  361. `CMD_DEEP_POWERDOWN :
  362. begin
  363. if(!status_reg[`WIP] && !flag_power_down)
  364. begin
  365. flag_power_down = 1;
  366. @(posedge CLK);
  367. flag_power_down = 0;
  368. end
  369. end
  370. `CMD_READ_SIGNATURE :
  371. begin
  372. if(!status_reg[`WIP])
  373. begin
  374. flag_power_up_exec = 1;
  375. input_byte(null_reg);
  376. input_byte(null_reg);
  377. input_byte(null_reg);
  378. forever
  379. begin
  380. output_byte(DEVICE_ID);
  381. flag_power_up_sig_read = 1;
  382. end
  383. end
  384. end
  385. `CMD_READ_JEDEC_ID :
  386. begin
  387. if(!status_reg[`WIP] && !flag_power_down)
  388. begin
  389. output_byte(MANUFACTURER);
  390. if(flag_qpi_mode)
  391. output_byte(JEDEC_ID_HI_QPI);
  392. else
  393. output_byte(JEDEC_ID_HI);
  394. output_byte(JEDEC_ID_LO);
  395. end
  396. end
  397. `CMD_READ_ID :
  398. begin
  399. if(!status_reg[`WIP] && !flag_power_down)
  400. begin
  401. byte_address = 0;
  402. input_byte(byte_address[23:16]);
  403. input_byte(byte_address[15:8]);
  404. input_byte(byte_address[7:0]);
  405. forever
  406. begin
  407. if(byte_address[0])
  408. begin
  409. output_byte(DEVICE_ID);
  410. output_byte(MANUFACTURER);
  411. end
  412. else
  413. begin
  414. output_byte(MANUFACTURER);
  415. output_byte(DEVICE_ID);
  416. end
  417. end
  418. end
  419. end
  420. `CMD_READ_ID_DUAL :
  421. begin
  422. if(!status_reg[`WIP] && !flag_power_down)
  423. begin
  424. byte_address = 0;
  425. input_byte_dual(byte_address[23:16]);
  426. input_byte_dual(byte_address[15:8]);
  427. input_byte_dual(byte_address[7:0]);
  428. input_byte_dual(mode_reg[7:0]);
  429. forever
  430. begin
  431. if(byte_address[0])
  432. begin
  433. output_byte_dual(DEVICE_ID);
  434. output_byte_dual(MANUFACTURER);
  435. end
  436. else
  437. begin
  438. output_byte_dual(MANUFACTURER);
  439. output_byte_dual(DEVICE_ID);
  440. end
  441. end
  442. end
  443. end
  444. `CMD_READ_ID_QUAD :
  445. begin
  446. if(!status_reg[`WIP] && !flag_power_down && status_reg[`QE])
  447. begin
  448. byte_address = 0;
  449. input_byte_quad(byte_address[23:16]);
  450. input_byte_quad(byte_address[15:8]);
  451. input_byte_quad(byte_address[7:0]);
  452. input_byte_quad(mode_reg[7:0]);
  453. input_byte_quad(temp[7:0]);
  454. input_byte_quad(temp[7:0]);
  455. forever
  456. begin
  457. if(byte_address[0])
  458. begin
  459. output_byte_quad(DEVICE_ID);
  460. output_byte_quad(MANUFACTURER);
  461. end
  462. else
  463. begin
  464. output_byte_quad(MANUFACTURER);
  465. output_byte_quad(DEVICE_ID);
  466. end
  467. end
  468. end
  469. end
  470. `CMD_READ_UNIQUE_ID :
  471. begin
  472. if(!status_reg[`WIP] && !flag_power_down)
  473. begin
  474. input_byte(null_reg);
  475. input_byte(null_reg);
  476. input_byte(null_reg);
  477. input_byte(null_reg);
  478. output_byte(UNIQUE_ID[63:56]);
  479. output_byte(UNIQUE_ID[55:48]);
  480. output_byte(UNIQUE_ID[47:40]);
  481. output_byte(UNIQUE_ID[39:32]);
  482. output_byte(UNIQUE_ID[31:24]);
  483. output_byte(UNIQUE_ID[23:16]);
  484. output_byte(UNIQUE_ID[15:8]);
  485. output_byte(UNIQUE_ID[7:0]);
  486. end
  487. end
  488. // Status Register commands
  489. `CMD_WRITE_ENABLE :
  490. begin
  491. if((!flag_power_down) && (WPn || status_reg[`QE]))
  492. status_reg[`WEL] = 1;
  493. end
  494. `CMD_WRITE_ENABLE_VSR :
  495. begin
  496. if(!flag_power_down)
  497. flag_volatile_sr_write = 1;
  498. end
  499. `CMD_WRITE_DISABLE :
  500. begin
  501. if(!flag_power_down)
  502. status_reg[`WEL] = 0;
  503. end
  504. `CMD_READ_STATUS :
  505. begin
  506. if(!flag_power_down)
  507. begin
  508. forever
  509. begin
  510. output_byte(status_reg[7:0]);
  511. end
  512. end
  513. end
  514. `CMD_READ_STATUS2 :
  515. begin
  516. if(!flag_power_down)
  517. begin
  518. forever
  519. begin
  520. output_byte(status_reg[15:8]);
  521. end
  522. end
  523. end
  524. `CMD_READ_STATUS3 :
  525. begin
  526. if(!flag_power_down)
  527. begin
  528. forever
  529. begin
  530. output_byte(status_reg[23:16]);
  531. end
  532. end
  533. end
  534. `CMD_WRITE_STATUS :
  535. begin
  536. if(!status_reg[`WIP] && (status_reg[`WEL] || flag_volatile_sr_write) && !flag_power_down && !status_reg[`SUS])
  537. begin
  538. flag_read_op_reg = 1'b0;
  539. case ({status_reg[`SRP1],status_reg[`SRP0]})
  540. 2'b00, 2'b01 :
  541. begin
  542. if((status_reg[`SRP0] && WPn) || !status_reg[`SRP0] || status_reg[`QE])
  543. begin
  544. // Zero out high order byte of status register
  545. status_reg_shadow[23:8] = status_reg[23:8];
  546. input_byte(status_reg_shadow[7:0]);
  547. // flag write now that we have 8 bits....2nd 8 bits is optional
  548. // command must bail if /CS does not go high at 8th or 16th clock
  549. flag_write_status_reg = 1;
  550. // 2nd byte is optional
  551. if(flag_qpi_mode == 1)
  552. @(posedge CLK);
  553. else
  554. get_posclk_holdn; // If an extra clock comes before CSn goes high, kill command read 2nd byte.
  555. flag_write_status_reg = 0;
  556. input_byte_no1stclock(temp);
  557. flag_write_status_reg = 1;
  558. status_reg_shadow[15:8] = temp;
  559. if(flag_qpi_mode == 1)
  560. @(posedge CLK);
  561. else
  562. get_posclk_holdn; // If an extra clock comes before CSn goes high, kill command read 2nd byte.
  563. flag_write_status_reg = 0;
  564. end
  565. end
  566. endcase
  567. end
  568. end
  569. `CMD_WRITE_STATUS2 :
  570. begin
  571. if(!status_reg[`WIP] && (status_reg[`WEL] || flag_volatile_sr_write) && !flag_power_down && !status_reg[`SUS])
  572. begin
  573. flag_read_op_reg = 1'b0;
  574. case ({status_reg[`SRP1],status_reg[`SRP0]})
  575. 2'b00, 2'b01 :
  576. begin
  577. if((status_reg[`SRP0] && WPn) || !status_reg[`SRP0] || status_reg[`QE])
  578. begin
  579. status_reg_shadow[23:16] = status_reg[23:16];
  580. status_reg_shadow[7:0] = status_reg[7:0];
  581. input_byte(status_reg_shadow[15:8]);
  582. // flag write now that we have 8 bits....
  583. // command must bail if /CS does not go high at 8th clock
  584. flag_write_status_reg = 1;
  585. // 2nd byte is optional
  586. if(flag_qpi_mode == 1)
  587. @(posedge CLK);
  588. else
  589. get_posclk_holdn; // If an extra clock comes before CSn goes high, kill command read 2nd byte.
  590. flag_write_status_reg = 0;
  591. end
  592. end
  593. endcase
  594. end
  595. end
  596. `CMD_WRITE_STATUS3 :
  597. begin
  598. if(!status_reg[`WIP] && (status_reg[`WEL] || flag_volatile_sr_write) && !flag_power_down && !status_reg[`SUS])
  599. begin
  600. flag_read_op_reg = 1'b0;
  601. case ({status_reg[`SRP1],status_reg[`SRP0]})
  602. 2'b00, 2'b01 :
  603. begin
  604. if((status_reg[`SRP0] && WPn) || !status_reg[`SRP0] || status_reg[`QE])
  605. begin
  606. status_reg_shadow[15:0] = status_reg[15:0];
  607. input_byte(status_reg_shadow[23:16]);
  608. // flag write now that we have 8 bits....
  609. // command must bail if /CS does not go high at 8th clock
  610. flag_write_status_reg = 1;
  611. // 2nd byte is optional
  612. if(flag_qpi_mode == 1)
  613. @(posedge CLK);
  614. else
  615. get_posclk_holdn; // If an extra clock comes before CSn goes high, kill command read 2nd byte.
  616. flag_write_status_reg = 0;
  617. end
  618. end
  619. endcase
  620. end
  621. end
  622. // Write Page Commands
  623. `CMD_PAGE_PROGRAM :
  624. begin
  625. if(status_reg[`WEL] && !status_reg[`SUS] && !flag_power_down)
  626. begin
  627. flag_read_op_reg = 1'b0;
  628. write_page(0);
  629. end
  630. end
  631. `CMD_PAGE_PROGRAM_QUAD :
  632. begin
  633. if(status_reg[`WEL]&& !status_reg[`SUS] && status_reg[`QE] && !flag_power_down)
  634. begin
  635. flag_read_op_reg = 1'b0;
  636. write_page(1);
  637. end
  638. end
  639. // Suspend / Resume Commands
  640. `CMD_SUSPEND :
  641. begin
  642. if(!flag_power_down && !flag_erase_bulk)
  643. begin
  644. if((!flag_suspend) && (flag_erase_sector || flag_erase_secsi_sector || flag_erase_half_block || flag_erase_block || flag_prog_page || flag_prog_secsi_page))
  645. begin
  646. flag_suspend = 1'b1;
  647. get_posclk_holdn; // If an extra clock comes before CSn goes high, kill command.
  648. flag_suspend = 1'b0;
  649. end
  650. end
  651. end
  652. `CMD_RESUME :
  653. begin
  654. if(!flag_power_down)
  655. begin
  656. if(flag_suspend)
  657. begin
  658. flag_resume = 1'b1;
  659. get_posclk_holdn; // If an extra clock comes before CSn goes high, kill command.
  660. flag_resume = 1'b0;
  661. end
  662. end
  663. end
  664. // Erase Commands
  665. `CMD_SECTOR_ERASE :
  666. begin
  667. if(status_reg[`WEL] && !flag_power_down && !status_reg[`SUS])
  668. begin
  669. flag_read_op_reg = 1'b0;
  670. input_byte(byte_address[23:16]);
  671. input_byte(byte_address[15:8]);
  672. input_byte(byte_address[7:0]);
  673. if(!write_protected(byte_address))
  674. begin
  675. flag_erase_sector = 1;
  676. get_posclk_holdn; // If an extra clock comes before CSn goes high, kill command.
  677. flag_erase_sector = 0;
  678. end
  679. end
  680. end
  681. `CMD_HALF_BLOCK_ERASE :
  682. begin
  683. if(status_reg[`WEL] && !flag_power_down && !status_reg[`SUS])
  684. begin
  685. flag_read_op_reg = 1'b0;
  686. input_byte(byte_address[23:16]);
  687. input_byte(byte_address[15:8]);
  688. input_byte(byte_address[7:0]);
  689. if(!write_protected(byte_address))
  690. begin
  691. flag_erase_half_block = 1;
  692. get_posclk_holdn; // If an extra clock comes before CSn goes high, kill command.
  693. flag_erase_half_block = 0;
  694. end
  695. end
  696. end
  697. `CMD_BLOCK_ERASE :
  698. begin
  699. if(status_reg[`WEL] && !flag_power_down && !status_reg[`SUS])
  700. begin
  701. flag_read_op_reg = 1'b0;
  702. input_byte(byte_address[23:16]);
  703. input_byte(byte_address[15:8]);
  704. input_byte(byte_address[7:0]);
  705. if(!write_protected(byte_address))
  706. begin
  707. flag_erase_block = 1;
  708. get_posclk_holdn; // If an extra clock comes before CSn goes high, kill command.
  709. flag_erase_block = 0;
  710. end
  711. end
  712. end
  713. `CMD_BULK_ERASE, `CMD_BULK_ERASE2 :
  714. begin
  715. if(status_reg[`WEL] && !flag_power_down && !status_reg[`SUS])
  716. begin
  717. flag_read_op_reg = 1'b0;
  718. case ({status_reg[`BP0],status_reg[`BP1]})
  719. 2'b00 :
  720. begin
  721. flag_erase_bulk = 1;
  722. get_posclk_holdn;
  723. flag_erase_bulk = 0;
  724. end
  725. endcase
  726. end
  727. end
  728. // Read Page Commands
  729. `CMD_READ_DATA :
  730. begin
  731. if(!flag_power_down)
  732. begin
  733. flag_slow_read_reg = 1'b1;
  734. read_page(0,0);
  735. end
  736. end
  737. `CMD_READ_DATA_FAST :
  738. begin
  739. if(!flag_power_down)
  740. read_page(1,0);
  741. end
  742. `CMD_READ_DATA_FAST_WRAP :
  743. begin
  744. if(!flag_power_down)
  745. begin
  746. if(flag_qpi_mode)
  747. read_page_quadio(cmd_byte);
  748. else
  749. read_page(1,0);
  750. end
  751. end
  752. `CMD_READ_DATA_FAST_DUAL :
  753. begin
  754. if(!flag_power_down)
  755. read_page(2,0);
  756. end
  757. `CMD_READ_DATA_FAST_QUAD :
  758. begin
  759. if(!flag_power_down && status_reg[`QE])
  760. read_page(3,0);
  761. end
  762. `CMD_READ_DATA_FAST_DUAL_IO :
  763. begin
  764. if(!flag_power_down)
  765. read_page_dualio;
  766. end
  767. `CMD_READ_DATA_FAST_QUAD_IO :
  768. begin
  769. if(!flag_power_down && status_reg[`QE])
  770. read_page_quadio(cmd_byte);
  771. end
  772. `CMD_READ_OCTAL_FAST_QUAD_IO :
  773. begin
  774. if(!flag_power_down && status_reg[`QE])
  775. read_page_quadio(cmd_byte);
  776. end
  777. `CMD_READ_WORD_FAST_QUAD_IO :
  778. begin
  779. if(!flag_power_down && status_reg[`QE])
  780. read_page_quadio(cmd_byte);
  781. end
  782. `CMD_SET_BURST_WRAP :
  783. begin
  784. if(!flag_power_down && status_reg[`QE])
  785. begin
  786. input_byte_quad(temp[7:0]);
  787. input_byte_quad(temp[7:0]);
  788. input_byte_quad(temp[7:0]);
  789. input_byte_quad(wrap_reg[7:0]);
  790. end
  791. end
  792. `CMD_READ_SFDP :
  793. begin
  794. if(!flag_power_down)
  795. begin
  796. flag_slow_read_reg = 1'b1;
  797. read_page(0,2);
  798. end
  799. end
  800. // Security Register Opcodes
  801. `CMD_SREG_READ :
  802. begin
  803. if(!flag_power_down)
  804. begin
  805. read_page(0,1);
  806. end
  807. end
  808. `CMD_SREG_ERASE :
  809. begin
  810. if(status_reg[`WEL] && !flag_power_down && !status_reg[`SUS])
  811. begin
  812. flag_read_op_reg = 1'b0;
  813. input_byte(byte_address[23:16]);
  814. input_byte(byte_address[15:8]);
  815. input_byte(byte_address[7:0]);
  816. case (byte_address[23:8])
  817. 16'h10 :
  818. begin
  819. if(!status_reg[`LB1])
  820. begin
  821. flag_erase_secsi_sector = 1;
  822. get_posclk_holdn;
  823. flag_erase_secsi_sector = 0;
  824. end
  825. end
  826. 16'h20 :
  827. begin
  828. if(!status_reg[`LB2])
  829. begin
  830. flag_erase_secsi_sector = 1;
  831. get_posclk_holdn;
  832. flag_erase_secsi_sector = 0;
  833. end
  834. end
  835. 16'h30 :
  836. begin
  837. if(!status_reg[`LB3])
  838. begin
  839. flag_erase_secsi_sector = 1;
  840. get_posclk_holdn;
  841. flag_erase_secsi_sector = 0;
  842. end
  843. end
  844. endcase
  845. end
  846. end
  847. `CMD_SREG_PROGRAM :
  848. begin
  849. if(status_reg[`WEL] && !flag_power_down && !status_reg[`SUS])
  850. begin
  851. flag_read_op_reg = 1'b0;
  852. begin
  853. if(!status_reg[`WIP])
  854. begin
  855. input_byte(prog_byte_address[23:16]);
  856. input_byte(prog_byte_address[15:8]);
  857. input_byte(prog_byte_address[7:0]);
  858. case (byte_address[23:8])
  859. 16'h10 :
  860. if(!status_reg[`LB1])
  861. fill_page_latch(0,prog_byte_address,1);
  862. 16'h20 :
  863. if(!status_reg[`LB2])
  864. fill_page_latch(0,prog_byte_address,1);
  865. 16'h30 :
  866. if(!status_reg[`LB3])
  867. fill_page_latch(0,prog_byte_address,1);
  868. endcase
  869. end
  870. end
  871. end
  872. end
  873. // Lock Bit commands
  874. `CMD_GLOBAL_BLOCK_LOCK :
  875. begin
  876. if(!status_reg[`WIP] && !flag_power_down)
  877. begin
  878. for(x = 0; x < NUM_LOCKBITS; x=x+1)
  879. lock_array[x] = 1;
  880. end
  881. end
  882. `CMD_GLOBAL_BLOCK_UNLOCK :
  883. begin
  884. if(!status_reg[`WIP] && !flag_power_down)
  885. begin
  886. for(x = 0; x < NUM_LOCKBITS; x=x+1)
  887. lock_array[x] = 0;
  888. end
  889. end
  890. `CMD_INDIVIDUAL_LOCK :
  891. begin
  892. if(!status_reg[`WIP] && !flag_power_down)
  893. begin
  894. input_byte(byte_address[23:16]);
  895. input_byte(byte_address[15:8]);
  896. input_byte(byte_address[7:0]);
  897. lock_array[lockbit_index(byte_address)] = 1;
  898. end
  899. end
  900. `CMD_INDIVIDUAL_UNLOCK :
  901. begin
  902. if(!status_reg[`WIP] && !flag_power_down)
  903. begin
  904. input_byte(byte_address[23:16]);
  905. input_byte(byte_address[15:8]);
  906. input_byte(byte_address[7:0]);
  907. lock_array[lockbit_index(byte_address)] = 0;
  908. end
  909. end
  910. `CMD_READ_BLOCK_LOCK :
  911. begin
  912. if(!status_reg[`WIP] && !flag_power_down)
  913. begin
  914. input_byte(byte_address[23:16]);
  915. input_byte(byte_address[15:8]);
  916. input_byte(byte_address[7:0]);
  917. null_reg[7:1] = 0;
  918. null_reg[0] = lock_array[lockbit_index(byte_address)];
  919. output_byte(null_reg);
  920. end
  921. end
  922. default :
  923. begin
  924. $display("Invalid Opcode. (%0h)",cmd_byte);
  925. $stop;
  926. end
  927. endcase
  928. end
  929. /******************************************************************************
  930. The following routine occurs when CSn goes high. In the case, all communications
  931. activities inside the chip must halt. Transfer and Program/Erase conditions
  932. will continue.
  933. ******************************************************************************/
  934. always @(posedge CSn) // When CSn goes high, device becomes in-active
  935. begin :disable_interface
  936. #tSHQZ; // Data-output disable time
  937. HOLDn_Active = 1'b0; // Disable HOLDn from mucking with output registers.
  938. DO_Output_Enable = 1'b0; // Tri-state DO output.
  939. DIO_Output_Enable_reg = 1'b0; // Tri-state DIO output.
  940. WPn_Output_Enable_reg = 1'b0; // Tri-state WPn output
  941. HOLDn_Output_Enable = 1'b0; // Tri-state HOLDn output
  942. flag_slow_read_reg = 1'b0; // Initiate normal timing checks
  943. disable input_byte;
  944. disable input_byte_dual;
  945. disable input_mode_dual;
  946. disable input_byte_quad;
  947. disable output_byte;
  948. disable output_byte_dual;
  949. disable output_byte_quad;
  950. disable read_opcode;
  951. disable write_page;
  952. disable fill_page_latch;
  953. disable read_page;
  954. disable read_page_dualio;
  955. disable read_page_quadio;
  956. disable get_posclk_holdn;
  957. disable get_negclk_holdn;
  958. end
  959. /******************************************************************************
  960. The following routine occurs when HOLDn goes low.
  961. ******************************************************************************/
  962. always @(negedge (HOLDn & !status_reg[`QE] & !CSn))
  963. begin
  964. if(!HOLDn)
  965. begin
  966. #tHLQZ;
  967. temp_DIO_Output_Enable_reg = DIO_Output_Enable_reg;
  968. temp_DO_Output_Enable = DO_Output_Enable;
  969. DIO_Output_Enable_reg = 1'b0; // Set DIO and DO to an input state
  970. DO_Output_Enable = 1'b0;
  971. HOLDn_Active = 1'b1;
  972. end
  973. end
  974. /******************************************************************************
  975. The following routine occurs when HOLDn goes high.
  976. ******************************************************************************/
  977. always @(posedge HOLDn)
  978. begin
  979. if(HOLDn_Active == 1'b1)
  980. begin
  981. #tHHQX;
  982. DIO_Output_Enable_reg = temp_DIO_Output_Enable_reg;
  983. DO_Output_Enable = temp_DO_Output_Enable;
  984. HOLDn_Active = 1'b0;
  985. end
  986. end
  987. /******************************************************************************
  988. GENERAL PURPOSE SUBROUTINES
  989. ******************************************************************************/
  990. task chip_reset;
  991. integer x;
  992. begin
  993. // Tri-state all outputs
  994. temp_DIO_Output_Enable_reg = 1'b0;
  995. DIO_Output_Enable_reg = 1'b0; // Tri-state DIO Output
  996. temp_DO_Output_Enable = 1'b0;
  997. DO_Output_Enable = 1'b0; // Tri-state DO Output.
  998. WPn_Output_Enable_reg = 1'b0; // Tri-state WPn Output
  999. HOLDn_Output_Enable = 1'b0; // Tri-state HOLDn Output
  1000. HOLDn_Active = 1'b0;
  1001. // Set all output registers to default to 0
  1002. DIO_Reg = 1'b0;
  1003. DO_Reg = 1'b0;
  1004. WPn_Reg = 1'b0;
  1005. HOLDn_Reg = 1'b0;
  1006. mode_reg = 8'h00; // Setup null mode register
  1007. wrap_reg = 8'b00010000; // Setup Bit 4 of wrap register to 1 as default
  1008. read_param_reg = 8'h00; // Reset defaults for read parameter register
  1009. status_reg = 0; // Status register default OTP values.
  1010. // status_reg[`QE] = status_reg_otp[`QE];
  1011. status_reg[`QE] = 1;
  1012. status_reg[`SRP1] = 0;//status_reg_otp[`SRP1];
  1013. status_reg[`SRP0] = 0;//status_reg_otp[`SRP0];
  1014. status_reg[`BP0] = 0;//status_reg_otp[`BP0];
  1015. status_reg[`BP1] = 0;//status_reg_otp[`BP1];
  1016. status_reg[`BP2] = 0;//status_reg_otp[`BP2];
  1017. status_reg[`TB] = 0;//status_reg_otp[`TB];
  1018. status_reg[`SEC] = 0;//status_reg_otp[`SEC];
  1019. status_reg[`CMP] = 0;//status_reg_otp[`CMP];
  1020. status_reg[`WPS] = 0;//status_reg_otp[`WPS];
  1021. status_reg[`DRV0] = 0;//status_reg_otp[`DRV0];
  1022. status_reg[`DRV1] = 0;//status_reg_otp[`DRV1];
  1023. status_reg[`HLD_RST] = 0;//status_reg_otp[`HLD_RST];
  1024. status_reg[`LB1] = 0;//status_reg_otp[`LB1];
  1025. status_reg[`LB2] = 0;//status_reg_otp[`LB2];
  1026. status_reg[`LB3] = 0;//status_reg_otp[`LB3];
  1027. flag_prog_page = 0;
  1028. flag_prog_secsi_page = 0;
  1029. flag_erase_sector = 0;
  1030. flag_erase_half_block = 0;
  1031. flag_erase_block = 0;
  1032. flag_erase_secsi_sector = 0;
  1033. flag_erase_bulk = 0;
  1034. flag_power_down = 0;
  1035. flag_power_up_exec = 0;
  1036. flag_power_up_sig_read = 0;
  1037. flag_write_status_reg = 0;
  1038. flag_slow_read_reg = 1'b0; // Flag for standard read command....i.e. different timings
  1039. flag_read_op_reg = 1'b0; // Flag for any read command....i.e. different timings.
  1040. flag_suspend = 1'b0; // clear erase suspend status
  1041. flag_suspend_enabled = 1'b0;
  1042. flag_volatile_sr_write = 1'b0;
  1043. flag_qpi_mode = 0;
  1044. flag_enable_reset = 0;
  1045. flag_reset = 0;
  1046. flag_reset_condition = 0;
  1047. flag_set_read_param = 0;
  1048. timing_error = 0;
  1049. cmd_byte = 0;
  1050. null_reg = 0;
  1051. in_byte = 0;
  1052. out_byte = 0;
  1053. // Reset the Lock Array to full write protect
  1054. for(x = 0; x < NUM_LOCKBITS; x=x+1)
  1055. lock_array[x] = 1;
  1056. end
  1057. endtask
  1058. /******************************************************************************
  1059. The following routine will input 1 byte from the SPI DIO pin and place
  1060. the results in the input_data register.
  1061. ******************************************************************************/
  1062. task input_byte;
  1063. output [7:0] input_data;
  1064. integer x;
  1065. begin
  1066. if(flag_qpi_mode == 1)
  1067. input_byte_quad(input_data);
  1068. else
  1069. begin
  1070. // Set the DIO output register high-Z
  1071. if(DIO_Output_Enable_reg != 1'b0)
  1072. DIO_Output_Enable_reg = 1'b0;
  1073. for(x = 7; x >= 0; x=x-1)
  1074. begin
  1075. get_posclk_holdn;
  1076. input_data[x] = DIO;
  1077. end
  1078. in_byte = input_data;
  1079. end
  1080. end
  1081. endtask
  1082. /******************************************************************************
  1083. The following routine will input 1 byte from the SPI DIO pin and place
  1084. the results in the input_data register.
  1085. ******************************************************************************/
  1086. task input_byte_no1stclock;
  1087. output [7:0] input_data;
  1088. integer x;
  1089. begin
  1090. if(flag_qpi_mode == 1)
  1091. input_byte_quad_no1stclock(input_data);
  1092. else
  1093. begin
  1094. // Set the DIO output register high-Z
  1095. if(DIO_Output_Enable_reg != 1'b0)
  1096. DIO_Output_Enable_reg = 1'b0;
  1097. for(x = 7; x >= 0; x=x-1)
  1098. begin
  1099. if(x != 7)
  1100. get_posclk_holdn;
  1101. input_data[x] = DIO;
  1102. end
  1103. in_byte = input_data;
  1104. end
  1105. end
  1106. endtask
  1107. /******************************************************************************
  1108. The following routine will input 1 byte from the SPI DIO pin and DO pin and place
  1109. the results in the input_data register.
  1110. ******************************************************************************/
  1111. task input_byte_dual;
  1112. output [7:0] input_data;
  1113. integer x;
  1114. begin
  1115. // Set the DIO output register high-Z
  1116. if(DIO_Output_Enable_reg != 1'b0)
  1117. DIO_Output_Enable_reg = 1'b0;
  1118. // Set the DO output register high-Z
  1119. if(DO_Output_Enable != 1'b0)
  1120. DO_Output_Enable = 1'b0;
  1121. for(x = 7; x >= 0; x=x-2)
  1122. begin
  1123. get_posclk_holdn;
  1124. input_data[x-1] = DIO;
  1125. input_data[x] = DO;
  1126. end
  1127. in_byte = input_data;
  1128. end
  1129. endtask
  1130. /******************************************************************************
  1131. The following routine will input 1 nibble from the SPI DIO pin and DO pin and place
  1132. the results in the input_data register.
  1133. ******************************************************************************/
  1134. task input_mode_dual;
  1135. output [5:0] input_data;
  1136. integer x;
  1137. begin
  1138. // Set the DIO output register high-Z
  1139. if(DIO_Output_Enable_reg != 1'b0)
  1140. DIO_Output_Enable_reg = 1'b0;
  1141. // Set the DO output register high-Z
  1142. if(DO_Output_Enable != 1'b0)
  1143. DO_Output_Enable = 1'b0;
  1144. for(x = 5; x >= 0; x=x-2)
  1145. begin
  1146. get_posclk_holdn;
  1147. input_data[x-1] = DIO;
  1148. input_data[x] = DO;
  1149. end
  1150. end
  1151. endtask
  1152. /******************************************************************************
  1153. The following routine will input 1 byte from the SPI DIO and DO and WPn and HOLDn pins
  1154. and place the results in the input_data register.
  1155. ******************************************************************************/
  1156. task input_byte_quad;
  1157. output [7:0] input_data;
  1158. integer x;
  1159. begin
  1160. // Set the DIO output register high-Z
  1161. if(DIO_Output_Enable_reg != 1'b0)
  1162. DIO_Output_Enable_reg = 1'b0;
  1163. // Set the DO output register high-Z
  1164. if(DO_Output_Enable != 1'b0)
  1165. DO_Output_Enable = 1'b0;
  1166. // Set the WPn output register high-Z
  1167. if(WPn_Output_Enable_reg != 1'b0)
  1168. WPn_Output_Enable_reg = 1'b0;
  1169. // Set the HOLDn output register high-Z
  1170. if(HOLDn_Output_Enable != 1'b0)
  1171. DO_Output_Enable = 1'b0;
  1172. for(x = 7; x >= 0; x=x-4)
  1173. begin
  1174. @(posedge CLK);
  1175. input_data[x-3] = DIO;
  1176. input_data[x-2] = DO;
  1177. input_data[x-1] = WPn;
  1178. input_data[x] = HOLDn;
  1179. end
  1180. in_byte = input_data;
  1181. end
  1182. endtask
  1183. /******************************************************************************
  1184. The following routine will input 1 byte from the SPI DIO and DO and WPn and HOLDn pins
  1185. and place the results in the input_data register.
  1186. ******************************************************************************/
  1187. task input_byte_quad_no1stclock;
  1188. output [7:0] input_data;
  1189. integer x;
  1190. begin
  1191. // Set the DIO output register high-Z
  1192. if(DIO_Output_Enable_reg != 1'b0)
  1193. DIO_Output_Enable_reg = 1'b0;
  1194. // Set the DO output register high-Z
  1195. if(DO_Output_Enable != 1'b0)
  1196. DO_Output_Enable = 1'b0;
  1197. // Set the WPn output register high-Z
  1198. if(WPn_Output_Enable_reg != 1'b0)
  1199. WPn_Output_Enable_reg = 1'b0;
  1200. // Set the HOLDn output register high-Z
  1201. if(HOLDn_Output_Enable != 1'b0)
  1202. DO_Output_Enable = 1'b0;
  1203. for(x = 7; x >= 0; x=x-4)
  1204. begin
  1205. if(x != 7)
  1206. @(posedge CLK);
  1207. input_data[x-3] = DIO;
  1208. input_data[x-2] = DO;
  1209. input_data[x-1] = WPn;
  1210. input_data[x] = HOLDn;
  1211. end
  1212. in_byte = input_data;
  1213. end
  1214. endtask
  1215. /******************************************************************************
  1216. The following routine will output 1 byte to the DO pin.
  1217. ******************************************************************************/
  1218. task output_byte;
  1219. input [7:0] output_data;
  1220. integer x;
  1221. begin
  1222. if(flag_qpi_mode == 1)
  1223. output_byte_quad(output_data);
  1224. else
  1225. begin
  1226. out_byte = output_data;
  1227. for(x = 7; x >= 0; x=x-1)
  1228. begin
  1229. get_negclk_holdn;
  1230. if(DO_Output_Enable == 1'b0) // If the bus is not enabled, enable it now.
  1231. DO_Output_Enable = 1'b1;
  1232. #tCLQV DO_Reg = output_data[x];
  1233. end
  1234. end
  1235. end
  1236. endtask
  1237. /******************************************************************************
  1238. The following routine will output 1 byte to the DO and DIO pin.
  1239. ******************************************************************************/
  1240. task output_byte_dual;
  1241. input [7:0] output_data;
  1242. integer x;
  1243. begin
  1244. out_byte = output_data;
  1245. for(x = 7; x >= 0; x=x-2)
  1246. begin
  1247. get_negclk_holdn;
  1248. if(DO_Output_Enable == 1'b0) // If the bus is not enabled, enable it now.
  1249. DO_Output_Enable = 1'b1;
  1250. if(DIO_Output_Enable_reg == 1'b0)
  1251. DIO_Output_Enable_reg = 1'b1;
  1252. #tCLQV ;
  1253. DIO_Reg = output_data[x-1];
  1254. DO_Reg = output_data[x];
  1255. end
  1256. end
  1257. endtask
  1258. /******************************************************************************
  1259. The following routine will output 1 byte to the DO and DIO and WPn and HOLDn pin.
  1260. ******************************************************************************/
  1261. task output_byte_quad;
  1262. input [7:0] output_data;
  1263. integer x;
  1264. begin
  1265. out_byte = output_data;
  1266. for(x = 7; x >= 0; x=x-4)
  1267. begin
  1268. @(negedge CLK);
  1269. if(DO_Output_Enable == 1'b0) // If the bus is not enabled, enable it now.
  1270. DO_Output_Enable = 1'b1;
  1271. if(DIO_Output_Enable_reg == 1'b0)
  1272. DIO_Output_Enable_reg = 1'b1;
  1273. if(WPn_Output_Enable_reg == 1'b0)
  1274. WPn_Output_Enable_reg = 1'b1;
  1275. if(HOLDn_Output_Enable == 1'b0)
  1276. HOLDn_Output_Enable = 1'b1;
  1277. #tCLQV;
  1278. DIO_Reg = output_data[x-3];
  1279. DO_Reg = output_data[x-2];
  1280. WPn_Reg = output_data[x-1];
  1281. HOLDn_Reg = output_data[x];
  1282. end
  1283. end
  1284. endtask
  1285. /******************************************************************************
  1286. The following routine will return when a negative edge happens on CLK with respect
  1287. to the HOLDn signal.
  1288. ******************************************************************************/
  1289. task get_negclk_holdn;
  1290. begin
  1291. if(status_reg[`QE]) // Quad bus is enabled, HOLD condition does not exist
  1292. @(negedge CLK); // Therefore return negedge CLK
  1293. else
  1294. @(negedge (CLK & HOLDn)); // If Quad bus is disabled, return CLK only when HOLDn is high.
  1295. end
  1296. endtask
  1297. /******************************************************************************
  1298. The following routine will return when a positive edge happens on CLK with respect
  1299. to the HOLDn signal.
  1300. ******************************************************************************/
  1301. task get_posclk_holdn;
  1302. begin
  1303. if(status_reg[`QE]) // Quad bus is enabled, HOLD condition does not exist
  1304. @(posedge CLK); // Therefore return negedge CLK
  1305. else
  1306. @(posedge (CLK & HOLDn)); // If Quad bus is disabled, return CLK only when HOLDn is high.
  1307. end
  1308. endtask
  1309. /******************************************************************************
  1310. The following routine will delay the specified amount of time while waiting for the
  1311. flag_suspend_enabled signal or the flag_reset_condition signal. If the flag_suspend_enable asserts, the delay routine will wait indefinetly
  1312. until flag_suspend_enable deasserts; if flag_reset_condition asserts, the routine exits immediately
  1313. ******************************************************************************/
  1314. task wait_reset_suspend;
  1315. input [31:0] delay;
  1316. integer waitx;
  1317. integer num_iterations;
  1318. begin
  1319. // Warning, this routine is not recursive and cannot be called while suspend is enabled!
  1320. // This function delays while optionally waiting for the suspend signal. To reduce CPU simulation resources,
  1321. // This routine will count in tReset_Suspend_Max increments down to a value less than tReset_Suspend_Max wait and then
  1322. // look every nanosecond to finish. It exists under any circumstance if the chip is reset.
  1323. waitx = 0;
  1324. if(delay >= tReset_Suspend_Max)
  1325. begin
  1326. num_iterations = delay / tReset_Suspend_Max;
  1327. for(waitx = 0; waitx < num_iterations; waitx=waitx+1) // check for erase suspend while part is programming
  1328. begin
  1329. if(flag_reset_condition) // If chip is reset, exit loop
  1330. waitx = num_iterations; // Break the loop
  1331. else
  1332. begin
  1333. wait(!flag_suspend_enabled || flag_reset_condition);
  1334. #tReset_Suspend_Max;
  1335. end
  1336. end
  1337. end
  1338. num_iterations = delay % tReset_Suspend_Max;
  1339. for(waitx = 0; waitx < num_iterations; waitx=waitx+1)
  1340. begin
  1341. if(flag_reset_condition) // check for chip reset while part is programming
  1342. waitx = num_iterations;
  1343. else
  1344. begin
  1345. wait(!flag_suspend_enabled || flag_reset_condition); // check for erase suspend while waiting
  1346. #1;
  1347. end
  1348. end
  1349. end
  1350. endtask
  1351. /******************************************************************************
  1352. The following routine will delay the specified amount of time while waiting for the
  1353. flag_reset_condition signal. If flag_reset_condition is asserted, the routine aborts because the chip has been reset
  1354. ******************************************************************************/
  1355. task wait_reset;
  1356. input [31:0] delay;
  1357. integer waitx;
  1358. integer num_iterations;
  1359. begin
  1360. // This task delays while waiting for the reset signal. To reduce CPU simulation resources,
  1361. // This routine will count in tReset_Suspend_Max increments down to a value less than tReset_Suspend_Max wait and then
  1362. // look every nanosecond to finish. It exists under any circumstance if the chip is reset.
  1363. waitx = 0;
  1364. if(delay >= tReset_Suspend_Max)
  1365. begin
  1366. num_iterations = delay / tReset_Suspend_Max;
  1367. for(waitx = 0; waitx < num_iterations; waitx=waitx+1) // check for erase suspend while part is programming
  1368. begin
  1369. if(flag_reset_condition) // If chip is reset, exit loop
  1370. waitx = num_iterations; // Break the loop
  1371. else
  1372. #tReset_Suspend_Max; // else delay
  1373. end
  1374. end
  1375. num_iterations = delay % tReset_Suspend_Max;
  1376. for(waitx = 0; waitx < num_iterations; waitx=waitx+1) // check for erase suspend while part is programming
  1377. begin
  1378. if(flag_reset_condition) // check for chip reset while part is programming
  1379. waitx = num_iterations;
  1380. else
  1381. #1;
  1382. end
  1383. end
  1384. endtask
  1385. /******************************************************************************
  1386. The following function returns whether or not the current page is write
  1387. protected based upon the status register protect bits.
  1388. ******************************************************************************/
  1389. function write_protected;
  1390. input [23:0] byte_address;
  1391. begin
  1392. if(status_reg[`WPS])
  1393. write_protected = lock_array[lockbit_index(byte_address)];
  1394. else
  1395. begin
  1396. casez ({status_reg[`SEC], status_reg[`TB],status_reg[`BP2],status_reg[`BP1],status_reg[`BP0]})
  1397. 5'b??000 :
  1398. write_protected = 1'b0 ^ status_reg[`CMP];
  1399. 5'b00001 :
  1400. begin
  1401. if(byte_address >= (NUM_PAGES * 63 / 64 * PAGESIZE))
  1402. write_protected = 1'b1 ^ status_reg[`CMP];
  1403. else
  1404. write_protected = 1'b0 ^ status_reg[`CMP];
  1405. end
  1406. 5'b00010 :
  1407. begin
  1408. if(byte_address >= (NUM_PAGES * 31 / 32 * PAGESIZE))
  1409. write_protected = 1'b1 ^ status_reg[`CMP];
  1410. else
  1411. write_protected = 1'b0 ^ status_reg[`CMP];
  1412. end
  1413. 5'b00011 :
  1414. begin
  1415. if(byte_address >= (NUM_PAGES * 15 / 16 * PAGESIZE))
  1416. write_protected = 1'b1 ^ status_reg[`CMP];
  1417. else
  1418. write_protected = 1'b0 ^ status_reg[`CMP];
  1419. end
  1420. 5'b00100 :
  1421. begin
  1422. if(byte_address >= (NUM_PAGES * 7 / 8 * PAGESIZE))
  1423. write_protected = 1'b1 ^ status_reg[`CMP];
  1424. else
  1425. write_protected = 1'b0 ^ status_reg[`CMP];
  1426. end
  1427. 5'b00101 :
  1428. begin
  1429. if(byte_address >= (NUM_PAGES * 3 / 4 * PAGESIZE))
  1430. write_protected = 1'b1 ^ status_reg[`CMP];
  1431. else
  1432. write_protected = 1'b0 ^ status_reg[`CMP];
  1433. end
  1434. 5'b00110 :
  1435. begin
  1436. if(byte_address >= (NUM_PAGES * 1 / 2 * PAGESIZE))
  1437. write_protected = 1'b1 ^ status_reg[`CMP];
  1438. else
  1439. write_protected = 1'b0 ^ status_reg[`CMP];
  1440. end
  1441. 5'b01001 :
  1442. begin
  1443. if(byte_address < (NUM_PAGES * 1 / 64 * PAGESIZE))
  1444. write_protected = 1'b1 ^ status_reg[`CMP];
  1445. else
  1446. write_protected = 1'b0 ^ status_reg[`CMP];
  1447. end
  1448. 5'b01010 :
  1449. begin
  1450. if(byte_address < (NUM_PAGES * 1 / 32 * PAGESIZE))
  1451. write_protected = 1'b1 ^ status_reg[`CMP];
  1452. else
  1453. write_protected = 1'b0 ^ status_reg[`CMP];
  1454. end
  1455. 5'b01011 :
  1456. begin
  1457. if(byte_address < (NUM_PAGES * 1 / 16 * PAGESIZE))
  1458. write_protected = 1'b1 ^ status_reg[`CMP];
  1459. else
  1460. write_protected = 1'b0 ^ status_reg[`CMP];
  1461. end
  1462. 5'b01100:
  1463. begin
  1464. if(byte_address < (NUM_PAGES * 1 / 8 * PAGESIZE))
  1465. write_protected = 1'b1 ^ status_reg[`CMP];
  1466. else
  1467. write_protected = 1'b0 ^ status_reg[`CMP];
  1468. end
  1469. 5'b01101 :
  1470. begin
  1471. if(byte_address < (NUM_PAGES * 1 / 4 * PAGESIZE))
  1472. write_protected = 1'b1 ^ status_reg[`CMP];
  1473. else
  1474. write_protected = 1'b0 ^ status_reg[`CMP];
  1475. end
  1476. 5'b01110 :
  1477. begin
  1478. if(byte_address < (NUM_PAGES * 1 / 2 * PAGESIZE))
  1479. write_protected = 1'b1 ^ status_reg[`CMP];
  1480. else
  1481. write_protected = 1'b0 ^ status_reg[`CMP];
  1482. end
  1483. 5'b10001 :
  1484. begin
  1485. if(byte_address >= (NUM_PAGES * 4095 / 4096 * PAGESIZE))
  1486. write_protected = 1'b1 ^ status_reg[`CMP];
  1487. else
  1488. write_protected = 1'b0 ^ status_reg[`CMP];
  1489. end
  1490. 5'b10010 :
  1491. begin
  1492. if(byte_address >= (NUM_PAGES * 2047 / 2048 * PAGESIZE))
  1493. write_protected = 1'b1 ^ status_reg[`CMP];
  1494. else
  1495. write_protected = 1'b0 ^ status_reg[`CMP];
  1496. end
  1497. 5'b10011 :
  1498. begin
  1499. if(byte_address >= (NUM_PAGES * 1023 / 1024 * PAGESIZE))
  1500. write_protected = 1'b1 ^ status_reg[`CMP];
  1501. else
  1502. write_protected = 1'b0 ^ status_reg[`CMP];
  1503. end
  1504. 5'b1010? :
  1505. begin
  1506. if(byte_address >= (NUM_PAGES * 511 / 512 * PAGESIZE))
  1507. write_protected = 1'b1 ^ status_reg[`CMP];
  1508. else
  1509. write_protected = 1'b0 ^ status_reg[`CMP];
  1510. end
  1511. 5'b11001 :
  1512. begin
  1513. if(byte_address < (NUM_PAGES * 1 / 4096 * PAGESIZE))
  1514. write_protected = 1'b1 ^ status_reg[`CMP];
  1515. else
  1516. write_protected = 1'b0 ^ status_reg[`CMP];
  1517. end
  1518. 5'b11010 :
  1519. begin
  1520. if(byte_address < (NUM_PAGES * 1 / 2048 * PAGESIZE))
  1521. write_protected = 1'b1 ^ status_reg[`CMP];
  1522. else
  1523. write_protected = 1'b0 ^ status_reg[`CMP];
  1524. end
  1525. 5'b11011 :
  1526. begin
  1527. if(byte_address < (NUM_PAGES * 1 / 1024 * PAGESIZE))
  1528. write_protected = 1'b1 ^ status_reg[`CMP];
  1529. else
  1530. write_protected = 1'b0 ^ status_reg[`CMP];
  1531. end
  1532. 5'b1110? :
  1533. begin
  1534. if(byte_address < (NUM_PAGES * 1 / 512 * PAGESIZE))
  1535. write_protected = 1'b1 ^ status_reg[`CMP];
  1536. else
  1537. write_protected = 1'b0 ^ status_reg[`CMP];
  1538. end
  1539. 5'b??111 :
  1540. begin
  1541. write_protected = 1'b1 ^ status_reg[`CMP];
  1542. end
  1543. endcase
  1544. end
  1545. end
  1546. endfunction
  1547. /******************************************************************************
  1548. The following function returns whether passed command is valid in QPI mode.
  1549. ******************************************************************************/
  1550. function is_qpi;
  1551. input [7:0] cmd_byte;
  1552. begin
  1553. if(flag_qpi_mode == 1)
  1554. begin
  1555. case (cmd_byte) // check command byte for being valid in QPI mode.
  1556. `CMD_WRITE_ENABLE, `CMD_WRITE_ENABLE_VSR, `CMD_WRITE_DISABLE, `CMD_READ_STATUS,
  1557. `CMD_READ_STATUS2, `CMD_READ_STATUS3, `CMD_WRITE_STATUS, `CMD_WRITE_STATUS2, `CMD_WRITE_STATUS3, `CMD_PAGE_PROGRAM,
  1558. `CMD_INDIVIDUAL_LOCK, `CMD_INDIVIDUAL_UNLOCK, `CMD_READ_BLOCK_LOCK, `CMD_GLOBAL_BLOCK_LOCK, `CMD_GLOBAL_BLOCK_UNLOCK,
  1559. `CMD_SECTOR_ERASE,`CMD_HALF_BLOCK_ERASE, `CMD_BLOCK_ERASE, `CMD_BULK_ERASE, `CMD_BULK_ERASE2,
  1560. `CMD_SUSPEND, `CMD_RESUME, `CMD_DEEP_POWERDOWN, `CMD_SET_READ_PARAM, `CMD_READ_DATA_FAST,
  1561. `CMD_READ_DATA_FAST_WRAP, `CMD_READ_DATA_FAST_QUAD_IO, `CMD_READ_SIGNATURE, `CMD_READ_ID, `CMD_READ_JEDEC_ID,
  1562. `CMD_READ_UNIQUE_ID, `CMD_DISABLE_QPI, `CMD_ENABLE_RESET, `CMD_CHIP_RESET :
  1563. begin
  1564. is_qpi = 1;
  1565. end
  1566. default :
  1567. begin
  1568. is_qpi = 0;
  1569. $display("Invalid Opcode for QPI mode. (%0h)",cmd_byte);
  1570. end
  1571. endcase
  1572. end
  1573. else
  1574. is_qpi = 1;
  1575. end
  1576. endfunction
  1577. /******************************************************************************
  1578. The following function returns the lockbit index based on the passed byte address
  1579. The array is indexed with BLOCK 0 sectors, then last Block sectors,
  1580. then block 1 - 510
  1581. ******************************************************************************/
  1582. function integer lockbit_index;
  1583. input [23:0] byte_address;
  1584. begin
  1585. if((byte_address[23:16] == 0) || (byte_address[23:16] == (NUM_BLOCKS-1)))
  1586. begin
  1587. if(byte_address[23:16] == 0)
  1588. lockbit_index = byte_address[15:0] / SECTORSIZE;
  1589. else
  1590. lockbit_index = (byte_address[15:0] / SECTORSIZE) + 16;
  1591. end
  1592. else
  1593. lockbit_index = byte_address[23:16] - 1 + 32;
  1594. end
  1595. endfunction
  1596. /******************************************************************************
  1597. ******************************************************************************
  1598. ******************************************************************************
  1599. COMMAND PROTOCOL HANDLERS
  1600. The following functions execute the command protocol for the selected function
  1601. before enabling the internal state machine to handle the function
  1602. ******************************************************************************
  1603. ******************************************************************************
  1604. ******************************************************************************/
  1605. /******************************************************************************
  1606. READ/WRITE PAGE PROTOCOL HANDLERS
  1607. ******************************************************************************/
  1608. /******************************************************************************
  1609. The following routine will execute the Read Page command 03h,
  1610. Read Page Fast command 0bh, Read Page Fast Dual 3bh and Read Page Fast Quad 6b.
  1611. and Read Security Registers 48h and SFDP Read 5Ah
  1612. ******************************************************************************/
  1613. task read_page;
  1614. input [1:0] fast_read; // 0 = normal, 2 = dual, 3 = quad
  1615. input [1:0] mem_read; // 0 = main array, 1 = Security Pages, 2 = SFDP
  1616. integer x;
  1617. begin
  1618. if(!status_reg[`WIP])
  1619. begin
  1620. input_byte(byte_address[23:16]);
  1621. input_byte(byte_address[15:8]);
  1622. input_byte(byte_address[7:0]);
  1623. if(fast_read)
  1624. begin
  1625. if(flag_qpi_mode == 1)
  1626. begin
  1627. for(x = 0; x <= read_param_reg[5:4];x = x + 1)
  1628. input_byte(null_reg);
  1629. end
  1630. else
  1631. input_byte(null_reg);
  1632. end
  1633. if(mem_read) // SFDP Read and Security Register Read, input 8 dummy bytes.
  1634. input_byte(null_reg);
  1635. forever
  1636. begin
  1637. if(mem_read == 1) // If we're reading a security sector, process output here.
  1638. begin
  1639. case(byte_address[23:8])
  1640. 16'h10 :
  1641. output_byte(secsi[byte_address[7:0]]);
  1642. 16'h20 :
  1643. output_byte(secsi[byte_address[7:0]+PAGESIZE]);
  1644. 16'h30 :
  1645. output_byte(secsi[byte_address[7:0]]+(2*PAGESIZE));
  1646. default :
  1647. begin
  1648. $display("Invalid Security Page Address (%x)",byte_address);
  1649. $stop;
  1650. end
  1651. endcase
  1652. end
  1653. else if(mem_read == 2) //If we're reading SFDP, process output here.
  1654. begin
  1655. if(byte_address[23:8] == 0)
  1656. output_byte(sfdp[byte_address[7:0]]);
  1657. else
  1658. begin
  1659. $display("Invalid SFDP Page Address (%x)", byte_address);
  1660. $stop;
  1661. end
  1662. end
  1663. else // Main Array Reads
  1664. begin
  1665. byte_address = byte_address & ADDRESS_MASK;
  1666. if(fast_read == 2)
  1667. output_byte_dual(memory[byte_address]);
  1668. else if(fast_read == 3)
  1669. output_byte_quad(memory[byte_address]);
  1670. else
  1671. output_byte(memory[byte_address]);
  1672. end
  1673. // If security register or SFDP, wrap at 256 byte boundry. Only allow to read page.
  1674. if(mem_read)
  1675. byte_address[7:0] = byte_address[7:0] + 1;
  1676. else
  1677. byte_address = byte_address + 1;
  1678. end
  1679. end
  1680. end
  1681. endtask
  1682. /******************************************************************************
  1683. The following routine will execute the Read Page Fast Dual IO command bbh
  1684. ******************************************************************************/
  1685. task read_page_dualio;
  1686. begin
  1687. if(!status_reg[`WIP])
  1688. begin
  1689. input_byte_dual(byte_address[23:16]);
  1690. input_byte_dual(byte_address[15:8]);
  1691. input_byte_dual(byte_address[7:0]);
  1692. input_mode_dual(mode_reg[7:2]); // Ensure that mode_reg is setup on posedge clock 22.
  1693. get_posclk_holdn; // Get dummy last clock.
  1694. forever
  1695. begin
  1696. byte_address = byte_address & ADDRESS_MASK;
  1697. output_byte_dual(memory[byte_address]);
  1698. byte_address = byte_address + 1;
  1699. end
  1700. end
  1701. end
  1702. endtask
  1703. /******************************************************************************
  1704. The following routine will execute the Read Page Fast Quad IO command ebh and e3h and e7h and 0ch
  1705. For the following commands, fast_read == the command being sent.
  1706. `define CMD_READ_DATA_FAST_QUAD_IO 8'heb
  1707. `define CMD_READ_OCTAL_FAST_QUAD_IO 8'he3 A3:0 = 0
  1708. `define CMD_READ_WORD_FAST_QUAD_IO 8'he7 A0 = 0
  1709. ******************************************************************************/
  1710. task read_page_quadio;
  1711. input [7:0] cmd;
  1712. integer x;
  1713. begin
  1714. input_byte_quad(byte_address[23:16]);
  1715. input_byte_quad(byte_address[15:8]);
  1716. input_byte_quad(byte_address[7:0]);
  1717. if(!status_reg[`WIP])
  1718. begin
  1719. case (cmd)
  1720. `CMD_READ_OCTAL_FAST_QUAD_IO :
  1721. begin
  1722. input_byte_quad(mode_reg[7:0]);
  1723. if(byte_address[3:0] != 0)
  1724. begin
  1725. $display("WARNING: Error in Octal Word Read Quad I/O address input. A3-0 are non-zero!");
  1726. $display("WARNING: The actual device still accepts the command, but the output data may be wrong!");
  1727. $display("WARNING: It is OK if this is a Continuous Read Mode Reset (FFh).");
  1728. end
  1729. end
  1730. `CMD_READ_DATA_FAST_QUAD_IO :
  1731. begin
  1732. input_byte_quad(mode_reg[7:0]);
  1733. input_byte_quad(null_reg);
  1734. input_byte_quad(null_reg);
  1735. end
  1736. `CMD_READ_WORD_FAST_QUAD_IO :
  1737. begin
  1738. input_byte_quad(mode_reg[7:0]);
  1739. input_byte_quad(null_reg);
  1740. if(byte_address[0] != 0)
  1741. begin
  1742. $display("WARNING: Error in Word Read Quad I/O address input. A0 is non-zero!");
  1743. $display("WARNING: The actual device still accepts the command, but the output data may be wrong!");
  1744. $display("WARNING: It is OK if this is a Continuous Read Mode Reset (FFh).");
  1745. end
  1746. end
  1747. `CMD_READ_DATA_FAST_WRAP :
  1748. begin
  1749. for(x = 0; x <= read_param_reg[5:4];x = x + 1)
  1750. input_byte_quad(null_reg);
  1751. end
  1752. endcase
  1753. forever
  1754. begin
  1755. byte_address = byte_address & ADDRESS_MASK;
  1756. output_byte_quad(memory[byte_address]);
  1757. if(cmd == `CMD_READ_DATA_FAST_WRAP)
  1758. begin
  1759. case ({read_param_reg[1],read_param_reg[0]})
  1760. 2'b00 :
  1761. byte_address[2:0] = byte_address[2:0] + 1;
  1762. 2'b01 :
  1763. byte_address[3:0] = byte_address[3:0] + 1;
  1764. 2'b10 :
  1765. byte_address[4:0] = byte_address[4:0] + 1;
  1766. 2'b11 :
  1767. byte_address[5:0] = byte_address[5:0] + 1;
  1768. endcase
  1769. end
  1770. else
  1771. if(!wrap_reg[4] && ((cmd == `CMD_READ_WORD_FAST_QUAD_IO) || (cmd == `CMD_READ_DATA_FAST_QUAD_IO))) // wrap only a feature on non-fast read commands.
  1772. begin
  1773. case ({wrap_reg[6],wrap_reg[5]})
  1774. 2'b00 :
  1775. byte_address[2:0] = byte_address[2:0] + 1;
  1776. 2'b01 :
  1777. byte_address[3:0] = byte_address[3:0] + 1;
  1778. 2'b10 :
  1779. byte_address[4:0] = byte_address[4:0] + 1;
  1780. 2'b11 :
  1781. byte_address[5:0] = byte_address[5:0] + 1;
  1782. endcase
  1783. end
  1784. else
  1785. byte_address = byte_address + 1;
  1786. end
  1787. end
  1788. end
  1789. endtask
  1790. /******************************************************************************
  1791. The following routine will execute the Write to Page command 02h.
  1792. ******************************************************************************/
  1793. task write_page;
  1794. input quadio;
  1795. integer x;
  1796. integer address;
  1797. begin
  1798. if(!status_reg[`WIP])
  1799. begin
  1800. input_byte(prog_byte_address[23:16]);
  1801. input_byte(prog_byte_address[15:8]);
  1802. input_byte(prog_byte_address[7:0]);
  1803. if(!write_protected(prog_byte_address))
  1804. fill_page_latch(quadio,prog_byte_address,0);
  1805. end
  1806. end
  1807. endtask
  1808. /******************************************************************************
  1809. The following routine will fill the page_latch with input data in either regular or quad io.
  1810. ******************************************************************************/
  1811. task fill_page_latch;
  1812. input quadio;
  1813. input [31:0] prog_address;
  1814. input flag_secsi;
  1815. integer x;
  1816. integer address;
  1817. begin
  1818. prog_byte_number = 0;
  1819. // Move memory page into page latch
  1820. if(flag_secsi)
  1821. begin
  1822. address = (prog_address >> 4) - 31'h100;
  1823. address[7:0] = 0;
  1824. end
  1825. else
  1826. begin
  1827. address = prog_address;
  1828. address[7:0] = 0;
  1829. end
  1830. for(x = 0; x < PAGESIZE; x=x+1)
  1831. page_latch[x] = flag_secsi ? secsi[address+x] : memory[address+x];
  1832. // Now update page latch with input data and signal a page_program operation
  1833. forever
  1834. begin
  1835. if(quadio)
  1836. input_byte_quad(temp);
  1837. else
  1838. input_byte(temp);
  1839. page_latch[prog_address[7:0]] = temp;
  1840. prog_byte_number = prog_byte_number + 1;
  1841. if(flag_secsi)
  1842. flag_prog_secsi_page = 1;
  1843. else
  1844. flag_prog_page = 1;
  1845. prog_address[7:0] = prog_address[7:0] + 1;
  1846. end
  1847. end
  1848. endtask
  1849. ////////////////////////////////////////////////////////////////////////////////
  1850. // This routine dumps the main memory array to the MEM_FILENAME file.
  1851. //
  1852. task dump_mem;
  1853. integer x;
  1854. integer file;
  1855. begin
  1856. file = $fopen(`MEM_FILENAME);
  1857. $fwrite(file,"/* Contents of Memory Array starting from address 0. This is a standard Verilog readmemh format. */");
  1858. // Erase memory array to FFh state.
  1859. for(x = 0; x < (NUM_PAGES * PAGESIZE); x=x+1)
  1860. begin
  1861. if(x % 16)
  1862. $fwrite(file,"%h ", memory[x]);
  1863. else
  1864. $fwrite(file,"\n%h ", memory[x]);
  1865. end
  1866. $fclose(file);
  1867. end
  1868. endtask
  1869. /******************************************************************************
  1870. ******************************************************************************
  1871. ******************************************************************************
  1872. COMMAND STATE MACHINES
  1873. ******************************************************************************
  1874. ******************************************************************************/
  1875. /******************************************************************************
  1876. The following routine occurs when flag_set_read_param goes high.
  1877. This starts the main process for the set read param process.
  1878. ******************************************************************************/
  1879. always @(posedge flag_set_read_param)
  1880. begin :set_read_param
  1881. @(posedge CSn);
  1882. if(flag_set_read_param == 1)
  1883. begin
  1884. read_param_reg = read_param_reg_shadow;
  1885. end
  1886. flag_set_read_param = 0;
  1887. end
  1888. /******************************************************************************
  1889. The following routine occurs when flag_reset goes high.
  1890. This starts the main process for the reset process.
  1891. ******************************************************************************/
  1892. always @(posedge flag_reset)
  1893. begin :reset
  1894. @(posedge CSn);
  1895. if((flag_reset == 1) && (flag_write_status_reg == 0)) // Execute command, except if within a write status register command.
  1896. begin
  1897. flag_reset_condition = 1;
  1898. #tRES1;
  1899. chip_reset();
  1900. end
  1901. flag_reset = 0;
  1902. end
  1903. /******************************************************************************
  1904. POWER UP/DOWN STATE MACHINES
  1905. ******************************************************************************/
  1906. /******************************************************************************
  1907. The following routine occurs when flag_power_up_exec goes high.
  1908. This starts the main process for the power up process.
  1909. ******************************************************************************/
  1910. always @(posedge flag_power_up_exec)
  1911. begin :power_up
  1912. @(posedge CSn);
  1913. if(flag_power_up_exec == 1)
  1914. begin
  1915. if(flag_power_up_sig_read == 1)
  1916. #tRES2;
  1917. else
  1918. #tRES1;
  1919. flag_power_down = 0;
  1920. flag_power_up_exec = 0;
  1921. flag_power_up_sig_read = 0;
  1922. flag_suspend = 0;
  1923. end
  1924. end
  1925. /******************************************************************************
  1926. The following routine occurs when flag_power_down_exec goes high.
  1927. This starts the main process for the power down process.
  1928. ******************************************************************************/
  1929. always @(posedge flag_power_down)
  1930. begin :power_down
  1931. @(posedge CSn);
  1932. if(flag_power_down == 1)
  1933. begin
  1934. #tDP;
  1935. end
  1936. end
  1937. /******************************************************************************
  1938. ERASE PAGE/BLOCK COMMAND STATE MACHINES
  1939. ******************************************************************************/
  1940. /******************************************************************************
  1941. The following routine occurs when flag_suspend goes high.
  1942. This starts the main erase process for the handling erase suspend.
  1943. ******************************************************************************/
  1944. always @(posedge flag_suspend)
  1945. begin :erase_suspend
  1946. @(posedge CSn); // Wait for CSn to go high
  1947. if(flag_suspend == 1)
  1948. begin
  1949. status_reg[`SUS] = 1;
  1950. wait_reset(tSUS);
  1951. flag_suspend_enabled = 1'b1;
  1952. status_reg[`WIP] = 0;
  1953. status_reg[`WEL] = 0;
  1954. end
  1955. end
  1956. /******************************************************************************
  1957. The following routine occurs when flag_resume goes high.
  1958. This starts the main erase process for the handling erase resume.
  1959. ******************************************************************************/
  1960. always @(posedge flag_resume)
  1961. begin :erase_resume
  1962. @(posedge CSn); // Wait for CSn to go high
  1963. if(flag_resume == 1)
  1964. begin
  1965. status_reg[`SUS] = 0;
  1966. flag_suspend_enabled = 1'b0;
  1967. flag_suspend = 1'b0;
  1968. flag_resume = 1'b0;
  1969. status_reg[`WEL] = 1;
  1970. status_reg[`WIP] = 1;
  1971. end
  1972. end
  1973. /******************************************************************************
  1974. The following routine occurs when flag_erase_sector goes high.
  1975. This starts the main erase process for the defined sector.
  1976. ******************************************************************************/
  1977. always @(posedge flag_erase_sector) // When flag_erase_sector goes high, device becomes active
  1978. // and starts erasing the sector defined by byte_address
  1979. begin :erase_sector
  1980. integer x;
  1981. @(posedge CSn); // Wait for CSn to go high
  1982. if(flag_erase_sector == 1)
  1983. begin
  1984. status_reg[`WIP] = 1;
  1985. wait_reset_suspend(tSE);
  1986. for(x = 0; x < SECTORSIZE; x=x+1)
  1987. memory[(byte_address[23:12] * SECTORSIZE) + x] = 8'hff;
  1988. status_reg[`WIP] = 0;
  1989. status_reg[`WEL] = 0;
  1990. end
  1991. flag_erase_sector = 0;
  1992. end
  1993. /******************************************************************************
  1994. The following routine occurs when flag_erase_secsi_sector goes high.
  1995. This starts the main erase process for the defined secsi sector.
  1996. ******************************************************************************/
  1997. always @(posedge flag_erase_secsi_sector) // When flag_erase_secsi_sector goes high, device becomes active
  1998. // and starts erasing the sector defined by byte_address
  1999. begin :erase_secsi_sector
  2000. integer x;
  2001. @(posedge CSn); // Wait for CSn to go high
  2002. if(flag_erase_secsi_sector == 1)
  2003. begin
  2004. status_reg[`WIP] = 1;
  2005. case(byte_address[23:8])
  2006. 16'h10 :
  2007. begin
  2008. wait_reset_suspend(tSE);
  2009. for(x = 0; x < PAGESIZE; x=x+1)
  2010. secsi[x] = 8'hff;
  2011. end
  2012. 16'h20 :
  2013. begin
  2014. wait_reset_suspend(tSE);
  2015. for(x = 0; x < PAGESIZE; x=x+1)
  2016. secsi[x+PAGESIZE] = 8'hff;
  2017. end
  2018. 16'h30 :
  2019. begin
  2020. wait_reset_suspend(tSE);
  2021. for(x = 0; x < PAGESIZE; x=x+1)
  2022. secsi[x+(PAGESIZE * 2)] = 8'hff;
  2023. end
  2024. default :
  2025. begin
  2026. $display("Invalid Security Page Erase Address (%x)",byte_address);
  2027. $stop;
  2028. end
  2029. endcase
  2030. status_reg[`WIP] = 0;
  2031. status_reg[`WEL] = 0;
  2032. end
  2033. flag_erase_secsi_sector = 0;
  2034. end
  2035. /******************************************************************************
  2036. The following routine occurs when flag_erase_block goes high.
  2037. This starts the main erase process for the defined block.
  2038. ******************************************************************************/
  2039. always @(posedge flag_erase_block) // When flag_erase_block goes high, device becomes active
  2040. // and starts erasing the block defined by byte_address
  2041. begin :erase_block
  2042. integer x;
  2043. @(posedge CSn); // Wait for CSn to go high
  2044. if(flag_erase_block == 1)
  2045. begin
  2046. status_reg[`WIP] = 1;
  2047. wait_reset_suspend(tBE2);
  2048. for(x = 0; x < BLOCKSIZE; x=x+1)
  2049. memory[(byte_address[23:16] * BLOCKSIZE) + x] = 8'hff;
  2050. status_reg[`WIP] = 0;
  2051. status_reg[`WEL] = 0;
  2052. end
  2053. flag_erase_block = 0;
  2054. end
  2055. /******************************************************************************
  2056. The following routine occurs when flag_erase_half_block goes high.
  2057. This starts the main erase process for the defined block.
  2058. ******************************************************************************/
  2059. always @(posedge flag_erase_half_block) // When flag_erase_block goes high, device becomes active
  2060. // and starts erasing the block defined by byte_address
  2061. begin :erase_half_block
  2062. integer x;
  2063. @(posedge CSn); // Wait for CSn to go high
  2064. if(flag_erase_half_block == 1)
  2065. begin
  2066. status_reg[`WIP] = 1;
  2067. wait_reset_suspend(tBE1);
  2068. for(x = 0; x < HALFBLOCKSIZE; x=x+1)
  2069. memory[(byte_address[23:15] * HALFBLOCKSIZE) + x] = 8'hff;
  2070. status_reg[`WIP] = 0;
  2071. status_reg[`WEL] = 0;
  2072. end
  2073. flag_erase_half_block = 0;
  2074. end
  2075. /******************************************************************************
  2076. The following routine occurs when flag_erase_bulk goes high.
  2077. This starts the main erase process for the entire chip.
  2078. ******************************************************************************/
  2079. always @(posedge flag_erase_bulk) // When flag_erase_block goes high, device becomes active
  2080. // and starts erasing the block defined by page_address
  2081. begin :erase_bulk
  2082. integer x;
  2083. @(posedge CSn); // Wait for CSn to go high
  2084. if(flag_erase_bulk == 1)
  2085. begin
  2086. status_reg[`WIP] = 1;
  2087. for(x = 0; x < 40; x=x+1)
  2088. wait_reset(tCE_40);
  2089. for(x = 0; x < PAGESIZE * NUM_PAGES; x=x+1)
  2090. memory[x] = 8'hff;
  2091. status_reg[`WIP] = 0;
  2092. status_reg[`WEL] = 0;
  2093. end
  2094. flag_erase_bulk = 0;
  2095. end
  2096. /******************************************************************************
  2097. PROGRAMMING PAGE COMMAND STATE MACHINES
  2098. ******************************************************************************/
  2099. /******************************************************************************
  2100. The following routine occurs when flag_prog_page goes high.
  2101. This starts the program page process.
  2102. ******************************************************************************/
  2103. always @(posedge flag_prog_page) // When flag_prog_page goes high, device becomes active
  2104. // and starts programming the page defined by page_address
  2105. begin :program_to_page
  2106. reg [31:0] x; // Local loop variable only to be used here.
  2107. @(posedge CSn); // Wait for CSn to go high
  2108. begin
  2109. status_reg[`WIP] = 1;
  2110. if((prog_byte_address[7:0]+prog_byte_number[8:0]) > PAGESIZE)
  2111. begin
  2112. prog_byte_address[7:0] = 0;
  2113. prog_byte_number = 256;
  2114. end
  2115. for(x = prog_byte_address; x < (prog_byte_address+prog_byte_number[8:0]); x=x+1)
  2116. begin
  2117. memory[x] = page_latch[x[7:0]] & memory[x];
  2118. if(x == prog_byte_address)
  2119. wait_reset_suspend(tBP1);
  2120. else
  2121. wait_reset_suspend(tPP / PAGESIZE);
  2122. end
  2123. status_reg[`WIP] = 0;
  2124. status_reg[`WEL] = 0;
  2125. end
  2126. flag_prog_page = 0;
  2127. end
  2128. /******************************************************************************
  2129. The following routine occurs when flag_prog_secsi_page goes high.
  2130. This starts the program secsi page process.
  2131. ******************************************************************************/
  2132. always @(posedge flag_prog_secsi_page) // When flag_prog_page goes high, device becomes active
  2133. // and starts programming the page defined by page_address
  2134. begin :program_to_secsi_page
  2135. integer x; // Local loop variable only to be used here.
  2136. @(posedge CSn); // Wait for CSn to go high
  2137. begin
  2138. status_reg[`WIP] = 1;
  2139. prog_byte_address[7:0] = 0;
  2140. case(prog_byte_address[23:8])
  2141. 16'h10 :
  2142. begin
  2143. for(x = 0; x < PAGESIZE; x=x+1)
  2144. begin
  2145. secsi[x] = page_latch[x] & secsi[x];
  2146. wait_reset_suspend(tPP / PAGESIZE);
  2147. end
  2148. end
  2149. 16'h20 :
  2150. begin
  2151. for(x = 0; x < PAGESIZE; x=x+1)
  2152. begin
  2153. secsi[x+PAGESIZE] = page_latch[x] & secsi[x+PAGESIZE];
  2154. wait_reset_suspend(tPP / PAGESIZE);
  2155. end
  2156. end
  2157. 16'h30 :
  2158. begin
  2159. for(x = 0; x < PAGESIZE; x=x+1)
  2160. begin
  2161. secsi[x+(PAGESIZE*2)] = page_latch[x] & secsi[x+(PAGESIZE*2)];
  2162. wait_reset_suspend(tPP / PAGESIZE);
  2163. end
  2164. end
  2165. default :
  2166. begin
  2167. $display("Invalid Security Page Program Address (%x)",prog_byte_address);
  2168. $stop;
  2169. end
  2170. endcase
  2171. status_reg[`WIP] = 0;
  2172. status_reg[`WEL] = 0;
  2173. end
  2174. flag_prog_secsi_page = 0;
  2175. end
  2176. /******************************************************************************
  2177. CONFIGURATION REGISTER COMMAND STATE MACHINES
  2178. ******************************************************************************/
  2179. /******************************************************************************
  2180. The following routine occurs when flag_write_status_reg goes high.
  2181. This starts the main write status register process.
  2182. ******************************************************************************/
  2183. always @(posedge flag_write_status_reg) // When flag_write_status_reg goes high, device becomes active
  2184. // and starts writing the status_reg_shadow register into the
  2185. begin :write_status_reg
  2186. @(posedge CSn); // Wait for CSn to go high
  2187. if(flag_write_status_reg == 1)
  2188. begin
  2189. status_reg[`WIP] = 1;
  2190. status_reg[`QE] = status_reg_shadow[`QE];
  2191. status_reg[`SRP1] = status_reg_shadow[`SRP1];
  2192. status_reg[`SRP0] = status_reg_shadow[`SRP0];
  2193. status_reg[`BP0] = status_reg_shadow[`BP0];
  2194. status_reg[`BP1] = status_reg_shadow[`BP1];
  2195. status_reg[`BP2] = status_reg_shadow[`BP2];
  2196. status_reg[`TB] = status_reg_shadow[`TB];
  2197. status_reg[`SEC] = status_reg_shadow[`SEC];
  2198. status_reg[`CMP] = status_reg_shadow[`CMP];
  2199. status_reg[`WPS] = status_reg_shadow[`WPS];
  2200. status_reg[`DRV0] = status_reg_shadow[`DRV0];
  2201. status_reg[`DRV1] = status_reg_shadow[`DRV1];
  2202. status_reg[`HLD_RST] = status_reg_shadow[`HLD_RST];
  2203. // One time program OTP bits to 1.
  2204. status_reg[`LB1] = status_reg[`LB1] | status_reg_shadow[`LB1];
  2205. status_reg[`LB2] = status_reg[`LB2] | status_reg_shadow[`LB2];
  2206. status_reg[`LB3] = status_reg[`LB3] | status_reg_shadow[`LB3];
  2207. if(!flag_volatile_sr_write)
  2208. begin
  2209. // Now set OTP bits
  2210. status_reg_otp[`QE] = status_reg_shadow[`QE];
  2211. status_reg_otp[`SRP1] = status_reg_shadow[`SRP1];
  2212. status_reg_otp[`SRP0] = status_reg_shadow[`SRP0];
  2213. status_reg_otp[`BP0] = status_reg_shadow[`BP0];
  2214. status_reg_otp[`BP1] = status_reg_shadow[`BP1];
  2215. status_reg_otp[`BP2] = status_reg_shadow[`BP2];
  2216. status_reg_otp[`TB] = status_reg_shadow[`TB];
  2217. status_reg_otp[`SEC] = status_reg_shadow[`SEC];
  2218. status_reg_otp[`CMP] = status_reg_shadow[`CMP];
  2219. status_reg_otp[`WPS] = status_reg_shadow[`WPS];
  2220. status_reg_otp[`DRV0] = status_reg_shadow[`DRV0];
  2221. status_reg_otp[`DRV1] = status_reg_shadow[`DRV1];
  2222. status_reg_otp[`HLD_RST] = status_reg_shadow[`HLD_RST];
  2223. // One time program OTP bits to 1.
  2224. status_reg_otp[`LB1] = status_reg[`LB1] | status_reg_shadow[`LB1];
  2225. status_reg_otp[`LB2] = status_reg[`LB2] | status_reg_shadow[`LB2];
  2226. status_reg_otp[`LB3] = status_reg[`LB3] | status_reg_shadow[`LB3];
  2227. end
  2228. // If QE bit got reset, make sure QPI mode is disabled.
  2229. if(status_reg[`QE] == 0)
  2230. flag_qpi_mode = 0;
  2231. if(status_reg[`WEL])
  2232. wait_reset(tW);
  2233. status_reg[`WIP] = 0;
  2234. status_reg[`WEL] = 0;
  2235. flag_volatile_sr_write = 0;
  2236. flag_write_status_reg = 0;
  2237. end
  2238. end
  2239. endmodule // W25Q128JV