spiflash.v 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /*
  2. * PicoSoC - A simple example SoC using PicoRV32
  3. *
  4. * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
  5. *
  6. * Permission to use, copy, modify, and/or distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. *
  18. */
  19. `timescale 1 ns / 1 ps
  20. //
  21. // Simple SPI flash simulation model
  22. //
  23. // This model samples io input signals 1ns before the SPI clock edge and
  24. // updates output signals 1ns after the SPI clock edge.
  25. //
  26. // Supported commands:
  27. // AB, B9, FF, 03, BB, EB, ED
  28. //
  29. // Well written SPI flash data sheets:
  30. // Cypress S25FL064L http://www.cypress.com/file/316661/download
  31. // Cypress S25FL128L http://www.cypress.com/file/316171/download
  32. //
  33. // SPI flash used on iCEBreaker board:
  34. // https://www.winbond.com/resource-files/w25q128jv%20dtr%20revb%2011042016.pdf
  35. //
  36. module spiflash (
  37. input csb,
  38. input clk,
  39. inout io0, // MOSI
  40. inout io1, // MISO
  41. inout io2,
  42. inout io3
  43. );
  44. localparam verbose = 1;
  45. localparam integer latency = 8;
  46. reg [7:0] buffer;
  47. integer bitcount = 0;
  48. integer bytecount = 0;
  49. integer dummycount = 0;
  50. reg [7:0] spi_cmd;
  51. reg [7:0] xip_cmd = 0;
  52. reg [23:0] spi_addr;
  53. reg [7:0] spi_in;
  54. reg [7:0] spi_out;
  55. reg spi_io_vld;
  56. reg powered_up = 1;
  57. localparam [3:0] mode_spi = 1;
  58. localparam [3:0] mode_dspi_rd = 2;
  59. localparam [3:0] mode_dspi_wr = 3;
  60. localparam [3:0] mode_qspi_rd = 4;
  61. localparam [3:0] mode_qspi_wr = 5;
  62. localparam [3:0] mode_qspi_ddr_rd = 6;
  63. localparam [3:0] mode_qspi_ddr_wr = 7;
  64. reg [3:0] mode = 0;
  65. reg [3:0] next_mode = 0;
  66. reg io0_oe = 0;
  67. reg io1_oe = 0;
  68. reg io2_oe = 0;
  69. reg io3_oe = 0;
  70. reg io0_dout = 0;
  71. reg io1_dout = 0;
  72. reg io2_dout = 0;
  73. reg io3_dout = 0;
  74. assign #1 io0 = io0_oe ? io0_dout : 1'bz;
  75. assign #1 io1 = io1_oe ? io1_dout : 1'bz;
  76. assign #1 io2 = io2_oe ? io2_dout : 1'bz;
  77. assign #1 io3 = io3_oe ? io3_dout : 1'bz;
  78. wire io0_delayed;
  79. wire io1_delayed;
  80. wire io2_delayed;
  81. wire io3_delayed;
  82. assign #1 io0_delayed = io0;
  83. assign #1 io1_delayed = io1;
  84. assign #1 io2_delayed = io2;
  85. assign #1 io3_delayed = io3;
  86. // 16 MB (128Mb) Flash
  87. reg [7:0] memory [0:16*1024*1024-1];
  88. reg [1023:0] firmware_file;
  89. initial begin
  90. if (!$value$plusargs("firmware=%s", firmware_file))
  91. firmware_file = "firmware.hex";
  92. $readmemh(firmware_file, memory);
  93. end
  94. task spi_action;
  95. begin
  96. spi_in = buffer;
  97. if (bytecount == 1) begin
  98. spi_cmd = buffer;
  99. if (spi_cmd == 8'h ab)
  100. powered_up = 1;
  101. if (spi_cmd == 8'h b9)
  102. powered_up = 0;
  103. if (spi_cmd == 8'h ff)
  104. xip_cmd = 0;
  105. end
  106. if (powered_up && spi_cmd == 'h 03) begin
  107. if (bytecount == 2)
  108. spi_addr[23:16] = buffer;
  109. if (bytecount == 3)
  110. spi_addr[15:8] = buffer;
  111. if (bytecount == 4)
  112. spi_addr[7:0] = buffer;
  113. if (bytecount >= 4) begin
  114. buffer = memory[spi_addr];
  115. spi_addr = spi_addr + 1;
  116. end
  117. end
  118. if (powered_up && spi_cmd == 'h 0b) begin
  119. if (bytecount == 2)
  120. spi_addr[23:16] = buffer;
  121. if (bytecount == 3)
  122. spi_addr[15:8] = buffer;
  123. if (bytecount == 4)
  124. spi_addr[7:0] = buffer;
  125. if (bytecount >= 5) begin
  126. buffer = memory[spi_addr];
  127. spi_addr = spi_addr + 1;
  128. end
  129. end
  130. if (powered_up && spi_cmd == 'h bb) begin
  131. if (bytecount == 1)
  132. mode = mode_dspi_rd;
  133. if (bytecount == 2)
  134. spi_addr[23:16] = buffer;
  135. if (bytecount == 3)
  136. spi_addr[15:8] = buffer;
  137. if (bytecount == 4)
  138. spi_addr[7:0] = buffer;
  139. if (bytecount == 5) begin
  140. xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00;
  141. mode = mode_dspi_wr;
  142. dummycount = latency;
  143. end
  144. if (bytecount >= 5) begin
  145. buffer = memory[spi_addr];
  146. spi_addr = spi_addr + 1;
  147. end
  148. end
  149. if (powered_up && spi_cmd == 'h eb) begin
  150. if (bytecount == 1)
  151. mode = mode_qspi_rd;
  152. if (bytecount == 2)
  153. spi_addr[23:16] = buffer;
  154. if (bytecount == 3)
  155. spi_addr[15:8] = buffer;
  156. if (bytecount == 4)
  157. spi_addr[7:0] = buffer;
  158. if (bytecount == 5) begin
  159. xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00;
  160. mode = mode_qspi_wr;
  161. dummycount = latency;
  162. end
  163. if (bytecount >= 5) begin
  164. buffer = memory[spi_addr];
  165. spi_addr = spi_addr + 1;
  166. end
  167. end
  168. if (powered_up && spi_cmd == 'h ed) begin
  169. if (bytecount == 1)
  170. next_mode = mode_qspi_ddr_rd;
  171. if (bytecount == 2)
  172. spi_addr[23:16] = buffer;
  173. if (bytecount == 3)
  174. spi_addr[15:8] = buffer;
  175. if (bytecount == 4)
  176. spi_addr[7:0] = buffer;
  177. if (bytecount == 5) begin
  178. xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00;
  179. mode = mode_qspi_ddr_wr;
  180. dummycount = latency;
  181. end
  182. if (bytecount >= 5) begin
  183. buffer = memory[spi_addr];
  184. spi_addr = spi_addr + 1;
  185. end
  186. end
  187. spi_out = buffer;
  188. spi_io_vld = 1;
  189. if (verbose) begin
  190. if (bytecount == 1)
  191. $write("<SPI-START>");
  192. $write("<SPI:%02x:%02x>", spi_in, spi_out);
  193. end
  194. end
  195. endtask
  196. task ddr_rd_edge;
  197. begin
  198. buffer = {buffer, io3_delayed, io2_delayed, io1_delayed, io0_delayed};
  199. bitcount = bitcount + 4;
  200. if (bitcount == 8) begin
  201. bitcount = 0;
  202. bytecount = bytecount + 1;
  203. spi_action;
  204. end
  205. end
  206. endtask
  207. task ddr_wr_edge;
  208. begin
  209. io0_oe = 1;
  210. io1_oe = 1;
  211. io2_oe = 1;
  212. io3_oe = 1;
  213. io0_dout = buffer[4];
  214. io1_dout = buffer[5];
  215. io2_dout = buffer[6];
  216. io3_dout = buffer[7];
  217. buffer = {buffer, 4'h 0};
  218. bitcount = bitcount + 4;
  219. if (bitcount == 8) begin
  220. bitcount = 0;
  221. bytecount = bytecount + 1;
  222. spi_action;
  223. end
  224. end
  225. endtask
  226. always @(csb) begin
  227. if (csb) begin
  228. if (verbose) begin
  229. $display("");
  230. $fflush;
  231. end
  232. buffer = 0;
  233. bitcount = 0;
  234. bytecount = 0;
  235. mode = mode_spi;
  236. io0_oe = 0;
  237. io1_oe = 0;
  238. io2_oe = 0;
  239. io3_oe = 0;
  240. end else
  241. if (xip_cmd) begin
  242. buffer = xip_cmd;
  243. bitcount = 0;
  244. bytecount = 1;
  245. spi_action;
  246. end
  247. end
  248. always @(csb, clk) begin
  249. spi_io_vld = 0;
  250. if (!csb && !clk) begin
  251. if (dummycount > 0) begin
  252. io0_oe = 0;
  253. io1_oe = 0;
  254. io2_oe = 0;
  255. io3_oe = 0;
  256. end else
  257. case (mode)
  258. mode_spi: begin
  259. io0_oe = 0;
  260. io1_oe = 1;
  261. io2_oe = 0;
  262. io3_oe = 0;
  263. io1_dout = buffer[7];
  264. end
  265. mode_dspi_rd: begin
  266. io0_oe = 0;
  267. io1_oe = 0;
  268. io2_oe = 0;
  269. io3_oe = 0;
  270. end
  271. mode_dspi_wr: begin
  272. io0_oe = 1;
  273. io1_oe = 1;
  274. io2_oe = 0;
  275. io3_oe = 0;
  276. io0_dout = buffer[6];
  277. io1_dout = buffer[7];
  278. end
  279. mode_qspi_rd: begin
  280. io0_oe = 0;
  281. io1_oe = 0;
  282. io2_oe = 0;
  283. io3_oe = 0;
  284. end
  285. mode_qspi_wr: begin
  286. io0_oe = 1;
  287. io1_oe = 1;
  288. io2_oe = 1;
  289. io3_oe = 1;
  290. io0_dout = buffer[4];
  291. io1_dout = buffer[5];
  292. io2_dout = buffer[6];
  293. io3_dout = buffer[7];
  294. end
  295. mode_qspi_ddr_rd: begin
  296. ddr_rd_edge;
  297. end
  298. mode_qspi_ddr_wr: begin
  299. ddr_wr_edge;
  300. end
  301. endcase
  302. if (next_mode) begin
  303. case (next_mode)
  304. mode_qspi_ddr_rd: begin
  305. io0_oe = 0;
  306. io1_oe = 0;
  307. io2_oe = 0;
  308. io3_oe = 0;
  309. end
  310. mode_qspi_ddr_wr: begin
  311. io0_oe = 1;
  312. io1_oe = 1;
  313. io2_oe = 1;
  314. io3_oe = 1;
  315. io0_dout = buffer[4];
  316. io1_dout = buffer[5];
  317. io2_dout = buffer[6];
  318. io3_dout = buffer[7];
  319. end
  320. endcase
  321. mode = next_mode;
  322. next_mode = 0;
  323. end
  324. end
  325. end
  326. always @(posedge clk) begin
  327. if (!csb) begin
  328. if (dummycount > 0) begin
  329. dummycount = dummycount - 1;
  330. end else
  331. case (mode)
  332. mode_spi: begin
  333. buffer = {buffer, io0};
  334. bitcount = bitcount + 1;
  335. if (bitcount == 8) begin
  336. bitcount = 0;
  337. bytecount = bytecount + 1;
  338. spi_action;
  339. end
  340. end
  341. mode_dspi_rd, mode_dspi_wr: begin
  342. buffer = {buffer, io1, io0};
  343. bitcount = bitcount + 2;
  344. if (bitcount == 8) begin
  345. bitcount = 0;
  346. bytecount = bytecount + 1;
  347. spi_action;
  348. end
  349. end
  350. mode_qspi_rd, mode_qspi_wr: begin
  351. buffer = {buffer, io3, io2, io1, io0};
  352. bitcount = bitcount + 4;
  353. if (bitcount == 8) begin
  354. bitcount = 0;
  355. bytecount = bytecount + 1;
  356. spi_action;
  357. end
  358. end
  359. mode_qspi_ddr_rd: begin
  360. ddr_rd_edge;
  361. end
  362. mode_qspi_ddr_wr: begin
  363. ddr_wr_edge;
  364. end
  365. endcase
  366. end
  367. end
  368. endmodule