Attention

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

complex_freq_wrap Source File

  1`timescale 1ns / 1ns
  2
  3/** COMPLEX_FREQ_WRAP **
  4    Wraps around complex_freq.v and adds COMB (CCFILT) portion
  5    of upstream CIC filter and conveyor belt channel selection.
  6
  7    Assumes following conveyor belt ordering:
  8    {I,Q} * {Field, Forward, Reverse, Fiber, Drive, spare}
  9*/
 10
 11module complex_freq_wrap #(
 12   parameter n_chan     = 12,
 13   parameter sr_wi      = 40, // Conveyor belt data width
 14   parameter shift_base = 4,
 15   parameter refcnt_w   = 17
 16) (
 17   input              clk,         // single clock domain
 18   input  [1:0]       channel_sel, // 0 - Field, 1 - Forward, 2 - Reverse, 3 - IQ_Fiber (from PRC)
 19   input              sample_wave,
 20   input  [3:0]       wave_shift,
 21   input              sr_valid,
 22   input  [sr_wi-1:0] sr_data,
 23   output signed [refcnt_w-1:0] reg_freq,
 24   output             reg_freq_valid,
 25   output [16:0]      reg_amp_max,
 26   output [16:0]      reg_amp_min,
 27   output             reg_updated,
 28   // Additional outputs
 29   output [23:0]      avg_power,
 30   output             avg_power_strobe,
 31   output             reg_timing_err
 32);
 33   localparam CCFILT_OUTW = 20;
 34   localparam CFREQ_INW   = 18;
 35   localparam FIELD_CHID = 0, FWD_CHID = 1, REV_CHID = 2, IQFIB_CHID = 3;
 36
 37   wire signed [CCFILT_OUTW-1:0] cc_result;
 38   wire cc_strobe;
 39   wire signed [CFREQ_INW-1:0] cfreq_data;
 40   wire signed [CFREQ_INW-1:0] cfreq_din;
 41   wire cfreq_valid;
 42
 43   reg  [n_chan-1: 0] fchan_mask, fchan_mask_r;
 44   wire fchan_time_err, cfreq_time_err;
 45
 46   ccfilt #(
 47      .use_hb     (0),
 48      .use_delay  (0),
 49      .dsr_len    (n_chan),
 50      .dw         (sr_wi),
 51      .outw       (CCFILT_OUTW),
 52      .shift_base (shift_base))
 53   ccfilt(
 54      .clk        (clk),
 55      .reset      (1'b0),
 56      .sr_in      (sr_data),
 57      .sr_valid   (sr_valid & sample_wave),
 58      .shift      (wave_shift),
 59      .result     (cc_result),
 60      .strobe     (cc_strobe));
 61
 62   // Truncate LSBs - Assumes that CCFILT_OUTW >= CFREQ_INW
 63   assign cfreq_data = cc_result[CCFILT_OUTW-1:CCFILT_OUTW-CFREQ_INW];
 64
 65   // Channel selection
 66   always @(channel_sel) begin
 67      fchan_mask = 0;
 68      case (channel_sel)
 69         FIELD_CHID : fchan_mask[1:0] = 2'b11;
 70         FWD_CHID   : fchan_mask[3:2] = 2'b11;
 71         REV_CHID   : fchan_mask[5:4] = 2'b11;
 72         IQFIB_CHID : fchan_mask[7:6] = 2'b11;
 73      endcase
 74   end
 75
 76   // Latch onto new mask between strobes
 77   always @(posedge clk) if (cc_strobe == 0) fchan_mask_r <= fchan_mask;
 78
 79   fchan_subset #(
 80      .KEEP_OLD (1),
 81      .a_dw     (CFREQ_INW),
 82      .o_dw     (CFREQ_INW),
 83      .len      (n_chan))
 84   i_fchan_subset (
 85      .clk      (clk),
 86      .reset    (1'b0),
 87      .keep     (fchan_mask_r),
 88      .a_data   (cfreq_data),
 89      .a_gate   (cc_strobe),
 90      .a_trig   (~cc_strobe),
 91      .o_data   (cfreq_din),
 92      .o_gate   (cfreq_valid),
 93      .o_trig   (),
 94      .time_err (fchan_time_err)
 95   );
 96
 97   wire [23:0] square_sum_out;
 98   wire square_sum_valid;
 99   complex_freq #(
100      .refcnt_w(refcnt_w))
101   i_complex_freq (
102      .clk        (clk),
103      .sdata      (cfreq_din),
104      .sgate      (cfreq_valid),
105      .freq       (reg_freq),
106      .freq_valid (reg_freq_valid),
107      .amp_max    (reg_amp_max),
108      .amp_min    (reg_amp_min),
109      .updated    (reg_updated),
110      .timing_err (cfreq_time_err),
111      .square_sum_out   (square_sum_out),
112      .square_sum_valid (square_sum_valid)
113   );
114
115   // First-order CIC filter of square_sum
116   localparam square_sum_ex=15;  // average and decimate by 2^square_sum_ex
117   cic_simple_us #(.dw(24), .ex(square_sum_ex)) cic(.clk(clk),
118      .data_in(square_sum_out), .data_in_gate(square_sum_valid),
119      .roll(1'b0),
120      .data_out(avg_power), .data_out_gate(avg_power_strobe)
121   );
122
123   assign reg_timing_err = cfreq_time_err | fchan_time_err;
124
125endmodule