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