Attention

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

half_filt Source File

  1`timescale 1ns / 1ns
  2// Multiplier-free half-band filter and decimator.
  3// See http://recycle.lbl.gov/~ldoolitt/halfband/
  4
  5// This is an FIR filter
  6//   https://en.wikipedia.org/wiki/Finite_impulse_response
  7// with 7 non-zero taps, categorized as an order-3 half-band filter.
  8// The taps are
  9//   2  0  -9  0  39  64  39  0  -9  0  2
 10
 11// The filter has a nominal low-frequency gain of unity.  But since
 12// the gain peaks at +0.074 dB (at an input frequency of 0.12 of the input
 13// sample rate), the output can clip.  The module correctly saturates
 14// its arithmetic.
 15
 16// This filter is linear-phase (note the symmetric tap coefficients),
 17// with an essential DSP group delay of 5 samples.
 18// Additional pipeline delay is added by the implementation; see below.
 19
 20// The input can consist of a fixed (set by the parameter len at
 21// build-time) number of interleaved signal data streams.
 22// The half-band filter is applied to each stream independently.
 23
 24// half_filt() can accept 20-bit data at the full clock rate.
 25// The output stream is decimated by two; blocks of len cycles of 20-bit
 26// output data are interleaved with len silent cycles.  The input data
 27// and ing control are pipelined four cycles before getting to the output.
 28
 29// There are no restrictions on the ing pattern.  The len-way
 30// interleaving of the input data ignores cycles with ing low.
 31
 32// Synthesizes to 251 slices at 116 MHz in XC3Sxxx-4 using XST-8.2i
 33
 34module half_filt(
 35     input clk,  // Rising edge clock input; all logic is synchronous in this domain
 36     input signed [19:0] ind,  // Input data
 37     input ing,  // Active high gate marking input data as valid
 38     output signed [19:0] outd,  // Output data
 39     output outg,  // Active high gate marking output data as valid
 40     input reset  // manually reset counter
 41);
 42
 43parameter len = 4;  // number of interleaved data streams
 44wire signed [19:0] d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
 45
 46assign d0 = ind;
 47reg_delay #(.dw(20),.len(len)) h0(clk, 1'b0, ing, d0, d1);
 48reg_delay #(.dw(20),.len(len)) h1(clk, 1'b0, ing, d1, d2);
 49reg_delay #(.dw(20),.len(len)) h2(clk, 1'b0, ing, d2, d3);
 50reg_delay #(.dw(20),.len(len)) h3(clk, 1'b0, ing, d3, d4);
 51reg_delay #(.dw(20),.len(len)) h4(clk, 1'b0, ing, d4, d5);
 52reg_delay #(.dw(20),.len(len)) h5(clk, 1'b0, ing, d5, d6);
 53reg_delay #(.dw(20),.len(len)) h6(clk, 1'b0, ing, d6, d7);
 54reg_delay #(.dw(20),.len(len)) h7(clk, 1'b0, ing, d7, d8);
 55reg_delay #(.dw(20),.len(len)) h8(clk, 1'b0, ing, d8, d9);
 56reg_delay #(.dw(20),.len(len)) h9(clk, 1'b0, ing, d9, d10);
 57
 58reg signed [20:0] s1=0, s2=0, s3=0, s4=0;
 59reg sg=0;
 60always @(posedge clk) begin
 61     if (reset) begin
 62             sg <= 0;
 63     end else begin
 64             sg <= ing;
 65     end
 66     s1 <= d0 + d10;
 67     s2 <= d2 + d8;
 68     s3 <= d4 + d6;
 69     s4 <= d5 + 0; // {d5[19],d5};
 70end
 71
 72// FIR filter coefficients:
 73// 2*(1/32 0 -1/8-1/64 0 1/2+1/8-1/64 1 1/2+1/8-1/64 0 -1/8-1/64 0 1/32)/4
 74// see lowp3.m
 75
 76reg signed [21:0] a1=0, a2=0, a3=0, a4=0;
 77reg ag=0;
 78always @(posedge clk) begin
 79     if (reset) begin
 80             ag <= 0;
 81     end else begin
 82             ag <= sg;
 83     end
 84`ifdef TRUST_VERILOG_DIVISION
 85     a1 <= s1/16 + 0;
 86     a2 <= s2/4 + s2/32;
 87     a3 <= s3/4 - s3/32;
 88     a4 <= s3 + 2*s4;
 89`else
 90     a1 <= {{5{s1[20]}},s1[20:4]};
 91     a2 <= {{3{s2[20]}},s2[20:2]} + {{6{s2[20]}},s2[20:5]};
 92     a3 <= {{3{s3[20]}},s3[20:2]} - {{6{s3[20]}},s3[20:5]};
 93     a4 <= {{1{s3[20]}},s3[20:0]} + {            s4[20:0],1'b0};
 94`endif
 95end
 96
 97reg signed [22:0] b1=0, b2=0;
 98reg bg=0;
 99reg [8:0] samp=0;
100reg show=0;
101always @(posedge clk) begin
102     b1 <= a1 - a2;
103     b2 <= a3 + a4 + 1;
104     if (reset) begin
105             bg <= 0;
106             samp <= 0;
107             show <= 0;
108     end else begin
109             bg <= ag;
110             if (bg) begin
111                     samp <= (samp==len-1'b1) ? 0 : samp+1'b1;
112                     if (samp==len-1) show <= ~show;
113             end
114     end
115end
116
117wire signed [21:0] c1;
118sat_add #(23,22) finals(clk,b1,b2,c1);
119reg cg=0;
120always @(posedge clk) begin
121     if (reset) cg <= 0;
122     else cg <= bg & show;
123end
124
125assign outd = c1[21:2];
126assign outg = cg;
127
128endmodule