aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/top/x400/rf/200m/rf_up_2to4.v
blob: 0cabf346eb5ed9855f38eda2186d7b6392b06eae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//
// Copyright 2021 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: rf_up_2to4
//
// Description:
//
//   Implements an up-sampling filter that accepts 2 samples per cycle on the
//   input and outputs 4 samples per cycle. A 2x speed clock is used to perform
//   the DSP computation, so that less logic can be used to implement the
//   half-band filter.
//
//     Data Path  :  In --> Gearbox --> Filter --> Gearbox --> Out
//     SPC        :     2           1          2           4
//     Clock Rate :     1x          2x         2x          1x
//

`default_nettype none

module rf_up_2to4 #(
  parameter NUM_CHANNELS = 1
) (
  input  wire clk,
  input  wire clk_2x,

  // Synchronous resets
  input  wire rst,
  input  wire rst_2x,

  // Input - 2 SPC, synchronous to "clk"
  input  wire [NUM_CHANNELS*64-1:0] i_tdata,
  input  wire [NUM_CHANNELS* 1-1:0] i_tvalid,

  // Output - 4 SPC, synchronous to "clk"
  output wire [NUM_CHANNELS*128-1:0] o_tdata,
  output wire [NUM_CHANNELS*  1-1:0] o_tvalid
);

  generate
    genvar ch;
    for (ch = 0; ch < NUM_CHANNELS; ch = ch + 1) begin : gen_channel

      //-----------------------------------------------------------------------
      // Input Gearbox
      //-----------------------------------------------------------------------
      //
      // Convert from 2 SPC on clk to 1 SPC on clk_2x.
      //
      //-----------------------------------------------------------------------

      wire [31:0] gear_to_filt_tdata;
      wire        gear_to_filt_tvalid;

      gearbox_2x1 #(
        .WORD_W     (32),
        .IN_WORDS   (2),
        .OUT_WORDS  (1),
        .BIG_ENDIAN (0)
      ) gearbox_2x1_in (
        .i_clk    (clk),
        .i_rst    (rst),
        .i_tdata  (i_tdata[ch*64 +: 64]),
        .i_tvalid (i_tvalid[ch]),
        .o_clk    (clk_2x),
        .o_rst    (rst_2x),
        .o_tdata  (gear_to_filt_tdata),
        .o_tvalid (gear_to_filt_tvalid)
      );


      //-----------------------------------------------------------------------
      // Interpolating Filter
      //-----------------------------------------------------------------------

      wire [95:0] filt_to_clip_tdata;
      wire        filt_to_clip_tvalid;

      hb47_1to2 hb47_1to2_i (
        .aresetn            (~rst_2x),
        .aclk               (clk_2x),
        .s_axis_data_tvalid (gear_to_filt_tvalid),
        .s_axis_data_tready (),
        .s_axis_data_tdata  (gear_to_filt_tdata),
        .m_axis_data_tvalid (filt_to_clip_tvalid),
        .m_axis_data_tuser  (),
        .m_axis_data_tdata  (filt_to_clip_tdata)
      );


      //-----------------------------------------------------------------------
      // Saturation
      //-----------------------------------------------------------------------

      wire [63:0] clip_to_gear_tdata;
      wire        clip_to_gear_tvalid;

      genvar word;
      for (word = 0; word < 4; word = word+1) begin : gen_sat
        axi_clip #(
          .WIDTH_IN  (24),
          .WIDTH_OUT (16),
          .FIFOSIZE  (0)
        ) axi_clip_i (
          .clk      (clk_2x),
          .reset    (rst_2x),
          .i_tdata  (filt_to_clip_tdata[word*24 +: 24]),
          .i_tlast  (1'b0),
          .i_tvalid (filt_to_clip_tvalid),
          .i_tready (),
          .o_tdata  (clip_to_gear_tdata[word*16 +: 16]),
          .o_tlast  (),
          .o_tvalid (clip_to_gear_tvalid),
          .o_tready (1'b1)
        );
      end


      //-----------------------------------------------------------------------
      // Output Gearbox
      //-----------------------------------------------------------------------
      //
      // Convert from 2 SPC on clk_2x to 4 SPC on clk.
      //
      //-----------------------------------------------------------------------

      gearbox_2x1 #(
        .WORD_W     (32),
        .IN_WORDS   (2),
        .OUT_WORDS  (4),
        .BIG_ENDIAN (0)
      ) gearbox_2x1_out (
        .i_clk    (clk_2x),
        .i_rst    (rst_2x),
        .i_tdata  (clip_to_gear_tdata),
        .i_tvalid (clip_to_gear_tvalid),
        .o_clk    (clk),
        .o_rst    (rst),
        .o_tdata  (o_tdata[ch*128 +: 128]),
        .o_tvalid (o_tvalid[ch])
      );

    end // for
  endgenerate

endmodule

`default_nettype wire