Attention
This documentation is a work in progress. Expect to see errors and unfinished things.
cic_wave_recorder Source File
1`timescale 1ns / 1ns
2
3/* CIC Wave Recorder
4 Generic waveform recording system comprised of:
5 - Multichannel CIC filter with runtime selectable base sample rate and waveform
6 sampling rate (cc_samp_per)
7 - Double-buffered circular buffer that can be read through a local bus interface
8
9 +------------------------+
10 | +-------+ +------+ |
11 in[0]+-----> | | <---+ rd_addr/stb
12 | | CIC | | CIRC | |
13 in[1]+-----> +----> BUF | |
14 | |MULTICH| |SERIAL+---> d_out
15 in[N]+-----> | | | |
16 | +---^---+ +---^--+ |
17 | | | |
18 +------------------------+
19 | |
20 cic_sample + + cc_sample
21*/
22
23module cic_wave_recorder #(
24 parameter n_chan=12,
25
26 // DI parameters
27 parameter di_dwi=16, // data width
28 parameter di_rwi=32, // result width
29 // Difference between above two widths should be N*log2 of the maximum number
30 // of samples per CIC sample, where N=2 is the order of the CIC filter.
31 parameter di_noise_bits=4, // Number of noise bits to discard at the output of Double Integrator.
32 // This depends on the SNR of the inputs and the CIC sample rate
33 // CCFILT parameters
34 parameter cc_outw=20, // CCFilt output width; Must be 20 if using half-band filter
35 parameter cc_halfband=1,
36 parameter cc_use_delay=0, // Match pipeline length of filt_halfband=1
37 parameter cc_shift_base=0, // Bits to discard from previous acc step
38 parameter cc_shift_wi=4,
39
40
41 // Circular Buffer parameters
42 parameter buf_dw=16, // If buf_dw < cc_outw, lsb are dropped
43 // If buf_dw > cc_outw, msbs are zero-filled
44 parameter buf_aw=13,
45 parameter lsb_mask=1, // LSB of channel mask is CH0
46 parameter buf_stat_w=16,
47 parameter buf_auto_flip=1 // auto_flip=1: Double buffers will be flipped when
48 // last read address is reached
49 // auto_flip=0: Buffers must be explicitly flipped by
50 // using stb_out as a pulse and not a strobe
51) (
52 input iclk,
53 input reset,
54 input stb_in, // Strobe signal for input samples
55 input [n_chan*di_dwi-1:0] d_in, // Flattened array of unprocessed data streams. CH0 in LSBs
56 input cic_sample, // CIC base sampling signal
57
58 // Post-integrator conveyor belt tap
59 output di_stb_out,
60 output [di_rwi-1:0] di_sr_out,
61
62 // CC Filter controls
63 input cc_sample, // CCFilt sampling signal
64 input [cc_shift_wi-1:0] cc_shift, // controls scaling of filter result
65
66 // Channel selector controls
67 input [n_chan-1:0] chan_mask, // Bitmask of channels to record
68
69 // Selected waveform data in iclk domain
70 output wave_gate_out,
71 output wave_dval_out,
72 output [buf_dw-1:0] wave_data_out,
73
74 // Circular Buffer control and status
75 input oclk,
76 input buf_write, // Level-signal to enable writing into buffer
77 output buf_sync, // single-cycle when buffer starts/ends
78 output buf_transferred, // single-cycle when a buffer has been
79 // handed over for reading;
80 // one cycle delayed from buf_sync
81 input buf_stop, // single-cycle - interrupts cbuf writing
82 output [buf_stat_w-1:0] buf_count,
83 output [buf_aw-1:0] buf_stat2, // includes fault bit
84 output [buf_stat_w-1:0] buf_stat, // includes fault bit, and (if set) the last valid location
85 output [buf_aw+4:0] debug_stat, // {stb_in, boundary, btest, wbank, rbank, wr_addr}
86
87 // Circular Buffer data readout
88 input buf_stb,
89 output buf_enable,
90 input [buf_aw-1:0] buf_read_addr, // nominally 8192 locations
91 output [buf_dw-1:0] buf_d_out
92);
93
94 // ------
95 // CIC Filter
96 // ------
97 wire cic_stb_out;
98 wire [cc_outw-1:0] cic_sr_out;
99
100 cic_multichannel #(
101 .n_chan (n_chan),
102 .di_dwi (di_dwi),
103 .di_rwi (di_rwi),
104 .di_noise_bits (di_noise_bits),
105 .cc_outw (cc_outw),
106 .cc_halfband (cc_halfband),
107 .cc_use_delay (cc_use_delay),
108 .cc_shift_base (cc_shift_base),
109 .cc_shift_wi (cc_shift_wi))
110 i_cic_multichannel
111 (
112 .clk (iclk),
113 .reset (reset),
114 .stb_in (stb_in),
115 .d_in (d_in),
116 .cic_sample (cic_sample),
117
118 .cc_sample (cc_sample),
119 .cc_shift (cc_shift),
120
121 .di_stb_out (di_stb_out),
122 .di_sr_out (di_sr_out),
123
124 .cc_stb_out (cic_stb_out),
125 .cc_sr_out (cic_sr_out)
126 );
127
128 // ------
129 // Double-buffered circular buffer
130 // ------
131
132 wire [buf_dw-1:0] wave_data_i;
133
134 // Resize output of CIC filter so it can be stored in circle_buf
135 generate
136 if (cc_outw > buf_dw) begin: g_wave_data_resize
137 assign wave_data_i = cic_sr_out[cc_outw-1:(cc_outw-buf_dw)]; // Drop lsbs
138 end else if (cc_outw < buf_dw) begin: g_wave_data_pad
139 assign wave_data_i = {{(buf_dw-cc_outw){1'b0}}, cic_sr_out}; // Zero extend
140 end else begin: g_wave_data_direct
141 assign wave_data_i = cic_sr_out;
142 end
143 endgenerate
144
145 // Avoid partial strobes/bursts when using buf_write
146 // Assume strobes are well formed (asserted in fchan_subset)
147 // Count beats in case there's no separation between bursts
148 reg [4:0] chan_stb_cnt=0;
149 reg wr_gated_r=0;
150
151 wire wr_gated = (chan_stb_cnt==0 && !buf_write);
152
153 always @(posedge iclk) begin
154 if (cic_stb_out) begin
155 chan_stb_cnt <= chan_stb_cnt + 1;
156
157 if (wr_gated) wr_gated_r <= 1;
158 end
159
160 if (chan_stb_cnt == n_chan-1) begin
161 chan_stb_cnt <= 0;
162 wr_gated_r <= 0;
163 end
164 end
165
166 circle_buf_serial #(
167 .n_chan (n_chan),
168 .lsb_mask (lsb_mask),
169 .buf_aw (buf_aw),
170 .buf_dw (buf_dw),
171 .buf_stat_w (buf_stat_w),
172 .buf_auto_flip (buf_auto_flip))
173 i_circle_buf_serial (
174 .iclk (iclk),
175 .reset (reset),
176 .sr_in (wave_data_i),
177 .sr_stb (cic_stb_out & (~wr_gated & ~wr_gated_r)),
178 .chan_mask (chan_mask),
179 .wave_data (wave_data_out),
180 .wave_dval (wave_dval_out),
181 .wave_gate (wave_gate_out),
182 .oclk (oclk),
183 .buf_sync (buf_sync),
184 .buf_transferred (buf_transferred),
185 .buf_stop (buf_stop),
186 .buf_count (buf_count),
187 .buf_stat2 (buf_stat2),
188 .buf_stat (buf_stat),
189 .debug_stat (debug_stat),
190 .stb_out (buf_stb),
191 .enable (buf_enable),
192 .read_addr (buf_read_addr),
193 .d_out (buf_d_out)
194 );
195
196endmodule