https://blackmesalabs.wordpress.com/2016/10/24/sump2-96-msps-logic-analyzer-for-22/
[BML_sump2] / sump2 / source / spi_prom.v
1 /* ****************************************************************************\r
2 -- Source file: spi_prom.v           \r
3 -- Date:        June 2014\r
4 -- Author:      khubbard\r
5 -- Description: A generic LocalBus hardware interface to a SPI PROM that \r
6 --              provides for a reusable software interface for configuring \r
7 --              current and future SPI PROMs. Uses a single BRAM.\r
8 -- Language:    Verilog-2001 and VHDL-1993\r
9 -- Simulation:  Mentor-Modelsim \r
10 -- Synthesis:   Xilinst-XST \r
11 -- License:     This project is licensed with the CERN Open Hardware Licence\r
12 --              v1.2.  You may redistribute and modify this project under the\r
13 --              terms of the CERN OHL v.1.2. (http://ohwr.org/cernohl).\r
14 --              This project is distributed WITHOUT ANY EXPRESS OR IMPLIED\r
15 --              WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY\r
16 --              AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN OHL\r
17 --              v.1.2 for applicable Conditions.\r
18 --\r
19 --                                --------------\r
20 --           reset           --->|  spi_prom.v  |\r
21 --           clk_lb          --->|              |\r
22 --           ck_divisor[7:0] --->|              |\r
23 --                               |              |\r
24 --           lb_cs_prom_c ------>|              |\r
25 --           lb_cs_prom_d ------>|              |\r
26 --           lb_wr ------------->|              |\r
27 --           lb_rd ------------->|              |---> lb_rd_rdy\r
28 --           lb_wr_d[31:0] ----->|              |---> lb_rd_d[31:0]\r
29 --                               |              |\r
30 --                               |              |---> spi_sck\r
31 --                               |              |---> spi_cs_l\r
32 --           spi_miso ---------->|              |---> spi_mosi\r
33 --                               |              |\r
34 --                               |              |---> reconfig_req\r
35 --                               |              |---> reconfig_addr[31:0]\r
36 --                                --------------\r
37 --\r
38 --  [ Control Register Write ]\r
39 --    D(7:0)                     D(27:8)\r
40 --      0x0 CMD_IDLE              NA         : NOP\r
41 --      0x1 CMD_QUERY_ID          NA         : Read PROM ID\r
42 --      0x2 CMD_RD_TIMESTAMP      NA         : Read FPGA UNIX Timestamp\r
43 --      0x3 CMD_RD_PROM           ADDR(27:8) : Read 256 Bytes from ADDR\r
44 --      0x4 CMD_UNLOCK            0x0AA5AA   : Unlock for Erase and Write Ops\r
45 --                                0x055A55   : Unlock for Reconfig Operation\r
46 --      0x5 CMD_ERASE_BULK        NA         : Erase entire PROM ( Slow )\r
47 --      0x6 CMD_ERASE_SECTOR      ADDR(27:8) : Erase Sector at ADDR\r
48 --      0x7 CMD_WR_PROM           ADDR(27:8) : Write 256 Bytes to ADDR\r
49 --      0x8 CMD_RECONFIG_FPGA     ADDR(27:8) : Reconfig FPGA from ADDR\r
50 --      0x9 CMD_RELEASE_POWERDOWN NA         : Release from Deep Power Down\r
51 --\r
52 --  [ Control Register Read ]\r
53 --    D(27:8) spi_addr[27:8]\r
54 --    D(7)    err_ram_wr_jk         : MOSI RAM Overwrite Error\r
55 --    D(6)    stat_polling_reqd_jk  : Polling is Required\r
56 --    D(5)    stat_mosi_buf_free    : MOSI buffer is available.\r
57 --    D(4)    stat_miso_buf_rdy_jk  : MISO buffer has data to be read.\r
58 --    D(3)    stat_fsm_wr           : Interface in "Write" state.\r
59 --    D(2)    stat_unlocked_jk      : PROM is unlocked for Writing and Erasing\r
60 --    D(1)    flag_wip              : PROM is Writing or Erasing\r
61 --    D(0)    stat_spi_busy         : SPI interface is in use\r
62 --\r
63 --\r
64 --  [ Data Register Read/Write ]\r
65 --    Up to 64 DWORD Burst Region for Writes and Reads\r
66 --\r
67 -- Resources Required in Spartan3A XC3S200A device:\r
68 --   Number of RAMB16BWEs:                   1 out of      16    6%\r
69 --  prom_is_32b = 1\r
70 --   Number of Slice Flip Flops:           410 out of   3,584   11%\r
71 --   Number of 4 input LUTs:               485 out of   3,584   13%\r
72 --  prom_is_32b = 0\r
73 --   Number of Slice Flip Flops:           410 out of   3,584   11%\r
74 --   Number of 4 input LUTs:               410 out of   3,584   11%\r
75 --\r
76 --\r
77 --  Note: ck_divisor[7:0] is number of clk_lb cycles per HALF spi_sck period.\r
78 --        Example clk_lb = 80 MHz, ck_divisor=10, spi_sck will be 4 MHz.\r
79 --\r
80 --  Note: Regarding 4-Byte Addressing. The 256Mb Micron datasheet is confusing.\r
81 --        There are special 4-Byte commands, but they only exist for certain\r
82 --        mask revs of their 256Mb parts ( N25Q256A83 ). All of the other\r
83 --        N25Q256A revs require the "Enter 4-Byte" command which then extends\r
84 --        the regular 3-Byte commands to 4-Bytes. This module issues the \r
85 --        "Enter 4-Byte" at the beginning of ANY PROM command and then issues \r
86 --        "Exit 4-Byte" after the command is done.\r
87 --\r
88 -- PROM Spec:\r
89 --   Page   = 256 Bytes\r
90 --   Sector = 256 pages ( 64 KB )\r
91 --   Sector Erase = ~500ms\r
92 --   Page Program = ~1ms\r
93 -- Measured Program Times:\r
94 --   256 0xFFs = 330 us\r
95 --   256 0x00s = 800 us\r
96 --    64 0x00s = 200 us\r
97 --    32 0x00s = 100 us\r
98 --     8 0x00s =   0 us\r
99 --\r
100 -- Revision History:\r
101 -- Ver#  When      Who      What\r
102 -- ----  --------  -------- ---------------------------------------------------\r
103 -- 0.1   06.01.14  khubbard Creation\r
104 -- 0.2   07.08.14  khubbard Added 4-byte addressing support\r
105 -- 0.3   08.18.14  khubbard Added root protection for Slot-0 BootLoader\r
106 -- ***************************************************************************/\r
107 `default_nettype none // Strictly enforce all nets to be declared\r
108   \r
109 module spi_prom #\r
110 (\r
111    parameter depth_len  = 128,\r
112    parameter depth_bits = 7\r
113 // parameter depth_len  = 8,\r
114 // parameter depth_bits = 3\r
115 )\r
116 (\r
117   input  wire         reset,\r
118   input  wire         prom_is_32b,\r
119   input  wire [31:0]  slot_size,\r
120   input  wire         protect_1st_slot,\r
121   input  wire         clk_lb,\r
122   input  wire [7:0]   ck_divisor,\r
123   input  wire [3:0]   spi_ctrl,\r
124 \r
125   input  wire         lb_cs_prom_c,\r
126   input  wire         lb_cs_prom_d,\r
127   input  wire         lb_wr,\r
128   input  wire         lb_rd,\r
129   input  wire [31:0]  lb_wr_d,\r
130   output reg  [31:0]  lb_rd_d,\r
131   output reg          lb_rd_rdy,\r
132   output reg          flag_wip,\r
133   input  wire         reconfig_2nd_slot,\r
134   output reg          reconfig_req,\r
135   output reg  [31:0]  reconfig_addr,\r
136   output reg          bist_req,\r
137 \r
138   output wire         spi_sck,\r
139   output wire         spi_cs_l,\r
140   output wire         spi_mosi,\r
141   input  wire         spi_miso\r
142 );// module spi_prom \r
143 \r
144   wire [31:0]             all_zeros;\r
145   wire [31:0]             all_ones;\r
146 \r
147   reg                     flag_wip_loc;\r
148   reg                     xfer_start;\r
149   reg                     xfer_start_p1;\r
150   reg                     xfer_mosi_jk;\r
151   reg  [11:0]             xfer_tx_bytes;\r
152   reg  [11:0]             xfer_rx_bytes;\r
153 \r
154   reg  [3:0]              mosi_fsm;\r
155   reg  [11:0]             spi_byte_cnt;\r
156   reg  [7:0]              mosi_byte_d;\r
157   reg                     mosi_byte_pre;\r
158   reg                     mosi_byte_en;\r
159   wire                    mosi_byte_req;\r
160   reg                     mosi_byte_req_p1;\r
161   reg                     mosi_buf_rdy_jk;\r
162   reg  [1:0]              mosi_byte_cnt;\r
163 \r
164   wire [7:0]              miso_byte_d;\r
165   wire                    miso_byte_rdy;\r
166   reg  [1:0]              miso_byte_cnt;\r
167   reg                     err_ram_wr;\r
168   reg                     err_ram_wr_jk;\r
169   reg                     bist_req_jk;\r
170   reg                     req_timestamp;\r
171   reg                     req_timestamp_p1;\r
172   reg                     req_timestamp_p2;\r
173 \r
174   wire                    spi_is_idle;\r
175   reg                     spi_is_idle_p1;\r
176   reg                     spi_is_idle_jk;\r
177   wire [11:0]             page_size;\r
178   reg  [31:0]             spi_addr;\r
179   reg                     spi_addr_page_inc;\r
180   reg                     spi_addr_page_inc_p1;\r
181   reg                     cmd_en;\r
182   reg                     cmd_en_p1;\r
183   reg  [3:0]              cmd_nib;\r
184   reg  [7:0]              cmd_byte;\r
185 \r
186   reg  [31:0]             ram_array[depth_len-1:0];\r
187   reg  [depth_bits-1:0]   a_addr;\r
188   reg  [depth_bits-1:0]   a_addr_p1;\r
189   reg  [depth_bits-1:0]   b_addr;\r
190   reg                     a_we;\r
191   reg                     a_we_p1;\r
192   reg  [31:0]             a_di;\r
193   reg  [31:0]             a_di_p1;\r
194   reg                     a_we_miso;\r
195   reg  [31:0]             a_di_miso;\r
196   reg  [31:0]             a_do;\r
197   reg  [31:0]             b_do;\r
198   reg  [31:0]             b_do_p1;\r
199 \r
200   reg  [31:0]             prom_ctrl_reg;\r
201   reg  [31:0]             prom_data_reg;\r
202   wire [31:0]             time_stamp_d;\r
203   reg  [7:0]              post_rst_cnt;\r
204 \r
205   reg                     strb_clear_fsm;\r
206   reg                     strb_wr_data;\r
207   reg                     miso_rd_inc;\r
208   reg                     mosi_rd_inc;\r
209   reg                     wr_ping_pong;\r
210   reg                     rd_ping_pong_pend;\r
211   reg  [1:0]              rd_ping_pong_actv;\r
212   reg                     buffer_free_jk;\r
213   reg                     prom_wr_locked_jk;\r
214   reg                     prom_wr_locked_jk_p1;\r
215   reg                     fpga_boot_locked_jk;\r
216   reg                     fpga_root_locked_jk;\r
217   reg                     stat_spi_busy;\r
218   reg                     stat_polling_reqd_jk;\r
219   reg                     stat_mosi_buf_free;\r
220   reg                     stat_miso_buf_rdy_jk;\r
221   reg                     stat_fsm_wr;\r
222   reg                     stat_unlocked_jk;\r
223   reg                     we_reqd_jk;\r
224   reg                     rd_reqd_jk;\r
225   reg                     addr_reqd_jk;\r
226   reg                     done_enter_4byte;\r
227   reg                     in_reset;\r
228   reg                     in_reset_p1;\r
229 \r
230   `define CMD_IDLE              4'h0\r
231   `define CMD_QUERY_ID          4'h1\r
232   `define CMD_RD_TIMESTAMP      4'h2\r
233   `define CMD_RD_PROM           4'h3\r
234   `define CMD_UNLOCK            4'h4\r
235   `define CMD_ERASE_BULK        4'h5\r
236   `define CMD_ERASE_SECTOR      4'h6\r
237   `define CMD_WR_PROM           4'h7\r
238   `define CMD_RECONFIG_FPGA     4'h8\r
239   `define CMD_RELEASE_POWERDOWN 4'h9\r
240   `define CMD_REL_PD            4'h9\r
241 \r
242   assign all_zeros = 32'h00000000;\r
243   assign all_ones  = 32'hFFFFFFFF;\r
244 \r
245   assign page_size = ( 2*depth_len );// Number of Bytes in a Page ( 1/2 RAM )\r
246 \r
247 //assign sump_events[15:12] = mosi_fsm[3:0];\r
248 //assign sump_events[11:8]  = cmd_nib[3:0];\r
249 //assign sump_events[7]     = err_ram_wr_jk;\r
250 //assign sump_events[6]     = stat_polling_reqd_jk;\r
251 //assign sump_events[5]     = stat_miso_buf_rdy_jk;\r
252 //assign sump_events[4]     = stat_mosi_buf_free;\r
253 //assign sump_events[3]     = stat_fsm_wr;\r
254 //assign sump_events[2]     = stat_unlocked_jk;\r
255 //assign sump_events[1]     = flag_wip_loc;\r
256 //assign sump_events[0]     = stat_spi_busy;\r
257 \r
258 //assign slot_size = 32'h00020000; // 1 Mbit slots for XC3S200A\r
259 \r
260 //-----------------------------------------------------------------------------\r
261 // PROM_CTRL_REG : \r
262 // Write :\r
263 //  D(27:8) : Address(27:8) for Write or Read\r
264 //  D(7:0)  : Control Nibble:\r
265 //\r
266 // Read :\r
267 //     D(7)  : 1 = MOSI Buffer Overrun Error\r
268 //     D(6)  : 1 = MOSI Polling Required      ( Read D(4) before Writing )\r
269 //     D(5)  : 1 = MOSI Buffer Free           ( OK to Write 256 Bytes ) \r
270 //     D(4)  : 1 = MISO Buffer Read Ready     ( OK to Read 256 Bytes )\r
271 //\r
272 //     D(3)  : 1 = Write Bursting State      \r
273 //     D(2)  : 1 = Unlocked for Writing\r
274 //     D(1)  : 1 = PROM Write In Progress     ( WIP )\r
275 //     D(0)  : 1 = SPI is Busy \r
276 //\r
277 // PROM_DATA_REG : \r
278 //    D(31:0) : Write or Read Data ( 64 DWORDs at a time for Write and Read )\r
279 //-----------------------------------------------------------------------------\r
280 always @ ( posedge clk_lb ) begin : proc_lb_regs\r
281  begin\r
282    bist_req         <= bist_req_jk;\r
283    strb_clear_fsm   <= 0;\r
284    strb_wr_data     <= 0;\r
285    cmd_en           <= 0;\r
286    cmd_en_p1        <= cmd_en;\r
287    reconfig_req     <= 0;\r
288    req_timestamp    <= 0;\r
289    req_timestamp_p1 <= req_timestamp;\r
290    req_timestamp_p2 <= req_timestamp_p1;\r
291    in_reset         <= 0;\r
292    in_reset_p1      <= in_reset;\r
293   \r
294    stat_unlocked_jk     <= ~ prom_wr_locked_jk;\r
295    prom_wr_locked_jk_p1 <= prom_wr_locked_jk;\r
296 \r
297    if ( spi_addr_page_inc == 1 ) begin\r
298      spi_addr <= spi_addr[31:0] + page_size[11:0];\r
299    end\r
300 \r
301    // Process new Control Nibble when written\r
302    if ( lb_wr == 1 && lb_cs_prom_c == 1 ) begin \r
303      prom_ctrl_reg  <= lb_wr_d[31:0];\r
304      cmd_nib        <= lb_wr_d[3:0];\r
305      cmd_en         <= 1;\r
306      strb_clear_fsm <= 1;\r
307      spi_addr[27:0]  <= { lb_wr_d[27:8], 8'd0 };\r
308      spi_addr[31:28] <= 4'd0;\r
309 \r
310      if ( lb_wr_d[3:0] == `CMD_RD_TIMESTAMP ) begin\r
311        req_timestamp <= 1;\r
312        cmd_en        <= 0;\r
313      end \r
314 \r
315      if ( lb_wr_d[3:0] == `CMD_RECONFIG_FPGA ) begin\r
316        cmd_en        <= 0;\r
317        if ( fpga_boot_locked_jk == 0 ) begin\r
318          reconfig_req         <= 1;\r
319          reconfig_addr[27:0]  <= { lb_wr_d[27:8], 8'd0 };\r
320          reconfig_addr[31:28] <= 4'd0;\r
321        end\r
322      end \r
323 \r
324      // Handle the Lock. Lock on idle or bad unlock code\r
325      if ( lb_wr_d[3:0] == 4'h0 ) begin\r
326        prom_wr_locked_jk <= 1;\r
327        cmd_en            <= 0;\r
328      end\r
329 \r
330      if ( lb_wr_d[3:0] == `CMD_UNLOCK  ) begin\r
331        fpga_boot_locked_jk <= 1;\r
332        prom_wr_locked_jk   <= 1;\r
333        bist_req_jk         <= 0;\r
334        cmd_en              <= 0;\r
335        if ( lb_wr_d[27:8] == 20'haa5aa ) begin\r
336          prom_wr_locked_jk <= 0;\r
337        end\r
338        if ( lb_wr_d[27:8] == 20'h55a55 ) begin\r
339          fpga_boot_locked_jk <= 0;\r
340        end\r
341        if ( lb_wr_d[27:8] == 20'h5aaa5 ) begin\r
342          fpga_root_locked_jk <= 0;// Note: This is sticky\r
343        end\r
344        if ( lb_wr_d[27:8] == 20'h11111 ) begin\r
345          bist_req_jk         <= 1;\r
346        end\r
347      end \r
348 \r
349    end // if ( lb_wr == 1 && lb_cs_prom_c == 1 ) begin \r
350 \r
351    // Load BRAM for MOSI\r
352    if ( lb_wr == 1 && lb_cs_prom_d == 1 ) begin \r
353      prom_data_reg <= lb_wr_d[31:0];\r
354      strb_wr_data  <= 1;\r
355    end // if ( lb_wr == 1 && lb_cs_prom_d == 1 ) begin \r
356  \r
357    // Leaving Reset, if reconfig_2nd_slot==1, request a reconfig at slot_size \r
358    if          ( post_rst_cnt == 8'hF0 ) begin\r
359      if ( reconfig_2nd_slot == 1 ) begin\r
360        reconfig_req         <= 1;\r
361        reconfig_addr[27:0]  <= { slot_size[27:8], 8'd0 };\r
362        reconfig_addr[31:28] <= 4'd0;\r
363      end\r
364      post_rst_cnt <= post_rst_cnt + 1;\r
365    end else if ( post_rst_cnt == 8'hFF ) begin\r
366    end else begin\r
367      post_rst_cnt <= post_rst_cnt + 1;\r
368    end \r
369   \r
370    if ( reset == 1 ) begin\r
371      post_rst_cnt        <= 8'd0;\r
372      in_reset            <= 1;\r
373      in_reset_p1         <= 1;\r
374      prom_ctrl_reg       <= 32'd0;\r
375      prom_data_reg       <= 32'd0;\r
376      prom_wr_locked_jk   <= 1;\r
377      fpga_boot_locked_jk <= 1; // Prevents Reconfig\r
378      fpga_root_locked_jk <= 1; // Prevents Erasing Slot-0\r
379      reconfig_req        <= 0;\r
380      bist_req_jk         <= 0; // Request Built In Self Test mode\r
381      bist_req            <= 0; \r
382    end // if ( reset == 1 ) begin\r
383 \r
384  end\r
385 end // proc_lb_regs\r
386 \r
387 \r
388 //-----------------------------------------------------------------------------\r
389 // LocalBus Readback\r
390 //-----------------------------------------------------------------------------\r
391 always @ ( posedge clk_lb ) begin : proc_lb_rd\r
392  begin\r
393    lb_rd_d        <= 32'd0;\r
394    lb_rd_rdy      <= 0;\r
395    miso_rd_inc    <= 0;\r
396 \r
397    // Read Control Reg   \r
398    if ( lb_rd == 1 && lb_cs_prom_c == 1 ) begin \r
399      lb_rd_d[27:8] <= spi_addr[27:8];\r
400      lb_rd_d[7]    <= err_ram_wr_jk;\r
401      lb_rd_d[6]    <= stat_polling_reqd_jk;\r
402      lb_rd_d[5]    <= stat_mosi_buf_free;\r
403      lb_rd_d[4]    <= stat_miso_buf_rdy_jk;\r
404      lb_rd_d[3]    <= stat_fsm_wr;\r
405      lb_rd_d[2]    <= stat_unlocked_jk;\r
406      lb_rd_d[1]    <= flag_wip_loc;\r
407      lb_rd_d[0]    <= stat_spi_busy;\r
408      lb_rd_rdy     <= 1;\r
409    end // if ( lb_rd == 1 && lb_cs_prom_c == 1 ) begin \r
410 \r
411    // Read BRAM for MISO\r
412    if ( lb_rd == 1 && lb_cs_prom_d == 1 ) begin \r
413      lb_rd_d     <= b_do_p1[31:0];\r
414      lb_rd_rdy   <= 1;\r
415      miso_rd_inc <= 1;\r
416    end // if ( lb_wr == 1 && lb_cs_prom_d == 1 ) begin \r
417 \r
418  end\r
419 end // proc_lb_rd\r
420 \r
421 \r
422 //-----------------------------------------------------------------------------\r
423 // Convert Generic Command Nibbles into Device Specific Command Bytes and Leng\r
424 //-----------------------------------------------------------------------------\r
425 always @ ( posedge clk_lb ) begin : proc_cmd_lut \r
426  begin\r
427   // Latch as cmd_nib returns to 0x0 immediately\r
428     \r
429     // Translate User Nibble Commands to Device Specific Byte Commands\r
430     case( cmd_nib[3:0] )\r
431       `CMD_WR_PROM      : cmd_byte <= 8'h02;// Micron Page_Program\r
432       `CMD_RD_PROM      : cmd_byte <= 8'h03;// Micron Read_Data\r
433       `CMD_QUERY_ID     : cmd_byte <= 8'h9F;// Micron Read_ID\r
434       `CMD_REL_PD       : cmd_byte <= 8'hAB;// Micron Release from PowerDown\r
435       `CMD_ERASE_SECTOR : cmd_byte <= 8'hd8;// Micron Sector_Erase \r
436       `CMD_ERASE_BULK   : cmd_byte <= 8'hc7;// Micron Bulk_Erase   \r
437       default           : cmd_byte <= 8'h00;// NULL\r
438     endcase // case( cmd_nib[3:0] )\r
439 \r
440     // Is a WriteEnable required before User Command ?\r
441     case( cmd_nib[3:0] )\r
442       `CMD_WR_PROM      : we_reqd_jk <= 1;  // Page_Program\r
443       `CMD_RD_PROM      : we_reqd_jk <= 0;  // Read_Data\r
444       `CMD_QUERY_ID     : we_reqd_jk <= 0;  // Read_ID\r
445       `CMD_REL_PD       : we_reqd_jk <= 0;  // Release PowerDown\r
446       `CMD_ERASE_SECTOR : we_reqd_jk <= 1;  // Sector_Erase \r
447       `CMD_ERASE_BULK   : we_reqd_jk <= 1;  // Bulk_Erase   \r
448       default           : we_reqd_jk <= 0;  // NULL\r
449     endcase // case( cmd_nib[3:0] )\r
450 \r
451     // Will there be an address state ?\r
452     case( cmd_nib[3:0] )\r
453       `CMD_WR_PROM      : addr_reqd_jk <= 1;  // Page_Program\r
454       `CMD_RD_PROM      : addr_reqd_jk <= 1;  // Read_Data\r
455       `CMD_QUERY_ID     : addr_reqd_jk <= 0;  // Read_ID\r
456       `CMD_REL_PD       : addr_reqd_jk <= 0;  // Release PowerDown\r
457       `CMD_ERASE_SECTOR : addr_reqd_jk <= 1;  // Sector_Erase \r
458       `CMD_ERASE_BULK   : addr_reqd_jk <= 0;  // Bulk_Erase   \r
459       default           : addr_reqd_jk <= 0;  // NULL\r
460     endcase // case( cmd_nib[3:0] )\r
461 \r
462     // Will there be MISO data to capture ?\r
463     case( cmd_nib[3:0] )\r
464       `CMD_WR_PROM      : rd_reqd_jk <= 0;  // Page_Program\r
465       `CMD_RD_PROM      : rd_reqd_jk <= 1;  // Read_Data\r
466       `CMD_QUERY_ID     : rd_reqd_jk <= 1;  // Read_ID\r
467       `CMD_REL_PD       : rd_reqd_jk <= 0;  // Release Power Down\r
468       `CMD_ERASE_SECTOR : rd_reqd_jk <= 0;  // Sector_Erase \r
469       `CMD_ERASE_BULK   : rd_reqd_jk <= 0;  // Bulk_Erase   \r
470       default           : rd_reqd_jk <= 0;  // NULL\r
471     endcase // case( cmd_nib[3:0] )\r
472 \r
473 \r
474   // UserCommand : Decide How Many MOSI and MISO Bytes to Xfer\r
475   if ( mosi_fsm[3:0] == 4'h2 ) begin\r
476    if ( prom_is_32b == 0 ) begin\r
477     case( cmd_nib[3:0] )\r
478       `CMD_WR_PROM      : xfer_tx_bytes <= 12'd4 + page_size[11:0];\r
479       `CMD_RD_PROM      : xfer_tx_bytes <= 12'd4;\r
480       `CMD_QUERY_ID     : xfer_tx_bytes <= 12'd1;\r
481       `CMD_REL_PD       : xfer_tx_bytes <= 12'd1;\r
482       `CMD_ERASE_SECTOR : xfer_tx_bytes <= 12'd4;\r
483       `CMD_ERASE_BULK   : xfer_tx_bytes <= 12'd1;\r
484       default           : xfer_tx_bytes <= 12'd0;          \r
485     endcase // case( cmd_nib[3:0] )\r
486    end else begin\r
487     case( cmd_nib[3:0] )\r
488       `CMD_WR_PROM      : xfer_tx_bytes <= 12'd5 + page_size[11:0];\r
489       `CMD_RD_PROM      : xfer_tx_bytes <= 12'd5;\r
490       `CMD_QUERY_ID     : xfer_tx_bytes <= 12'd1;\r
491       `CMD_REL_PD       : xfer_tx_bytes <= 12'd1;\r
492       `CMD_ERASE_SECTOR : xfer_tx_bytes <= 12'd5;\r
493       `CMD_ERASE_BULK   : xfer_tx_bytes <= 12'd1;\r
494       default           : xfer_tx_bytes <= 12'd0;          \r
495     endcase // case( cmd_nib[3:0] )\r
496    end\r
497     case( cmd_nib[3:0] )\r
498       `CMD_WR_PROM      : xfer_rx_bytes <= 12'd0;\r
499       `CMD_RD_PROM      : xfer_rx_bytes <= page_size[11:0];\r
500       `CMD_QUERY_ID     : xfer_rx_bytes <= 12'd4;\r
501       `CMD_REL_PD       : xfer_rx_bytes <= 12'd0;\r
502       `CMD_ERASE_SECTOR : xfer_rx_bytes <= 12'd0;\r
503       `CMD_ERASE_BULK   : xfer_rx_bytes <= 12'd0;\r
504       default           : xfer_rx_bytes <= 12'd0;\r
505     endcase // case( cmd_nib[3:0] )\r
506   end\r
507 \r
508   // ReadStatus WIP Poll   \r
509   if ( mosi_fsm[3:0] == 4'h8 ) begin\r
510     xfer_tx_bytes <= 12'd1;\r
511     xfer_rx_bytes <= 12'd1;\r
512   end\r
513 \r
514   // Single Byte Commands \r
515   if ( mosi_fsm[3:0] == 4'h1 ||\r
516        mosi_fsm[3:0] == 4'h9 ||\r
517        mosi_fsm[3:0] == 4'ha ||\r
518        mosi_fsm[3:0] == 4'hb ||\r
519        mosi_fsm[3:0] == 4'hc   ) begin\r
520     xfer_tx_bytes <= 12'd1;\r
521     xfer_rx_bytes <= 12'd0;\r
522   end\r
523 \r
524  end\r
525 end // proc_cmd_lut\r
526 \r
527 \r
528 //-----------------------------------------------------------------------------\r
529 // Decide when SPI is idle or not\r
530 //-----------------------------------------------------------------------------\r
531 always @ ( posedge clk_lb ) begin : proc_spi_idle   \r
532  begin\r
533   spi_is_idle_p1    <= spi_is_idle;\r
534   if ( xfer_start == 1 ) begin\r
535     spi_is_idle_jk <= 0;\r
536   end else if ( spi_is_idle == 1 && spi_is_idle_p1 == 0 ) begin\r
537     spi_is_idle_jk <= 1;\r
538   end\r
539   if ( reset == 1 ||\r
540        mosi_fsm == 4'hF ) begin \r
541     spi_is_idle_jk    <= 1;\r
542   end\r
543   if ( mosi_fsm[3:0] == 4'h0 ) begin\r
544     stat_spi_busy <= 0;\r
545   end else begin\r
546     stat_spi_busy <= 1;\r
547   end \r
548  end\r
549 end // proc_spi_idle\r
550 \r
551 \r
552 //-----------------------------------------------------------------------------\r
553 // When cmd_nib[3:0] goes non-zero start a SPI command and continue until\r
554 // the xfer count is tx+rx count.\r
555 //\r
556 // mosi_fsm[3:0]\r
557 //   0x0 : idle\r
558 //   0x1 : WriteEnable\r
559 //   0x2 : Command Byte\r
560 //   0x3 : spi_addr[31:24] ( Skipped for 3-Byte )\r
561 //   0x4 : spi_addr[23:16] \r
562 //   0x5 : spi_addr[15:8] \r
563 //   0x6 : spi_addr[7:0] \r
564 //   0x7 : Data Stage\r
565 //   0x8 : ReadStatus\r
566 //   0x9 : Write-Enable for Enter 4-Byte Addr\r
567 //   0xA : Enter 4-Byte Addr\r
568 //   0xB : Write-Enable for Exit 4-Byte Addr\r
569 //   0xC : Exit 4-Byte Addr\r
570 //-----------------------------------------------------------------------------\r
571 always @ ( posedge clk_lb ) begin : proc_spi_len_fsm\r
572  begin\r
573   mosi_byte_en      <= mosi_byte_pre;\r
574   mosi_byte_req_p1  <= mosi_byte_req;\r
575   xfer_start        <= 0;\r
576   xfer_start_p1     <= xfer_start;\r
577   spi_addr_page_inc <= 0;\r
578   flag_wip_loc      <= 0;\r
579   flag_wip          <= flag_wip_loc;\r
580   stat_fsm_wr       <= 0;\r
581   done_enter_4byte  <= 0;\r
582 \r
583   if ( cmd_nib == `CMD_WR_PROM ) begin\r
584     stat_fsm_wr <= 1;\r
585   end\r
586 \r
587   // Either Kickoff new SPI Xfer, or advance the Xfer in progress \r
588   // If 32b PROM, Enable 4-Byte Mode 1st\r
589 //if ( mosi_fsm == 4'h0 && spi_is_idle_jk == 1 ) begin \r
590   if ( ( mosi_fsm == 4'h0 && spi_is_idle_jk == 1 ) ||    \r
591        ( prom_is_32b == 1 && done_enter_4byte == 1 )   ) begin\r
592     if (\r
593          ( cmd_en_p1 == 1  || done_enter_4byte == 1 ) &&\r
594            cmd_nib != `CMD_IDLE         &&\r
595            cmd_nib != `CMD_RD_TIMESTAMP &&\r
596            cmd_nib != `CMD_WR_PROM      &&\r
597            cmd_nib != `CMD_UNLOCK       &&    \r
598            cmd_nib != `CMD_RECONFIG_FPGA              ) begin\r
599       xfer_start        <= 1;\r
600       if ( we_reqd_jk == 1 ) begin\r
601         mosi_fsm <= 4'h1;// Start with WriteEnable \r
602       end else begin\r
603         mosi_fsm <= 4'h2;// Read can skip the WriteEnable\r
604       end\r
605       if ( prom_is_32b == 1 && done_enter_4byte == 0 ) begin\r
606         xfer_start <= 1;\r
607         mosi_fsm   <= 4'h9;// Enter 4-Byte Mode and defer cmd_nib\r
608       end\r
609     end\r
610 \r
611     // If Write Command, start when RAM buffer is full, not when cmd is issued\r
612     if ( \r
613          ( mosi_buf_rdy_jk == 1 || done_enter_4byte == 1 ) && \r
614            cmd_nib == `CMD_WR_PROM                            ) begin\r
615       // Only actually write if no overrun error has happened\r
616       if ( err_ram_wr_jk == 0 ) begin\r
617         xfer_start <= 1;\r
618         mosi_fsm   <= 4'h1;// Start with WriteEnable \r
619       end\r
620       if ( prom_is_32b == 1 && done_enter_4byte == 0 ) begin\r
621         xfer_start <= 1;\r
622         mosi_fsm   <= 4'h9;// Enter 4-Byte Mode and defer cmd_nib\r
623       end\r
624     end \r
625   end \r
626 \r
627   if ( prom_is_32b == 1 ) begin \r
628     if ( spi_is_idle == 1 && spi_is_idle_p1 == 0 ) begin\r
629       // Finished Write Enable for Entering 4-Byte Addr  \r
630       if ( mosi_fsm == 4'h9 ) begin\r
631         xfer_start <= 1;\r
632         mosi_fsm   <= 4'ha;\r
633       end \r
634       // Finished Entering 4-Byte Addr, time for actual command\r
635       if ( mosi_fsm == 4'ha ) begin\r
636 //      mosi_fsm         <= 4'h0;// Done\r
637         done_enter_4byte <= 1;\r
638       end \r
639       // Finished Write Enable for Exiting 4-Byte Addr  \r
640       if ( mosi_fsm == 4'hb ) begin\r
641         xfer_start <= 1;\r
642         mosi_fsm   <= 4'hc;\r
643       end \r
644       // Finished Exit 4-Byte Addr\r
645       if ( mosi_fsm == 4'hc ) begin\r
646         mosi_fsm   <= 4'h0;\r
647       end \r
648     end // if ( spi_is_idle == 1 && spi_is_idle_p1 == 0 ) begin\r
649   end // if ( prom_is_32b == 1 ) begin \r
650 \r
651   if ( xfer_start == 1 ) begin\r
652     spi_byte_cnt <= 12'd0;\r
653     xfer_mosi_jk <= 1;\r
654   end \r
655 \r
656   // Finished Write Enable for Erase or Programming\r
657   if ( mosi_fsm == 4'h1 ) begin\r
658     if ( spi_is_idle == 1 && spi_is_idle_p1 == 0 ) begin\r
659       xfer_start <= 1;\r
660       mosi_fsm   <= 4'h2;// Start Command Byte\r
661     end\r
662   end\r
663 \r
664   // Full Command,Addr     \r
665   if ( mosi_fsm == 4'h2 ||\r
666        mosi_fsm == 4'h3 ||\r
667        mosi_fsm == 4'h4 ||\r
668        mosi_fsm == 4'h5 ||\r
669        mosi_fsm == 4'h6 \r
670      ) begin\r
671     if ( mosi_byte_pre == 1 ) begin\r
672       if ( mosi_fsm == 4'h2 ) begin\r
673         if ( prom_is_32b == 0 ) begin\r
674           mosi_fsm <= 4'h4;// Skip 0x3 for 3-Byte Addressing\r
675         end else begin\r
676           mosi_fsm <= 4'h3;// 0x3 is for 4-Byte Addressing\r
677         end\r
678       end else begin\r
679         mosi_fsm <= mosi_fsm[3:0] + 1;\r
680       end\r
681       if ( mosi_fsm == 4'h2 && addr_reqd_jk == 0 ) begin\r
682         mosi_fsm <= 4'h7;// Skip Address Entirely\r
683       end\r
684     end\r
685   end\r
686 \r
687   // Data Burst   \r
688   if ( mosi_fsm == 4'h7 ) begin\r
689     if ( spi_is_idle == 1 && spi_is_idle_p1 == 0 ) begin\r
690       if ( we_reqd_jk == 1 ) begin\r
691         xfer_start        <= 1;\r
692         mosi_fsm          <= 4'h8;// Poll WIP \r
693         spi_addr_page_inc <= 1;\r
694       end else begin\r
695         if ( prom_is_32b == 1 ) begin \r
696           xfer_start <= 1;\r
697           mosi_fsm   <= 4'hb;// WriteEnable then Exit 4-Byte\r
698         end else begin\r
699           mosi_fsm   <= 4'h0;// Done \r
700         end\r
701       end\r
702     end\r
703   end\r
704 \r
705   // Poll WIP\r
706   if ( mosi_fsm == 4'h8 ) begin\r
707     flag_wip_loc <= 1;\r
708     if ( miso_byte_rdy == 1 ) begin\r
709       if ( miso_byte_d[0] == 0 ) begin\r
710         if ( prom_is_32b == 1 ) begin \r
711           xfer_start <= 1;\r
712           mosi_fsm   <= 4'hb;// WriteEnable then Exit 4-Byte\r
713         end else begin\r
714           mosi_fsm   <= 4'h0;// Done \r
715         end\r
716       end else begin\r
717         xfer_start   <= 1;\r
718         mosi_fsm     <= 4'h8;// Poll WIP \r
719       end\r
720     end\r
721   end\r
722 \r
723   // If we just xferred a SPI TX or RX Byte count it\r
724   if ( ( xfer_mosi_jk == 1 && mosi_byte_pre == 1 ) ||   \r
725        ( xfer_mosi_jk == 0 && miso_byte_rdy == 1 )    )begin\r
726     spi_byte_cnt <= spi_byte_cnt + 1;\r
727   end\r
728 \r
729   // Once all MOSI Bytes are transferred, switch to MISO Bytes\r
730   if ( mosi_byte_en == 1 && spi_byte_cnt == xfer_tx_bytes ) begin\r
731     xfer_mosi_jk <= 0;\r
732   end\r
733 \r
734   if ( reset == 1 ) begin\r
735     mosi_fsm <= 4'h0;\r
736   end\r
737  \r
738  end\r
739 end // proc_spi_len_fsm\r
740 \r
741 \r
742 //-----------------------------------------------------------------------------\r
743 // MOSI Mux. Mux in a MOSI Byte based on FSM stage ( Cmd,Addr,Data)\r
744 //\r
745 //      cmd_byte[7:0]->|\\r
746 //   spi_addr[31:0]--->| |---> mosi_byte_d[7:0]\r
747 //      ram_d[31:0]--->|/\r
748 //                      |\r
749 //        mosi_fsm[3:0]-\r
750 //-----------------------------------------------------------------------------\r
751 always @ ( posedge clk_lb ) begin : proc_mosi_mux\r
752  begin\r
753   mosi_byte_pre <= 0;\r
754   mosi_rd_inc   <= 0;\r
755   // When SPI wants a new MOSI byte, Mux Byte into SPI path based on FSM state\r
756   if ( mosi_byte_req == 1 && mosi_byte_req_p1 == 0 ) begin\r
757     mosi_byte_pre <= 1;\r
758     if ( mosi_fsm[3:0] != 4'h7 ) begin\r
759       case( mosi_fsm[3:0] )\r
760         4'h1    : mosi_byte_d <= 8'h06;// Micron WriteEnable\r
761         4'h2    : mosi_byte_d <= cmd_byte[7:0];\r
762         4'h3    : mosi_byte_d <= spi_addr[31:24]; \r
763         4'h4    : mosi_byte_d <= spi_addr[23:16]; \r
764         4'h5    : mosi_byte_d <= spi_addr[15:8]; \r
765         4'h6    : mosi_byte_d <= spi_addr[7:0]; \r
766         4'h8    : mosi_byte_d <= 8'h05;// Micron ReadStatus\r
767         4'h9    : mosi_byte_d <= 8'h06;// Micron WriteEnable\r
768         4'ha    : mosi_byte_d <= 8'hb7;// Micron Enter 4-Byte Addr Mode\r
769         4'hb    : mosi_byte_d <= 8'h06;// Micron WriteEnable\r
770         4'hc    : mosi_byte_d <= 8'he9;// Micron Exit  4-Byte Addr Mode\r
771         default : mosi_byte_d <= 8'h00;// NULL\r
772       endcase // case( mosi_fsm[3:0] )\r
773       mosi_byte_cnt <= 2'd0;\r
774 \r
775       // Prevent WriteEnable from happening if things are locked by issuing\r
776       // a Micron ReadStatus command instead of the WriteEnable command\r
777       if ( mosi_fsm[3:0] == 4'h1 ) begin\r
778 \r
779         // If PROM is locked, issue ReadStatus instead of WriteEnable\r
780         if ( prom_wr_locked_jk_p1 == 1 ) begin\r
781           mosi_byte_d <= 8'h05;// Micron ReadStatus\r
782         end\r
783 \r
784         // Protect BootLoader design at Slot-0 \r
785         // If protect_1st_slot==1 and fpga_root_locked_jk==1 check to see if\r
786         // spi_addr < slot_size and issue ReadStatus instead of WriteEnable\r
787         if ( protect_1st_slot == 1 && fpga_root_locked_jk == 1 &&\r
788              spi_addr[31:0] < slot_size[31:0]                     ) begin\r
789           mosi_byte_d <= 8'h05;// Micron ReadStatus\r
790         end\r
791 \r
792       end // if ( mosi_fsm[3:0] == 4'h1 ) begin\r
793 \r
794     end else begin\r
795       case( mosi_byte_cnt[1:0] )\r
796         2'h0    : mosi_byte_d <= b_do_p1[31:24];\r
797         2'h1    : mosi_byte_d <= b_do_p1[23:16];\r
798         2'h2    : mosi_byte_d <= b_do_p1[15:8];\r
799         default : mosi_byte_d <= b_do_p1[7:0];\r
800       endcase // case( mosi_byte_cnt[1:0] )\r
801 \r
802       mosi_byte_cnt <= mosi_byte_cnt + 1;\r
803       if ( mosi_byte_cnt[1:0] == 2'd3 ) begin\r
804         mosi_rd_inc <= 1;// Finished last Byte, Get next DWORD from BRAM\r
805       end\r
806     end\r
807   end // if ( mosi_byte_req == 1 && mosi_byte_req_p1 == 0 ) begin\r
808 \r
809  end\r
810 end // proc_mosi_mux\r
811 \r
812 \r
813 //-----------------------------------------------------------------------------\r
814 // MISO State Machine. Take MISO data and push to BRAM. \r
815 // Depending on the command either 1 byte or series of 4 bytes\r
816 //-----------------------------------------------------------------------------\r
817 always @ ( posedge clk_lb ) begin : proc_miso_fsm\r
818  begin\r
819    a_we_miso <= 0;\r
820    if ( miso_byte_rdy == 1 ) begin\r
821      // Count MISO Bytes for storing DWORDs to BRAM\r
822      miso_byte_cnt <= miso_byte_cnt[1:0] + 1;\r
823      if ( xfer_rx_bytes == 12'd1 ) begin \r
824        a_we_miso <= 1;\r
825        a_di_miso <= { 24'd0, miso_byte_d[7:0] };\r
826      end else begin\r
827        a_di_miso <= { miso_byte_d[7:0], a_di_miso[31:8] };\r
828        if ( miso_byte_cnt == 2'd3 ) begin\r
829          a_we_miso <= 1; // Write DWORD after shifting 4 bytes\r
830        end\r
831      end \r
832    end // if ( miso_byte_rdy == 1 ) begin\r
833 \r
834    // At end of Read Command, assert MISO Buffer Ready JK\r
835    if ( cmd_nib == `CMD_RD_PROM ) begin\r
836      if ( spi_is_idle == 1 && spi_is_idle_p1 == 0 ) begin\r
837        stat_miso_buf_rdy_jk <= 1;\r
838      end\r
839    end\r
840 \r
841    if ( strb_clear_fsm == 1 ) begin\r
842      miso_byte_cnt        <= 2'd0;\r
843      stat_miso_buf_rdy_jk <= 0;\r
844    end\r
845  end\r
846 end // proc_miso_fsm\r
847 \r
848 \r
849 //-----------------------------------------------------------------------------\r
850 // BRAM Write Access.\r
851 // This is a ping-pong buffer so that Backdoor or PCIe can fill 256 bytes \r
852 // while previous 256 bytes are transferred over SPI. \r
853 // A FIFO would work too, but this is more portable using inferred BRAM.\r
854 // As soon as there are 256 Bytes, a SPI xfer begins.\r
855 // The next 256 bytes can be loaded while the 1st are shipped out.\r
856 // If a new buffer is written while previous buffer is being read, a flag is\r
857 // set to tell software it should poll for free buffer status after each 256\r
858 // byte burst. Another flag indicates if the buffer was overrun.\r
859 //\r
860 // Good:\r
861 // (BD)   |- 6ms -|------ 32 ms -----|\r
862 //  LB   -<  Ping  >-----------------< Pong >----------------------\r
863 //  SPI  ----------<  Ping  >---------------< Pong >---------------\r
864 //  WIP             |--3ms--|<  Ping >-------------< Pong >--------\r
865 //                           |-800us-|\r
866 // Bad:\r
867 // (BD)   \r
868 //  LB   -<Ping>--<Pong>--<Ping>---------------\r
869 //  SPI  ----------<  Ping  >< Pong >---------------\r
870 //  WIP                     < Ping >-< Pong >--------\r
871 //  PollReqd _______/\r
872 //  ErrRAMwr _____________/\r
873 //-----------------------------------------------------------------------------\r
874 always @ ( posedge clk_lb ) begin : proc_ram_wr_fsm\r
875  begin\r
876   stat_mosi_buf_free <= buffer_free_jk;\r
877   a_we               <= 0;\r
878 \r
879   if ( strb_wr_data == 1 && mosi_buf_rdy_jk == 0 ) begin\r
880     a_we                   <= 1;\r
881     a_di                   <= prom_data_reg[31:0];\r
882     a_addr[depth_bits-2:0] <= a_addr[depth_bits-2:0] + 1;\r
883     a_addr[depth_bits-1]   <= wr_ping_pong;\r
884     if ( a_addr[depth_bits-2:0] == { all_ones[depth_bits-2:1], 1'b0 } ) begin\r
885       buffer_free_jk    <= 1; // Whole new Buffer available\r
886       mosi_buf_rdy_jk   <= 1; // Need to dump this buffer to SPI\r
887       wr_ping_pong      <= ~ wr_ping_pong;\r
888       rd_ping_pong_pend <=   wr_ping_pong;\r
889     end else begin\r
890       buffer_free_jk  <= 0; // Filling buffer, can't start a new 256 burst\r
891     end\r
892   end // if ( strb_wr_data == 1 ) begin\r
893 \r
894   // Check to see if writing to buffer while one is being read.\r
895   if ( strb_wr_data == 1 && rd_ping_pong_actv[1] == 1 ) begin\r
896     if ( wr_ping_pong == rd_ping_pong_actv[0] ) begin\r
897       err_ram_wr_jk        <= 1;\r
898     end else begin\r
899       stat_polling_reqd_jk <= 1;\r
900     end\r
901   end\r
902 \r
903   // Determine if this buffer has been claimed by SPI controller\r
904   if ( xfer_start == 1 && mosi_fsm == 4'h1 ) begin\r
905     if ( mosi_buf_rdy_jk == 1 ) begin \r
906       rd_ping_pong_actv <= { 1'b1, rd_ping_pong_pend };\r
907       mosi_buf_rdy_jk   <= 0;\r
908     end\r
909   end else if ( mosi_fsm == 4'h0 ) begin\r
910     rd_ping_pong_actv[1] <= 0;\r
911   end\r
912 \r
913   if ( reset == 1 || strb_clear_fsm == 1 ) begin\r
914     wr_ping_pong           <= 0;\r
915     rd_ping_pong_pend      <= 0;\r
916     rd_ping_pong_actv      <= 2'b01;\r
917     buffer_free_jk         <= 1;\r
918     mosi_buf_rdy_jk        <= 0;\r
919     a_addr[depth_bits-2:0] <= all_ones[depth_bits-2:0];// Roll from Ones to Zero\r
920     a_addr[depth_bits-1]   <= 0;\r
921     err_ram_wr_jk          <= 0;\r
922     stat_polling_reqd_jk   <= 0;\r
923   end\r
924 \r
925   // Normally BRAM writes are from LB, but If MISO has a byte, write it to BRAM\r
926   if ( a_we_miso == 1 && rd_reqd_jk == 1 ) begin\r
927     a_we                   <= 1;\r
928     a_di                   <= a_di_miso[31:0];\r
929     a_addr[depth_bits-2:0] <= a_addr[depth_bits-2:0] + 1;\r
930     a_addr[depth_bits-1]   <= 1;\r
931   end\r
932 \r
933   // Normally BRAM writes are from LB, but load 32bit UNIX timetstamp on reqst\r
934   if ( req_timestamp_p1 == 1 ) begin\r
935     a_we                   <= 1;\r
936     a_di                   <= time_stamp_d[31:0];\r
937     a_addr[depth_bits-2:0] <= a_addr[depth_bits-2:0] + 1;\r
938     a_addr[depth_bits-1]   <= 1;\r
939   end\r
940   // After the TimeStamp, provide the slot size\r
941   if ( req_timestamp_p2 == 1 ) begin\r
942     a_we                   <= 1;\r
943     a_di                   <= slot_size[31:0];\r
944     a_addr[depth_bits-2:0] <= a_addr[depth_bits-2:0] + 1;\r
945     a_addr[depth_bits-1]   <= 1;\r
946   end\r
947 \r
948  end\r
949 end // proc_ram_wr_fsm\r
950 \r
951 \r
952 //-----------------------------------------------------------------------------\r
953 // BRAM Read Port FSM : b_addr starts at 0x0 at beginning of a SPI command and\r
954 // increments after a dword has been read.\r
955 //-----------------------------------------------------------------------------\r
956 always @ ( posedge clk_lb ) begin : proc_ram_rd_fsm\r
957  begin\r
958   b_addr[depth_bits-2:0] <= b_addr[depth_bits-2:0];\r
959   b_addr[depth_bits-1]   <= rd_ping_pong_actv[0];\r
960   if ( strb_clear_fsm == 1 ) begin\r
961     b_addr[depth_bits-2:0] <= all_zeros[depth_bits-2:0];\r
962     b_addr[depth_bits-1]   <= rd_ping_pong_actv[0];\r
963   end\r
964   if ( miso_rd_inc == 1 || mosi_rd_inc == 1 ) begin\r
965     b_addr[depth_bits-2:0] <= b_addr[depth_bits-2:0] + 1;\r
966     b_addr[depth_bits-1]   <= rd_ping_pong_actv[0];\r
967   end\r
968  end\r
969 end // proc_ram_rd_fsm\r
970 \r
971 \r
972 //-----------------------------------------------------------------------------\r
973 // Dual Port RAM - Infer RAM here to make easy to change depth on the fly\r
974 // Really small RAM is used for simulations\r
975 //-----------------------------------------------------------------------------\r
976 always @( posedge clk_lb )\r
977 begin\r
978   a_we_p1   <= a_we;\r
979   a_addr_p1 <= a_addr[depth_bits-1:0];\r
980   a_di_p1   <= a_di[31:0];\r
981   if ( a_we_p1 ) begin\r
982     ram_array[a_addr_p1] <= a_di_p1[31:0];\r
983   end // if ( a_we )\r
984 end // always\r
985 \r
986 always @( posedge clk_lb )\r
987 begin\r
988   a_do <= ram_array[a_addr];\r
989 end // always\r
990 \r
991 always @( posedge clk_lb )\r
992 begin\r
993   b_do <= ram_array[b_addr];\r
994   b_do_p1 <= b_do[31:0];\r
995 end // always\r
996 \r
997 \r
998 //-----------------------------------------------------------------------------\r
999 // 32bit UNIX TimeStamp of when the design was synthesized\r
1000 //-----------------------------------------------------------------------------\r
1001 time_stamp u_time_stamp\r
1002 (\r
1003   .time_dout                        ( time_stamp_d                   )\r
1004 );\r
1005 \r
1006 \r
1007 //-----------------------------------------------------------------------------\r
1008 // Convert MOSI Bytes into SPI Bits and SPI Bits into MISO Bytes\r
1009 //-----------------------------------------------------------------------------\r
1010 spi_byte2bit u_spi_byte2bit\r
1011 (\r
1012   .reset                           ( reset                          ),\r
1013   .clk                             ( clk_lb                         ),\r
1014   .ck_divisor                      ( ck_divisor[7:0]                ),\r
1015   .spi_ctrl                        ( spi_ctrl[3:0]                  ),\r
1016 \r
1017   .spi_sck                         ( spi_sck                        ),\r
1018   .spi_cs_l                        ( spi_cs_l                       ),\r
1019   .spi_mosi                        ( spi_mosi                       ),\r
1020   .spi_miso                        ( spi_miso                       ),\r
1021   .spi_is_idle                     ( spi_is_idle                    ),\r
1022 \r
1023   .xfer_start                      ( xfer_start_p1                  ),\r
1024   .xfer_stall                      ( 1'b0                           ),\r
1025   .xfer_tx_bytes                   ( xfer_tx_bytes[11:0]            ),\r
1026   .xfer_rx_bytes                   ( xfer_rx_bytes[11:0]            ),\r
1027 \r
1028   .mosi_byte_d                     ( mosi_byte_d[7:0]               ),\r
1029   .mosi_byte_en                    ( mosi_byte_en                   ),\r
1030   .mosi_byte_req                   ( mosi_byte_req                  ),\r
1031   .mosi_err                        (                                ),\r
1032 \r
1033   .miso_byte_d                     ( miso_byte_d[7:0]               ),\r
1034   .miso_byte_rdy                   ( miso_byte_rdy                  )\r
1035 );\r
1036 \r
1037 \r
1038 endmodule // spi_prom.v\r