https://blackmesalabs.wordpress.com/2016/10/24/sump2-96-msps-logic-analyzer-for-22/
[BML_sump2] / sump2 / source / sump2.v
1 /* ****************************************************************************\r
2 -- (C) Copyright 2016 Kevin M. Hubbard - All rights reserved.\r
3 -- Source file: sump2.v\r
4 -- Date:        July 2016\r
5 -- Author:      khubbard\r
6 -- Description: SUMP2 is a fast and simple logic analyzer.\r
7 --              It captures N/2 samples before and after a specified trigger\r
8 --              event where N is length of BRAM specified when instantiated. \r
9 --              It is designed to scale easily from small and simple to wide \r
10 --              and deep block RAM primiting. \r
11 -- Language:    Verilog-2001\r
12 -- Simulation:  Mentor-Modelsim\r
13 -- Synthesis:   Xilinst-XST, Lattice-Synplify\r
14 -- License:     This project is licensed with the CERN Open Hardware Licence \r
15 --              v1.2.  You may redistribute and modify this project under the \r
16 --              terms of the CERN OHL v.1.2. (http://ohwr.org/cernohl). \r
17 --              This project is distributed WITHOUT ANY EXPRESS OR IMPLIED \r
18 --              WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY \r
19 --              AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN OHL\r
20 --              v.1.2 for applicable Conditions.\r
21 --\r
22 -- Design Instance Parameters with examples:\r
23 --   depth_len      =  1024 : Depth of RAM in number of cell, example 1024,4096\r
24 --   depth_bits     =  10   : Number of RAM address lines,    example 10,12\r
25 --   event_bytes    =  4    : Number of event bytes 1,2,3 or 4\r
26 --   data_dwords    =  16   : Number of DWORDs for Data 0,4,8,12 or 16\r
27 --\r
28 --   nonrle_en      =  1 : If 0, removes Event RAM (for small RLE only designs)\r
29 --   rle_en         =  1 : Adds logic for Event RLE captures.\r
30 --   pattern_en     =  1 : Adds logic for 32bit event pattern triggers\r
31 --   trigger_nth_en =  1 : Adds logic for triggering on Nth trigger event\r
32 --   trigger_dly_en =  1 : Adds logic for triggering after a delay from trigger\r
33 --\r
34 --   freq_mhz       =  16'd80   : Freq integer 0 MHz up to 65 GHz ( 16bit )\r
35 --   freq_fracts    =  16'h0000 : Freq fraction bits, example C000 = 0.75 MHz\r
36 --   sump_id        =  16'hABBA : Don't Change\r
37 --   sump_rev       =   8'h01   : Don't Change\r
38 --\r
39 -- LocalBus 2 DWORD Register Interface\r
40 --   lb_cs_ctrl : PCI addr sel for Control \r
41 --   lb_cs_data : PCI addr sel for Data transfers. +0x4 offset from lb_cs_ctrl\r
42 --\r
43 -- Software Interface\r
44 -- 5bit Control Commands:\r
45 --   0x00 : Idle + Read Status\r
46 --   0x01 : ARM  + Read Status\r
47 --   0x02 : Reset\r
48 --              \r
49 --   0x04 : Load Trigger Type  ( AND,OR,Ext )\r
50 --   0x05 : Load Trigger Field ( AND/OR bits )\r
51 --   0x06 : Load Trigger Delay & nth        \r
52 --   0x07 : Load Trigger Position ( Num Post Trigger Samples to capture ).\r
53 --\r
54 --   0x08 : Load RLE Event Enable\r
55 --   0x09 : Load Read Pointer\r
56 --   0x0a : Load Read Page\r
57 --              \r
58 --   0x0b : Read HW ID + Revision\r
59 --   0x0c : Read HW Config RAM Width+Length\r
60 --   0x0d : Read HW Config Sample Clock Frequency\r
61 --   0x0e : Read Trigger Location\r
62 --   0x0f : Read RAM Data ( address auto incrementing )\r
63 --\r
64 --   0x10 : Load User Controls\r
65 --   0x11 : Load User Pattern0\r
66 --   0x12 : Load User Pattern1\r
67 --   0x13 : Load Data Enable Field\r
68 --\r
69 -- Trigger Types:\r
70 --   AND Rising            = 0x00;\r
71 --   AND Falling           = 0x01;\r
72 --   OR  Rising            = 0x02;\r
73 --   OR  Falling           = 0x03;\r
74 --   Pattern Rising        = 0x04;\r
75 --   Pattern Falling       = 0x05;\r
76 --   Input Trigger Rising  = 0x06;\r
77 --   Input Trigger Falling = 0x07;\r
78 --\r
79 -- Revision History:\r
80 -- Ver#  When      Who      What\r
81 -- ----  --------  -------- --------------------------------------------------\r
82 -- 0.1   07.01.16  khubbard Creation\r
83 -- ***************************************************************************/\r
84 `default_nettype none // Strictly enforce all nets to be declared\r
85 \r
86 \r
87 module sump2 #\r
88 (\r
89    parameter depth_len      =  1024,\r
90    parameter depth_bits     =  10,\r
91    parameter event_bytes    =  4,\r
92    parameter data_dwords    =  16,\r
93 \r
94    parameter nonrle_en      =  1,\r
95    parameter rle_en         =  1,\r
96    parameter pattern_en     =  1,\r
97    parameter trigger_nth_en =  1,\r
98    parameter trigger_dly_en =  1,\r
99    parameter trigger_wd_en  =  1,\r
100 \r
101    parameter freq_mhz       =  16'd80,\r
102    parameter freq_fracts    =  16'h0000,\r
103    parameter sump_id        =  16'hABBA,\r
104    parameter sump_rev       =   8'h01\r
105 )\r
106 (\r
107   input  wire         reset,\r
108   input  wire         clk_cap,\r
109   input  wire         clk_lb,\r
110   input  wire         lb_cs_ctrl,\r
111   input  wire         lb_cs_data,\r
112   input  wire         lb_wr,\r
113   input  wire         lb_rd,\r
114   input  wire [31:0]  lb_wr_d,\r
115   output reg  [31:0]  lb_rd_d,\r
116   output reg          lb_rd_rdy,\r
117   output reg          active,\r
118 \r
119   output wire [31:0]  user_ctrl,\r
120   output wire [31:0]  user_pat0,\r
121   output wire [31:0]  user_pat1,\r
122 \r
123   input  wire         trigger_in,\r
124   output reg          trigger_out,\r
125 \r
126   input  wire [31:0]  events_din,\r
127 \r
128   input  wire [127:0] dwords_3_0,\r
129   input  wire [127:0] dwords_7_4,\r
130   input  wire [127:0] dwords_11_8,\r
131   input  wire [127:0] dwords_15_12,\r
132   output reg  [3:0]   led_bus\r
133 );\r
134 \r
135 \r
136   wire                    reset_loc;\r
137   wire [15:0]             zeros;\r
138   wire [15:0]             ones;\r
139   wire [7:0]              cap_status;\r
140   wire [4:0]              ctrl_cmd;\r
141   reg  [4:0]              ctrl_cmd_loc;\r
142   reg                     ctrl_cmd_xfer;\r
143   wire [4:0]              ctrl_rd_page;\r
144   wire [15:0]             ctrl_rd_ptr;\r
145   wire                    ctrl_trigger_edge;\r
146   wire [4:0]              ctrl_trigger;\r
147   reg  [4:0]              ctrl_trigger_p1;\r
148   reg  [4:0]              ctrl_reg;\r
149   reg  [31:0]             events_loc;\r
150   reg                     trigger_loc;\r
151   reg                     trigger_or;\r
152   reg                     trigger_or_p1;\r
153   reg                     trigger_and;\r
154   reg                     trigger_and_p1;\r
155   reg                     trigger_pat;\r
156   reg                     trigger_pat_p1;\r
157   reg                     xfer_clr;\r
158   reg                     rd_inc;\r
159   reg                     armed_jk;\r
160   reg                     triggered_jk;\r
161   reg                     acquired_jk;\r
162   reg                     complete_jk;\r
163 \r
164   reg  [31:0]             ctrl_04_reg;\r
165   reg  [31:0]             ctrl_05_reg;\r
166   reg  [31:0]             ctrl_06_reg;\r
167   reg  [31:0]             ctrl_07_reg;\r
168   reg  [31:0]             ctrl_08_reg;\r
169   reg  [31:0]             ctrl_09_reg;\r
170   reg  [31:0]             ctrl_0a_reg;\r
171   reg  [31:0]             ctrl_0b_reg;\r
172   reg  [31:0]             ctrl_10_reg;\r
173   reg  [31:0]             ctrl_11_reg;\r
174   reg  [31:0]             ctrl_12_reg;\r
175   reg  [31:0]             ctrl_13_reg;\r
176 \r
177   reg  [31:0]             ctrl_14_reg;\r
178   wire [31:0]             watchdog_reg;\r
179   reg  [31:0]             watchdog_cnt;\r
180   reg                     wd_armed_jk;\r
181   reg                     trigger_wd;\r
182 \r
183   wire [31:0]             trigger_bits;\r
184   wire [3:0]              trigger_type;\r
185   wire [31:0]             trigger_pos;\r
186   wire [15:0]             trigger_nth;\r
187   wire [15:0]             trigger_delay;\r
188   reg  [15:0]             trigger_dly_cnt;\r
189   wire [31:0]             rle_event_en;\r
190   reg  [15:0]             trigger_cnt;\r
191   reg  [31:0]             ram_rd_d;\r
192   reg  [depth_bits-1:0]   post_trig_cnt;\r
193   reg  [depth_bits-1:0]   trigger_ptr;\r
194   reg                     trigger_in_meta;\r
195   reg                     trigger_in_p1;\r
196   reg                     trigger_in_p2;\r
197   wire [31:0]             pat0;\r
198   wire [31:0]             pat1;\r
199 \r
200 // Variable Size Capture BRAM\r
201   reg  [31:0]             event_ram_array[depth_len-1:0];\r
202   reg  [127:0]            dwords_3_0_ram_array[depth_len-1:0];\r
203   reg  [127:0]            dwords_7_4_ram_array[depth_len-1:0];\r
204   reg  [127:0]            dwords_11_8_ram_array[depth_len-1:0];\r
205   reg  [127:0]            dwords_15_12_ram_array[depth_len-1:0];\r
206 \r
207   reg  [127:0]            dwords_3_0_p1;\r
208   reg  [127:0]            dwords_7_4_p1;\r
209   reg  [127:0]            dwords_11_8_p1;\r
210   reg  [127:0]            dwords_15_12_p1;\r
211 \r
212   reg  [127:0]            dwords_3_0_p2;\r
213   reg  [127:0]            dwords_7_4_p2;\r
214   reg  [127:0]            dwords_11_8_p2;\r
215   reg  [127:0]            dwords_15_12_p2;\r
216 \r
217   reg  [127:0]            dwords_3_0_do;\r
218   reg  [127:0]            dwords_7_4_do;\r
219   reg  [127:0]            dwords_11_8_do;\r
220   reg  [127:0]            dwords_15_12_do;\r
221 \r
222   reg  [depth_bits-1:0]   c_addr;\r
223   reg  [depth_bits-1:0]   c_addr_p1;\r
224   reg                     c_we;\r
225   reg                     c_we_p1;\r
226   wire [31:0]             c_di;\r
227   reg  [31:0]             c_di_p1;\r
228   reg  [depth_bits-1:0]   d_addr;\r
229   reg  [31:0]             d_do;\r
230 \r
231   reg  [63:0]             rle_ram_array[depth_len-1:0];\r
232   reg  [depth_bits-1:0]   a_addr;\r
233   reg  [depth_bits-1:0]   a_addr_p1;\r
234   reg                     a_we;\r
235   reg                     a_we_p1;\r
236   reg  [63:0]             a_di;\r
237   reg  [63:0]             a_di_p1;\r
238   reg  [depth_bits-1:0]   b_addr;\r
239   reg  [63:0]             b_do;\r
240 \r
241   wire [31:0]             data_en_bits;\r
242   reg                     data_en_loc;\r
243   reg                     data_en_loc_p1;\r
244   reg  [31:0]             events_pre;\r
245   reg  [31:0]             events_p1;\r
246   reg  [31:0]             events_p2;\r
247   reg  [31:0]             rle_time;\r
248   reg  [31:0]             rle_time_p1;\r
249   reg                     rle_wd_sample;\r
250   reg                     rle_pre_jk;\r
251   reg                     rle_done_jk;\r
252   wire [7:0]              data_4x_dwords;\r
253 \r
254 \r
255   assign zeros = 16'd0;\r
256   assign ones  = 16'hFFFF;\r
257   assign reset_loc = reset;\r
258 \r
259  \r
260   assign cap_status = { rle_en, 1'b0, rle_done_jk, ~rle_pre_jk,\r
261                         complete_jk, acquired_jk, triggered_jk, armed_jk }; \r
262 \r
263 \r
264 //-----------------------------------------------------------------------------\r
265 // Flop the input events and support reduction for much smaller designs.\r
266 //-----------------------------------------------------------------------------\r
267 always @ ( posedge clk_cap ) begin : proc_din \r
268   if          ( event_bytes == 1 ) begin\r
269     events_loc <= { 24'd0, events_din[7:0] };\r
270   end else if ( event_bytes == 2 ) begin\r
271     events_loc <= { 16'd0, events_din[15:0] };\r
272   end else if ( event_bytes == 3 ) begin\r
273     events_loc <= {  8'd0, events_din[23:0] };\r
274   end else begin\r
275     events_loc <= {        events_din[31:0] };\r
276   end\r
277 \r
278   if ( rle_en == 1 ) begin\r
279     events_pre <= events_loc[31:0] & rle_event_en[31:0];\r
280     events_p1  <= events_pre[31:0];\r
281     events_p2  <= events_p1[31:0];\r
282   end \r
283 end // proc_din\r
284 \r
285 \r
286 //-----------------------------------------------------------------------------\r
287 // Capture Logic. When armed, capture in a continuous loop until trigger is\r
288 // detected and then capture N/2 samples more.\r
289 // Note: Software Must go from Idle to Arm to clear the JKs.\r
290 //-----------------------------------------------------------------------------\r
291 always @ ( * ) begin : proc_data_en\r
292   if ( data_en_bits == 32'h00000000 ||\r
293        ( data_en_bits[31:0] & events_din[31:0] ) != 32'h00000000 ) begin\r
294     data_en_loc <= 1;// Capture sample in time \r
295   end else begin\r
296     data_en_loc <= 0;// Prevent sample capture\r
297   end\r
298 end // proc_data_en\r
299 \r
300 \r
301 //-----------------------------------------------------------------------------\r
302 // Capture Logic. When armed, capture in a continuous loop until trigger is\r
303 // detected and then capture N/2 samples more.\r
304 // Note: Software Must go from Idle to Arm to clear the JKs.\r
305 //-----------------------------------------------------------------------------\r
306 integer i;\r
307 always @ ( posedge clk_cap ) begin : proc_trig \r
308   trigger_in_meta <= trigger_in;\r
309   trigger_in_p1   <= trigger_in_meta;\r
310   trigger_in_p2   <= trigger_in_p1;\r
311   trigger_or      <= 0;\r
312   trigger_and     <= 0;\r
313   trigger_pat     <= 0;\r
314   trigger_or_p1   <= trigger_or;\r
315   trigger_and_p1  <= trigger_and;\r
316   trigger_pat_p1  <= trigger_pat;\r
317   data_en_loc_p1  <= data_en_loc;\r
318 \r
319   for ( i = 0; i <= 31; i=i+1 ) begin\r
320     if ( trigger_bits[i] == 1 && events_loc[i] == 1 ) begin\r
321       trigger_or <= 1;// This is a 32bit OR\r
322     end\r
323   end\r
324   \r
325   if ( ( events_loc[31:0] & trigger_bits[31:0] ) == trigger_bits[31:0] ) begin\r
326     trigger_and <= 1;\r
327   end \r
328 \r
329   if ( \r
330       (( events_loc[31:0] & pat0[31:0] ) ^  \r
331        ( pat1[31:0]       & pat0[31:0] )   ) == 32'h00000000  ) begin\r
332 \r
333     if ( pattern_en == 1 ) begin\r
334       trigger_pat <= 1;// Exact 32bit Pattern Match\r
335     end \r
336   end \r
337  \r
338 end // proc_trig\r
339 \r
340 \r
341 //-----------------------------------------------------------------------------\r
342 // Capture Logic. When armed, capture in a continuous loop until trigger is\r
343 // detected and then capture N/2 samples more.\r
344 // Note: Software Must go from Idle to Arm to clear the JKs.\r
345 //-----------------------------------------------------------------------------\r
346 always @ ( posedge clk_cap ) begin : proc_cap  \r
347   c_we        <= 0;\r
348   trigger_out <= 0;\r
349   trigger_loc <= 0;\r
350   trigger_wd  <= 0;\r
351   active      <= 0;\r
352 \r
353   // CMD_ARM   \r
354   if ( ctrl_cmd_loc == 5'h01 ) begin\r
355     active <= 1;\r
356 \r
357     // Watchdog gets armed on 1st kick. Every kick after clears count.\r
358     // If count expires, assert trigger_wd.\r
359     if ( trigger_wd_en == 1 && ( trigger_or != trigger_or_p1 ) ) begin\r
360       wd_armed_jk <= 1;\r
361     end\r
362     if ( wd_armed_jk == 0 || ( trigger_or != trigger_or_p1 ) ) begin\r
363       watchdog_cnt <= 32'd0;\r
364       trigger_wd   <= 0;\r
365     end else begin\r
366       watchdog_cnt <= watchdog_cnt[31:0] + 1;\r
367       if ( watchdog_cnt == watchdog_reg[31:0] ) begin\r
368         trigger_wd  <= 1;\r
369         wd_armed_jk <= 0;\r
370       end  \r
371     end \r
372 \r
373     if ( triggered_jk == 0 && acquired_jk == 0 ) begin\r
374       // PreTrigger Acquire\r
375       armed_jk <= 1;\r
376       if ( data_en_loc == 1 || data_en_loc_p1 == 1 ) begin\r
377         c_we     <= 1;\r
378         c_addr   <= c_addr + 1;\r
379       end\r
380 \r
381       if ( trigger_dly_cnt != 16'hFFFF ) begin\r
382         trigger_dly_cnt <= trigger_dly_cnt + 1;\r
383       end\r
384 \r
385       if ( ( trigger_type==4'h0 && trigger_and==1    && trigger_and_p1==0 ) ||\r
386            ( trigger_type==4'h1 && trigger_and==0    && trigger_and_p1==1 ) ||\r
387            ( trigger_type==4'h2 && trigger_or ==1    && trigger_or_p1 ==0 ) ||\r
388            ( trigger_type==4'h3 && trigger_or ==0    && trigger_or_p1 ==1 ) ||\r
389            ( trigger_type==4'h4 && trigger_pat==1    && trigger_pat_p1==0 ) ||\r
390            ( trigger_type==4'h5 && trigger_pat==0    && trigger_pat_p1==1 ) ||\r
391            ( trigger_type==4'h6 && trigger_in_p1 ==1 && trigger_in_p2 ==0 ) ||\r
392            ( trigger_type==4'h7 && trigger_in_p1 ==0 && trigger_in_p2 ==1 ) ||\r
393            ( trigger_type==4'h8 && trigger_wd == 1                        )\r
394          ) begin\r
395         if ( trigger_dly_cnt == 16'hFFFF || trigger_dly_en==0 ) begin\r
396           trigger_dly_cnt <= 16'd0;\r
397           trigger_loc     <= 1;// Only used if trigger delay is removed\r
398           c_we            <= 1;// Store Trigger even if data_en_loc == 0\r
399           c_addr          <= c_addr + 1;\r
400         end\r
401       end\r
402 \r
403       // Don't allow trigger until pre-trig buffer is full\r
404       if ( complete_jk == 1 ) begin\r
405         if ( ( trigger_dly_cnt == trigger_delay[15:0] ) || \r
406              (  trigger_dly_en==0 && trigger_loc == 1 ) ) begin\r
407           trigger_dly_cnt <= 16'hFFFF;\r
408           if ( trigger_cnt == trigger_nth[15:0] || trigger_nth_en==0 ) begin\r
409             armed_jk     <= 0;\r
410             trigger_ptr  <= c_addr[depth_bits-1:0];\r
411             trigger_out  <= 1;\r
412             triggered_jk <= 1;\r
413           end\r
414           trigger_cnt <= trigger_cnt + 1;\r
415         end\r
416       end\r
417 \r
418     end else if ( triggered_jk == 1 && acquired_jk == 0 ) begin\r
419       // PostTrigger Acquire\r
420       trigger_out <= 1;\r
421       if ( data_en_loc == 1 || data_en_loc_p1 == 1 ) begin\r
422         c_we          <= 1;\r
423         c_addr        <= c_addr + 1;\r
424         post_trig_cnt <= post_trig_cnt + 1;\r
425       end\r
426       if ( post_trig_cnt == trigger_pos[depth_bits-1:0] ) begin\r
427         acquired_jk <= 1;\r
428         c_we        <= 0;\r
429       end \r
430     end\r
431 \r
432     // If RAM has rolled, then pre-trigger buffer is full. Assert status bit.\r
433     // If RAM hasn't rolled, then pre-trigger samples start at 0x0.\r
434     if ( c_addr[depth_bits-1] == 0 && c_addr_p1[depth_bits-1] == 1 ) begin\r
435       complete_jk <= 1;\r
436     end\r
437 \r
438   // CMD_RESET\r
439   end else if ( ctrl_cmd_loc == 5'h02 ) begin\r
440     c_addr             <= zeros[depth_bits-1:0];\r
441     post_trig_cnt      <= zeros[depth_bits-1:0];\r
442     post_trig_cnt[1:0] <= 2'b11;// Subtracts 3 from trigger_pos for alignment\r
443     trigger_cnt        <= 16'd1;\r
444     trigger_dly_cnt    <= 16'hFFFF;\r
445     armed_jk           <= 0;\r
446     triggered_jk       <= 0;\r
447     acquired_jk        <= 0;\r
448     complete_jk        <= 0;\r
449     wd_armed_jk        <= 0;\r
450   end\r
451 \r
452   // Cleanly xfer clock domains\r
453   xfer_clr <= 0;\r
454   if ( ctrl_cmd_xfer == 1 ) begin\r
455     ctrl_cmd_loc <= ctrl_cmd[4:0];\r
456     xfer_clr     <= 1;\r
457   end\r
458 \r
459 end // proc_cap\r
460   assign c_di = events_loc[31:0];\r
461 \r
462 \r
463 //-----------------------------------------------------------------------------\r
464 // led_bus : Spins while waiting for trigger event. 2 Solids when done.\r
465 //-----------------------------------------------------------------------------\r
466 always @ ( posedge clk_cap ) begin : proc_led_bus\r
467   if ( rle_done_jk == 0 ) begin\r
468     led_bus <= 4'h0;\r
469   end\r
470   if ( ctrl_cmd_loc == 5'h01 ) begin\r
471     if          ( rle_time[25:24] == 2'd0 ) begin\r
472       led_bus <= 4'h1;\r
473     end else if ( rle_time[25:24] == 2'd1 ) begin\r
474       led_bus <= 4'h2;\r
475     end else if ( rle_time[25:24] == 2'd2 ) begin\r
476       led_bus <= 4'h4;\r
477     end else begin\r
478       led_bus <= 4'h8;\r
479     end \r
480     // After Trigger, but before completion, only flash Left and Right\r
481     if ( triggered_jk == 1 ) begin\r
482       led_bus[2] <= 1'b0;\r
483       led_bus[0] <= 1'b0;\r
484     end\r
485   end\r
486   if ( rle_done_jk == 1 ) begin\r
487     led_bus <= 4'hA;\r
488   end\r
489 end\r
490 \r
491 \r
492 //-----------------------------------------------------------------------------\r
493 // RLE Capture Logic. This captures and stores event changes along with \r
494 // time stamps to a x64 BRAM. 1st half of RAM is any pre-trigger activity.\r
495 // 2nd half of RAM is post-trigger activity. Pre-trig is circular and must\r
496 // be unrolled by software in correct order. Enabling RLE block is optional.\r
497 //-----------------------------------------------------------------------------\r
498 always @ ( posedge clk_cap ) begin : proc_rle  \r
499   a_we        <= 0;\r
500   rle_time_p1 <= rle_time[31:0];\r
501   // Prevent RLE from hanging in cases where no activity happens after the\r
502   // trigger event by storing a non-changing sample periodically every\r
503   // 2^24 clock cycles about 100ms at 100 MHz \r
504   // 2^20 clock cycles about 10ms at 100 MHz x 1024 RAM = 10Sec\r
505   // rle_wd_sample  <= rle_time[23] & ~ rle_time_p1[23];\r
506   rle_wd_sample  <= rle_time[19] & ~ rle_time_p1[19];// About 5sec\r
507 \r
508   // CMD_ARM   \r
509   if ( ctrl_cmd_loc == 5'h01 ) begin\r
510     rle_time <= rle_time[31:0] + 1;\r
511     if ( triggered_jk == 0 ) begin\r
512       a_addr[depth_bits-1] <= 0;// Pre-Trigger Half\r
513       // If the prebuffer is invalid, store everything, change or no change\r
514       // as to immediately fill up RAM with valid samples\r
515       // Once prebuffer is valid, only store event deltas ( RLE )\r
516       if ( rle_pre_jk == 1 || rle_wd_sample == 1 || \r
517            ( events_p1 != events_p2[31:0] ) ) begin\r
518         a_we <= 1;\r
519         a_addr[depth_bits-2:0] <= a_addr[depth_bits-2:0] + 1; \r
520         if ( a_addr[depth_bits-2:0] == ones[depth_bits-2:0] ) begin\r
521           rle_pre_jk <= 0;// PreBuffer is completely valid - and rolling\r
522         end\r
523       end\r
524     end else if ( triggered_jk == 1 && rle_done_jk == 0 ) begin\r
525       if ( ( events_p1 != events_p2[31:0] ) || ( rle_wd_sample == 1) ) begin\r
526         a_we <= 1;\r
527         a_addr[depth_bits-2:0] <= a_addr[depth_bits-2:0] + 1; \r
528         // If previous write was to last address in RAM, then call it quits\r
529         if ( a_addr[depth_bits-2:0] == ones[depth_bits-2:0] ) begin\r
530           rle_done_jk            <= 1;// Post-Trig RAM is full\r
531           a_we                   <= 0;\r
532           a_addr[depth_bits-2:0] <= a_addr[depth_bits-2:0];\r
533         end\r
534         // If previous cycle was pre-trig, set address to start of post trig\r
535         if ( a_addr[depth_bits-1] == 0 ) begin\r
536           a_addr[depth_bits-1]   <= 1;// Post-Trigger Half\r
537           a_addr[depth_bits-2:0] <= zeros[depth_bits-2:0];\r
538         end\r
539       end\r
540     end\r
541 \r
542   // CMD_RESET\r
543   end else if ( ctrl_cmd_loc == 5'h02 ) begin\r
544     rle_time    <= 32'd0;// 43 seconds at 100 MHz\r
545     a_addr      <= zeros[depth_bits-1:0];\r
546     rle_pre_jk  <= 1;\r
547     rle_done_jk <= 0;\r
548   end\r
549   a_di[31:0]  <= events_p1[31:0];\r
550   a_di[63:32] <= rle_time[31:0];\r
551 end // proc_rle\r
552 //assign a_di[31:0]  = events_p1[31:0];\r
553 //assign a_di[63:32] = rle_time[31:0];\r
554 \r
555 \r
556 //-----------------------------------------------------------------------------\r
557 // LocalBus Write Ctrl register\r
558 //-----------------------------------------------------------------------------\r
559 always @ ( posedge clk_lb ) begin : proc_lb_wr\r
560   if ( lb_wr == 1 && lb_cs_ctrl == 1 ) begin\r
561     ctrl_reg[4:0] <= lb_wr_d[4:0];\r
562     ctrl_cmd_xfer <= 1;\r
563   end \r
564 \r
565   if ( lb_wr == 1 && lb_cs_data == 1 ) begin\r
566     case( ctrl_cmd[4:0] )\r
567       5'h04 : ctrl_04_reg <= lb_wr_d[31:0];\r
568       5'h05 : ctrl_05_reg <= lb_wr_d[31:0];\r
569       5'h06 : ctrl_06_reg <= lb_wr_d[31:0];\r
570       5'h07 : ctrl_07_reg <= lb_wr_d[31:0];\r
571 \r
572       5'h08 : ctrl_08_reg <= lb_wr_d[31:0];\r
573       5'h09 : ctrl_09_reg <= lb_wr_d[31:0];\r
574       5'h0A : ctrl_0a_reg <= lb_wr_d[31:0];\r
575       5'h0B : ctrl_0b_reg <= lb_wr_d[31:0];\r
576 \r
577       5'h10 : ctrl_10_reg <= lb_wr_d[31:0];\r
578       5'h11 : ctrl_11_reg <= lb_wr_d[31:0];\r
579       5'h12 : ctrl_12_reg <= lb_wr_d[31:0];\r
580       5'h13 : ctrl_13_reg <= lb_wr_d[31:0];\r
581       5'h14 : ctrl_14_reg <= lb_wr_d[31:0];\r
582     endcase\r
583   end\r
584 \r
585   if ( xfer_clr == 1 ) begin\r
586     ctrl_cmd_xfer  <= 0;\r
587   end\r
588 \r
589   if ( ctrl_cmd == 5'h01 ) begin\r
590     d_addr  <= c_addr[depth_bits-1:0];// When Acq stops, d_addr will be last \r
591   end\r
592   if ( lb_wr == 1 && lb_cs_data == 1 && ctrl_cmd == 5'h09 ) begin\r
593     d_addr <= lb_wr_d[depth_bits-1:0];// Load user specified address\r
594   end \r
595   if ( rd_inc == 1 ) begin\r
596     d_addr  <= d_addr[depth_bits-1:0] + 1;// Auto Increment on each read\r
597   end \r
598 \r
599   if ( reset_loc == 1 ) begin\r
600     ctrl_reg[4:0] <= 5'd0;\r
601     ctrl_cmd_xfer <= 1;// Flag to xfer ctrl_reg into other clock domain\r
602   end \r
603 end\r
604 \r
605   assign ctrl_cmd[4:0]     = ctrl_reg[4:0];\r
606 \r
607   assign trigger_type      = ctrl_04_reg[3:0];\r
608   assign trigger_bits      = ctrl_05_reg[31:0];\r
609   assign trigger_nth       = ctrl_06_reg[15:0];\r
610   assign trigger_delay     = ctrl_06_reg[31:16];\r
611   assign trigger_pos       = ctrl_07_reg[31:0];\r
612   assign rle_event_en      = ctrl_08_reg[31:0];\r
613 \r
614   assign user_ctrl[31:0]   = ctrl_10_reg[31:0];\r
615   assign user_pat0[31:0]   = ctrl_11_reg[31:0];\r
616   assign user_pat1[31:0]   = ctrl_12_reg[31:0];\r
617   assign pat0[31:0]        = ctrl_11_reg[31:0];\r
618   assign pat1[31:0]        = ctrl_12_reg[31:0];\r
619   assign data_en_bits[31:0] = ctrl_13_reg[31:0];\r
620   assign watchdog_reg[31:0] = ctrl_14_reg[31:0];\r
621 \r
622   assign ctrl_rd_ptr[15:0] = ctrl_09_reg[15:0];\r
623   assign ctrl_rd_page[4:0] = ctrl_0a_reg[4:0];\r
624 \r
625   assign data_4x_dwords = data_dwords;\r
626 \r
627 \r
628 //-----------------------------------------------------------------------------\r
629 // LocalBus readback of ctrl_reg and data_reg\r
630 //-----------------------------------------------------------------------------\r
631 always @ ( posedge clk_lb ) begin : proc_lb_rd\r
632   lb_rd_d   <= 32'd0;\r
633   lb_rd_rdy <= 0;\r
634   rd_inc    <= 0;\r
635 \r
636   if ( lb_rd == 1 && lb_cs_ctrl == 1 ) begin\r
637     lb_rd_d[4:0] <= ctrl_reg[4:0];\r
638     lb_rd_rdy    <= 1;\r
639   end \r
640 \r
641   if ( lb_rd == 1 && lb_cs_data == 1 ) begin\r
642     lb_rd_rdy <= 1;\r
643     if ( ctrl_cmd == 5'h00 ||\r
644          ctrl_cmd == 5'h01    \r
645        ) begin\r
646       lb_rd_d[7:0] <= cap_status[7:0];\r
647     end\r
648     if ( ctrl_cmd == 5'h0b ) begin\r
649       lb_rd_d[31:16] <= sump_id;// Identification\r
650       lb_rd_d[15:8]  <= sump_rev;// Revision\r
651       lb_rd_d[7:5]   <= 3'd0;\r
652       lb_rd_d[4]     <= ~ nonrle_en;// Invert to disable backwards SW comptbl\r
653       lb_rd_d[3]     <= rle_en;\r
654       lb_rd_d[2]     <= pattern_en;\r
655       lb_rd_d[1]     <= trigger_nth_en;\r
656       lb_rd_d[0]     <= trigger_dly_en;\r
657     end\r
658     if ( ctrl_cmd == 5'h0c ) begin\r
659       lb_rd_d[31:28] <= rle_en     ;// 1 if RLE RAM exists\r
660       lb_rd_d[27:24] <= event_bytes;// How Many Event Bytes 1-4\r
661       lb_rd_d[23:16] <= data_4x_dwords[5:2];// How Many 32bit BRAMs data 4x \r
662       lb_rd_d[15:0]  <= depth_len;  // How deep RAMs are\r
663     end\r
664     if ( ctrl_cmd == 5'h0d ) begin\r
665       lb_rd_d[15:0]  <= freq_fracts;// Fractional MHz bits 1/2,1/4,etc.\r
666       lb_rd_d[31:16] <= freq_mhz   ;// Integer MHz\r
667     end\r
668     if ( ctrl_cmd == 5'h0e ) begin\r
669       lb_rd_d[depth_bits-1:0] <= trigger_ptr[depth_bits-1:0];// Where Trig Is\r
670     end\r
671     if ( ctrl_cmd == 5'h0f ) begin\r
672       lb_rd_d <= ram_rd_d[31:0];\r
673       rd_inc  <= 1;// Auto Increment RAM Address\r
674     end\r
675   end \r
676 \r
677   if ( data_dwords != 0 ) begin\r
678     // Mux between the BRAMs\r
679     case( ctrl_rd_page[4:0] )\r
680       5'H02   : ram_rd_d <= b_do[31:0];   // RLE Data\r
681       5'H03   : ram_rd_d <= b_do[63:32];  // RLE Time\r
682 \r
683       5'H10   : ram_rd_d <= dwords_3_0_do[31:0];\r
684       5'H11   : ram_rd_d <= dwords_3_0_do[63:32];\r
685       5'H12   : ram_rd_d <= dwords_3_0_do[95:64];\r
686       5'H13   : ram_rd_d <= dwords_3_0_do[127:96];\r
687 \r
688       5'H14   : ram_rd_d <= dwords_7_4_do[31:0];\r
689       5'H15   : ram_rd_d <= dwords_7_4_do[63:32];\r
690       5'H16   : ram_rd_d <= dwords_7_4_do[95:64];\r
691       5'H17   : ram_rd_d <= dwords_7_4_do[127:96];\r
692 \r
693       5'H18   : ram_rd_d <= dwords_11_8_do[31:0];\r
694       5'H19   : ram_rd_d <= dwords_11_8_do[63:32];\r
695       5'H1a   : ram_rd_d <= dwords_11_8_do[95:64];\r
696       5'H1b   : ram_rd_d <= dwords_11_8_do[127:96];\r
697 \r
698       5'H1c   : ram_rd_d <= dwords_15_12_do[31:0];\r
699       5'H1d   : ram_rd_d <= dwords_15_12_do[63:32];\r
700       5'H1e   : ram_rd_d <= dwords_15_12_do[95:64];\r
701       5'H1f   : ram_rd_d <= dwords_15_12_do[127:96];\r
702 \r
703       default : ram_rd_d <= d_do[31:0];    // Events\r
704     endcase\r
705   end else begin\r
706     // Mux between the BRAMs\r
707     case( ctrl_rd_page[4:0] )\r
708       5'H02   : ram_rd_d <= b_do[31:0]; // RLE Data\r
709       5'H03   : ram_rd_d <= b_do[63:32];// RLE Time\r
710       default : ram_rd_d <= d_do[31:0]; // Events\r
711     endcase\r
712   end \r
713 \r
714 end // proc_lb_rd\r
715 \r
716 \r
717 //-----------------------------------------------------------------------------\r
718 // Data Dual Port RAM - Infer RAM here to make easy to change depth on the fly\r
719 //-----------------------------------------------------------------------------\r
720 always @( posedge clk_cap  )\r
721 begin\r
722   c_we_p1   <= c_we;\r
723   c_addr_p1 <= c_addr;\r
724   c_di_p1   <= c_di;\r
725   if ( c_we_p1 ) begin\r
726     if ( nonrle_en == 1 ) begin\r
727       event_ram_array[c_addr_p1] <= c_di_p1;\r
728     end \r
729   end // if ( c_we )\r
730 \r
731   dwords_3_0_p1   <= dwords_3_0[127:0];\r
732   dwords_7_4_p1   <= dwords_7_4[127:0];\r
733   dwords_11_8_p1  <= dwords_11_8[127:0];\r
734   dwords_15_12_p1 <= dwords_15_12[127:0];\r
735 \r
736   dwords_3_0_p2   <= dwords_3_0_p1[127:0];\r
737   dwords_7_4_p2   <= dwords_7_4_p1[127:0];\r
738   dwords_11_8_p2  <= dwords_11_8_p1[127:0];\r
739   dwords_15_12_p2 <= dwords_15_12_p1[127:0];\r
740 \r
741   if ( c_we_p1 ) begin\r
742     if ( data_dwords >= 4 ) begin\r
743       dwords_3_0_ram_array[ c_addr_p1 ]  <= dwords_3_0_p2[127:0];\r
744     end\r
745     if ( data_dwords >= 8 ) begin\r
746       dwords_7_4_ram_array[ c_addr_p1 ]  <= dwords_7_4_p2[127:0];\r
747     end\r
748     if ( data_dwords >= 12 ) begin\r
749       dwords_11_8_ram_array[ c_addr_p1 ] <= dwords_11_8_p2[127:0];\r
750     end\r
751     if ( data_dwords >= 16 ) begin\r
752       dwords_15_12_ram_array[ c_addr_p1 ] <= dwords_15_12_p2[127:0];\r
753     end\r
754   end // if ( c_we )\r
755 end // always\r
756 \r
757 \r
758 //-----------------------------------------------------------------------------\r
759 // 2nd Port of RAM is clocked from local bus\r
760 //-----------------------------------------------------------------------------\r
761 always @( posedge clk_lb )\r
762 begin\r
763   if ( nonrle_en == 1 ) begin\r
764     d_do    <= event_ram_array[d_addr] ;\r
765   end\r
766 \r
767   if ( data_dwords >= 4 ) begin\r
768     dwords_3_0_do   <= dwords_3_0_ram_array[ d_addr ];\r
769   end\r
770   if ( data_dwords >= 8 ) begin\r
771     dwords_7_4_do   <= dwords_7_4_ram_array[ d_addr ];\r
772   end\r
773   if ( data_dwords >= 12 ) begin\r
774     dwords_11_8_do  <= dwords_11_8_ram_array[ d_addr ];\r
775   end\r
776   if ( data_dwords >= 16 ) begin\r
777     dwords_15_12_do <= dwords_15_12_ram_array[ d_addr ];\r
778   end\r
779 end // always\r
780 \r
781 \r
782 //-----------------------------------------------------------------------------\r
783 // RLE Dual Port RAM - Infer RAM here to make easy to change depth on the fly\r
784 //-----------------------------------------------------------------------------\r
785 always @( posedge clk_cap  )\r
786 begin\r
787   if ( rle_en == 1 ) begin\r
788     a_we_p1   <= a_we;\r
789     a_addr_p1 <= a_addr;\r
790     a_we_p1   <= a_we;\r
791     a_addr_p1 <= a_addr;\r
792     a_di_p1   <= a_di;\r
793 //  if ( a_we_p1 ) begin\r
794 //    rle_ram_array[a_addr_p1] <= a_di_p1;\r
795 //  end // if ( a_we )\r
796     if ( a_we    ) begin\r
797       rle_ram_array[a_addr   ] <= a_di;\r
798     end // if ( a_we )\r
799   end\r
800 end // always\r
801 \r
802 \r
803 //-----------------------------------------------------------------------------\r
804 // 2nd Port of RAM is clocked from local bus\r
805 //-----------------------------------------------------------------------------\r
806 always @( posedge clk_lb )\r
807 begin\r
808   if ( rle_en == 1 ) begin\r
809     b_do <= rle_ram_array[d_addr];\r
810   end\r
811 end // always\r
812 \r
813 \r
814 endmodule // sump2\r