Attention
This documentation is a work in progress. Expect to see errors and unfinished things.
iq_deinterleaver Source File
1`timescale 1ns / 1ns
2
3/** IQ_DEINTERLEAVER **
4 Deinterleave an IQ stream into separate I and Q components.
5 scale input allows IQ data to be scaled down by a non-binary factor, which
6 can be used to match the scaling of downconverted channels
7
8 I_OUT = (I_IN*scale) >> (scale_wi-davr-1)
9*/
10
11module iq_deinterleaver #(
12 parameter scale_wi = 18, // Width of scale input and downscale factor
13 parameter dwi = 16, // Width of iq stream
14 parameter davr = 4 // Guard bits to keep at output of scale multiplication
15) (
16 input clk,
17 input signed [scale_wi-1:0] scale_in, // Scaling factor; scale is typically positive;
18 // full-scale negative is not allowed
19 input signed [dwi-1:0] iq_data_in, // IQ interleaved data
20 input iq_sel, // 1 (I), 0 (Q)
21 output valid_out,
22 output [dwi+davr-1:0] i_data_out,
23 output [dwi+davr-1:0] q_data_out
24);
25 localparam SEL_I = 1, SEL_Q = 0;
26
27 reg signed [scale_wi+dwi-1:0] scaled_iq = 0, scaled_iq_r = 0;
28 wire signed [dwi+davr-1:0] scaled_iq_out;
29 reg [dwi+davr-1:0] i_data_l = 0, i_data = 0, q_data = 0;
30 reg iq_sel_r = 0, iq_sel_r2 = 0;
31 reg valid_r = 0, valid_r2 = 0;
32
33 // Use a multiplier so we can get full-scale to match between
34 // input and output when using a non-binary CIC interval
35 always @(posedge clk) begin
36 scaled_iq <= iq_data_in * scale_in;
37 iq_sel_r <= iq_sel;
38 scaled_iq_r <= scaled_iq;
39 iq_sel_r2 <= iq_sel_r;
40 end
41
42 // Drop sign bit and shift down TODO: Explain this operation, especially -1
43 assign scaled_iq_out = scaled_iq_r[scale_wi+dwi-2:scale_wi-davr-1];
44
45 always @(posedge clk) begin
46 case (iq_sel_r2)
47 SEL_I : i_data_l <= scaled_iq_out;
48 SEL_Q : q_data <= scaled_iq_out;
49 endcase
50
51 valid_r <= iq_sel_r2==SEL_I ? 1'b1 : 1'b0;
52
53 i_data <= i_data_l; // Time-align the common case where I and Q are paired
54 valid_r2 <= valid_r;
55 end
56
57 assign valid_out = valid_r2;
58 assign i_data_out = i_data;
59 assign q_data_out = q_data;
60
61endmodule