Attention

This documentation is a work in progress. Expect to see errors and unfinished things.

ccfilt Source File

  1`timescale 1ns / 1ns
  2// Cascaded Differentiator and post-filter
  3//  also includes a barrel shifter to adjust scale to compensate
  4//  for changing decimation intervals
  5module ccfilt #(
  6     parameter dw=32,  // data width of mon_chan output:
  7             // should be CIC input data width (18),
  8             // plus 2 * log2(max sample period)
  9     parameter outw=20,  // output data width
 10             // comments below assume outw == 20
 11             // outw must be 20 if using half-band filter
 12     parameter shift_wi=4,
 13     parameter shift_base=0,
 14     parameter dsr_len = 12,  // expected length of strobe pattern
 15     parameter use_hb = 1,  // compile-time conditional half-band code
 16     parameter use_delay = 0  // match pipeline length with use_hb case
 17) (
 18     input clk,
 19     // unprocessed double-integrator output
 20     input [dw-1:0] sr_in,
 21     input sr_valid,
 22
 23     // semi-static configuration
 24     input [shift_wi-1:0] shift,  // controls scaling of result
 25
 26     // filtered and scaled result, ready for storage
 27     output signed [outw-1:0] result,
 28     input reset,
 29     output strobe
 30);
 31
 32// Two stages of differentiator
 33wire valid2;
 34wire signed [dw-1:0] d2;
 35doublediff #(.dw(dw), .dsr_len(dsr_len)) diff(.clk(clk),
 36     .d_in(sr_in), .g_in(sr_valid), .d_out(d2), .g_out(valid2));
 37
 38// Reduce bit width for entry to half-band filter
 39// First get 21 bits, then see below
 40reg signed [outw:0] d3=0;
 41reg ovf=0;
 42`define UNIFORM(x) ((~|(x)) | &(x))  // All 0's or all 1's
 43// Lowest supported filter is R=4 (for which we set shift=0), and N=2 always.
 44// Input to CIC is 18 bits, so maximum 22 bits come out.
 45// Check for overflow is a simulation-only feature to check for bugs.
 46
 47// Invent some extra bits, just so the case statement is all legal Verilog,
 48// even if dw is less than 36.
 49// This construction should not result in any actual extra hardware.
 50localparam dwmax = outw+16+shift_base;
 51wire signed [dwmax:0] d2e = {{dwmax+1-dw{d2[dw-1]}},d2};
 52wire [shift_wi:0] full_shift = shift + shift_base;
 53wire [dwmax:0] d2es = d2e >>> full_shift;
 54always @(posedge clk) begin
 55     d3 <= d2es;
 56     ovf <= ~ `UNIFORM(d2es[dwmax:outw]);
 57end
 58reg valid3=0;
 59always @(posedge clk) valid3 <= valid2;
 60`undef UNIFORM
 61
 62`ifdef SIMULATE
 63reg [3:0] ch_id=0;
 64reg signed [dw-1:0] d2_prev;
 65wire print_overflow = ovf & valid3;
 66always @(posedge clk) begin
 67     ch_id <= valid3 ? (ch_id+1) : 0;
 68     d2_prev <= d2;
 69end
 70always @(negedge clk) if (print_overflow) $display("overflow %d %x %x %d %d", shift, d2_prev, d3, ch_id, $time);
 71`endif
 72
 73// Universal definition; note: old and new are msb numbers, not bit widths.
 74`define SAT(x,old,new) ((~|x[old:new] | &x[old:new]) ? x[new:0] : {x[old],{new{~x[old]}}})
 75
 76// Factor of two scaling of output by virtue of the LO table construction.
 77// When properly set up, saturation will only occur with pathological LO choices and/or ADC clipping.
 78reg signed [outw-1:0] d4=0;
 79reg valid4=0;
 80always @(posedge clk) begin
 81     d4 <= `SAT(d3, outw, outw-1);
 82     valid4 <= valid3;
 83end
 84
 85`undef SAT
 86
 87// Instantiate half-band filter .. or not
 88wire [outw-1:0] d5;
 89wire valid5;
 90reg [4-1:0] delay_v45=0;   // seems half_filter take 4 cycles?
 91reg [outw*4-1:0] delay_d45=0;
 92generate
 93if (use_hb) begin: g_use_hb
 94     half_filt #(.len(dsr_len))
 95             hb(.clk(clk), .ind(d4), .ing(valid4), .outd(d5), .outg(valid5), .reset(reset));
 96end
 97else if (use_delay) begin: g_use_delay
 98     always@(posedge clk) begin
 99             delay_v45 <= {delay_v45[4-2:0],valid4};
100             delay_d45 <= {delay_d45[outw*(4-1)-1:0],d4};
101
102     end
103     assign d5 = delay_d45[outw*4-1:outw*(4-1)];
104     assign valid5 = delay_v45[4-1];
105end
106else begin: g_use_short
107     assign d5 = d4;
108     assign valid5 = valid4;
109end
110endgenerate
111
112assign strobe=valid5;
113assign result=d5;
114endmodule