1// 2// Copyright 2019 Ettus Research, a National Instruments Company 3// Copyright 2020 Ettus Research, a National Instruments Brand 4// 5// SPDX-License-Identifier: LGPL-3.0-or-later 6// 7// Module: rfnoc_block_duc 8// 9// Description: An digital up-converter block for RFNoC. 10// 11// Parameters: 12// 13// THIS_PORTID : Control crossbar port to which this block is connected 14// CHDR_W : AXIS CHDR interface data width 15// NUM_PORTS : Number of DUC signal processing chains 16// MTU : Maximum transmission unit (i.e., maximum packet size) in 17// CHDR words is 2**MTU. 18// NUM_HB : Number of half-band filter blocks to include (0-3) 19// CIC_MAX_INTERP : Maximum interpolation to support in the CIC filter 20// 21 22module rfnoc_block_duc #( 23 parameter THIS_PORTID = 0, 24 parameter CHDR_W = 64, 25 parameter NUM_PORTS = 2, 26 parameter MTU = 10, 27 parameter NUM_HB = 2, 28 parameter CIC_MAX_INTERP = 128 29) ( 30 //--------------------------------------------------------------------------- 31 // AXIS CHDR Port 32 //--------------------------------------------------------------------------- 33 34 input wire rfnoc_chdr_clk, 35 input wire ce_clk, 36 37 // CHDR inputs from framework 38 input wire [NUM_PORTS*CHDR_W-1:0] s_rfnoc_chdr_tdata, 39 input wire [ NUM_PORTS-1:0] s_rfnoc_chdr_tlast, 40 input wire [ NUM_PORTS-1:0] s_rfnoc_chdr_tvalid, 41 output wire [ NUM_PORTS-1:0] s_rfnoc_chdr_tready, 42 43 // CHDR outputs to framework 44 output wire [NUM_PORTS*CHDR_W-1:0] m_rfnoc_chdr_tdata, 45 output wire [ NUM_PORTS-1:0] m_rfnoc_chdr_tlast, 46 output wire [ NUM_PORTS-1:0] m_rfnoc_chdr_tvalid, 47 input wire [ NUM_PORTS-1:0] m_rfnoc_chdr_tready, 48 49 // Backend interface 50 input wire [511:0] rfnoc_core_config, 51 output wire [511:0] rfnoc_core_status, 52 53 //--------------------------------------------------------------------------- 54 // AXIS CTRL Port 55 //--------------------------------------------------------------------------- 56 57 input wire rfnoc_ctrl_clk, 58 59 // CTRL port requests from framework 60 input wire [31:0] s_rfnoc_ctrl_tdata, 61 input wire s_rfnoc_ctrl_tlast, 62 input wire s_rfnoc_ctrl_tvalid, 63 output wire s_rfnoc_ctrl_tready, 64 65 // CTRL port requests to framework 66 output wire [31:0] m_rfnoc_ctrl_tdata, 67 output wire m_rfnoc_ctrl_tlast, 68 output wire m_rfnoc_ctrl_tvalid, 69 input wire m_rfnoc_ctrl_tready 70); 71 72 // These are the only supported values for now 73 localparam ITEM_W = 32; 74 localparam NIPC = 1; 75 76 localparam COMPAT_MAJOR = 16'h0; 77 localparam COMPAT_MINOR = 16'h1; 78 79 `include "rfnoc_block_duc_regs.vh" 80 `include "../../core/rfnoc_axis_ctrl_utils.vh" 81 82 83 //--------------------------------------------------------------------------- 84 // Signal Declarations 85 //--------------------------------------------------------------------------- 86 87 wire ctrlport_req_wr; 88 wire ctrlport_req_rd; 89 wire [19:0] ctrlport_req_addr; 90 wire [31:0] ctrlport_req_data; 91 wire ctrlport_req_has_time; 92 wire [63:0] ctrlport_req_time; 93 wire ctrlport_resp_ack; 94 wire [31:0] ctrlport_resp_data; 95 96 wire [NUM_PORTS*ITEM_W-1:0] m_axis_data_tdata; 97 wire [ NUM_PORTS-1:0] m_axis_data_tlast; 98 wire [ NUM_PORTS-1:0] m_axis_data_tvalid; 99 wire [ NUM_PORTS-1:0] m_axis_data_tready; 100 wire [ NUM_PORTS*64-1:0] m_axis_data_ttimestamp; 101 wire [ NUM_PORTS-1:0] m_axis_data_thas_time; 102 wire [ NUM_PORTS*16-1:0] m_axis_data_tlength; 103 wire [ NUM_PORTS-1:0] m_axis_data_teob; 104 wire [ NUM_PORTS*128-1:0] m_axis_data_tuser; 105 106 wire [NUM_PORTS*ITEM_W-1:0] s_axis_data_tdata; 107 wire [ NUM_PORTS-1:0] s_axis_data_tlast; 108 wire [ NUM_PORTS-1:0] s_axis_data_tvalid; 109 wire [ NUM_PORTS-1:0] s_axis_data_tready; 110 wire [ NUM_PORTS*128-1:0] s_axis_data_tuser; 111 wire [ NUM_PORTS-1:0] s_axis_data_teob; 112 wire [ NUM_PORTS*64-1:0] s_axis_data_ttimestamp; 113 wire [ NUM_PORTS-1:0] s_axis_data_thas_time; 114 115 116 //--------------------------------------------------------------------------- 117 // NoC Shell 118 //--------------------------------------------------------------------------- 119 120 wire ce_rst; 121 122 noc_shell_duc #( 123 .THIS_PORTID (THIS_PORTID), 124 .CHDR_W (CHDR_W), 125 .MTU (MTU), 126 .NUM_PORTS (NUM_PORTS) 127 ) noc_shell_duc_i ( 128 .rfnoc_chdr_clk (rfnoc_chdr_clk), 129 .rfnoc_ctrl_clk (rfnoc_ctrl_clk), 130 .ce_clk (ce_clk), 131 .rfnoc_chdr_rst (), 132 .rfnoc_ctrl_rst (), 133 .ce_rst (ce_rst), 134 .rfnoc_core_config (rfnoc_core_config), 135 .rfnoc_core_status (rfnoc_core_status), 136 .s_rfnoc_chdr_tdata (s_rfnoc_chdr_tdata), 137 .s_rfnoc_chdr_tlast (s_rfnoc_chdr_tlast), 138 .s_rfnoc_chdr_tvalid (s_rfnoc_chdr_tvalid), 139 .s_rfnoc_chdr_tready (s_rfnoc_chdr_tready), 140 .m_rfnoc_chdr_tdata (m_rfnoc_chdr_tdata), 141 .m_rfnoc_chdr_tlast (m_rfnoc_chdr_tlast), 142 .m_rfnoc_chdr_tvalid (m_rfnoc_chdr_tvalid), 143 .m_rfnoc_chdr_tready (m_rfnoc_chdr_tready), 144 .s_rfnoc_ctrl_tdata (s_rfnoc_ctrl_tdata), 145 .s_rfnoc_ctrl_tlast (s_rfnoc_ctrl_tlast), 146 .s_rfnoc_ctrl_tvalid (s_rfnoc_ctrl_tvalid), 147 .s_rfnoc_ctrl_tready (s_rfnoc_ctrl_tready), 148 .m_rfnoc_ctrl_tdata (m_rfnoc_ctrl_tdata), 149 .m_rfnoc_ctrl_tlast (m_rfnoc_ctrl_tlast), 150 .m_rfnoc_ctrl_tvalid (m_rfnoc_ctrl_tvalid), 151 .m_rfnoc_ctrl_tready (m_rfnoc_ctrl_tready), 152 .ctrlport_clk (), 153 .ctrlport_rst (), 154 .m_ctrlport_req_wr (ctrlport_req_wr), 155 .m_ctrlport_req_rd (ctrlport_req_rd), 156 .m_ctrlport_req_addr (ctrlport_req_addr), 157 .m_ctrlport_req_data (ctrlport_req_data), 158 .m_ctrlport_req_has_time (ctrlport_req_has_time), 159 .m_ctrlport_req_time (ctrlport_req_time), 160 .m_ctrlport_resp_ack (ctrlport_resp_ack), 161 .m_ctrlport_resp_data (ctrlport_resp_data), 162 .axis_data_clk (), 163 .axis_data_rst (), 164 .m_in_axis_tdata (m_axis_data_tdata), 165 .m_in_axis_tkeep (), 166 .m_in_axis_tlast (m_axis_data_tlast), 167 .m_in_axis_tvalid (m_axis_data_tvalid), 168 .m_in_axis_tready (m_axis_data_tready), 169 .m_in_axis_ttimestamp (m_axis_data_ttimestamp), 170 .m_in_axis_thas_time (m_axis_data_thas_time), 171 .m_in_axis_tlength (m_axis_data_tlength), 172 .m_in_axis_teov (), 173 .m_in_axis_teob (m_axis_data_teob), 174 .s_out_axis_tdata (s_axis_data_tdata), 175 .s_out_axis_tkeep ({NUM_PORTS*NIPC{1'b1}}), 176 .s_out_axis_tlast (s_axis_data_tlast), 177 .s_out_axis_tvalid (s_axis_data_tvalid), 178 .s_out_axis_tready (s_axis_data_tready), 179 .s_out_axis_ttimestamp (s_axis_data_ttimestamp), 180 .s_out_axis_thas_time (s_axis_data_thas_time), 181 .s_out_axis_teov ({NUM_PORTS{1'b0}}), 182 .s_out_axis_teob (s_axis_data_teob) 183 ); 184 185 186 //--------------------------------------------------------------------------- 187 // Register Translation 188 //--------------------------------------------------------------------------- 189 // 190 // Each DUC block is allocated an address spaces. This block translates CTRL 191 // port transactions in that space to settings bus. 192 // 193 //--------------------------------------------------------------------------- 194 195 wire [ 8*NUM_PORTS-1:0] set_addr; 196 wire [32*NUM_PORTS-1:0] set_data; 197 wire [ NUM_PORTS-1:0] set_has_time; 198 wire [ NUM_PORTS-1:0] set_stb; 199 wire [64*NUM_PORTS-1:0] set_time; 200 wire [ 8*NUM_PORTS-1:0] rb_addr; 201 reg [64*NUM_PORTS-1:0] rb_data; 202 203 ctrlport_to_settings_bus # ( 204 .NUM_PORTS (NUM_PORTS) 205 ) ctrlport_to_settings_bus_i ( 206 .ctrlport_clk (ce_clk), 207 .ctrlport_rst (ce_rst), 208 .s_ctrlport_req_wr (ctrlport_req_wr), 209 .s_ctrlport_req_rd (ctrlport_req_rd), 210 .s_ctrlport_req_addr (ctrlport_req_addr), 211 .s_ctrlport_req_data (ctrlport_req_data), 212 .s_ctrlport_req_has_time (ctrlport_req_has_time), 213 .s_ctrlport_req_time (ctrlport_req_time), 214 .s_ctrlport_resp_ack (ctrlport_resp_ack), 215 .s_ctrlport_resp_data (ctrlport_resp_data), 216 .set_data (set_data), 217 .set_addr (set_addr), 218 .set_stb (set_stb), 219 .set_time (set_time), 220 .set_has_time (set_has_time), 221 .rb_stb ({NUM_PORTS{1'b1}}), 222 .rb_addr (rb_addr), 223 .rb_data (rb_data), 224 .timestamp (64'b0) 225 ); 226 227 228 //--------------------------------------------------------------------------- 229 // DUC Implementation 230 //--------------------------------------------------------------------------- 231 232 // Unused signals 233 wire [ NUM_PORTS-1:0] clear_tx_seqnum = 0; 234 wire [16*NUM_PORTS-1:0] src_sid = 0; 235 wire [16*NUM_PORTS-1:0] next_dst_sid = 0; 236 237 localparam MAX_M = CIC_MAX_INTERP * 2<<(NUM_HB-1); 238 239 genvar i; 240 generate 241 for (i = 0; i < NUM_PORTS; i = i + 1) begin : gen_duc_chains 242 wire clear_user; 243 wire clear_duc = clear_tx_seqnum[i] | clear_user; 244 245 wire set_stb_int = set_stb[i]; 246 wire [7:0] set_addr_int = set_addr[8*i+7:8*i]; 247 wire [31:0] set_data_int = set_data[32*i+31:32*i]; 248 wire [63:0] set_time_int = set_time[64*i+63:64*i]; 249 wire set_has_time_int = set_has_time[i]; 250 251 // Build the expected tuser CHDR header 252 cvita_hdr_encoder cvita_hdr_encoder_i ( 253 .pkt_type (2'b0), 254 .eob (m_axis_data_teob[i]), 255 .has_time (m_axis_data_thas_time[i]), 256 .seqnum (12'b0), 257 .payload_length (m_axis_data_tlength[16*i +: 16]), 258 .src_sid (16'b0), 259 .dst_sid (16'b0), 260 .vita_time (m_axis_data_ttimestamp[64*i +: 64]), 261 .header (m_axis_data_tuser[128*i+:128]) 262 ); 263 264 // Extract bit fields from outgoing tuser CHDR header 265 assign s_axis_data_teob[i] = s_axis_data_tuser[128*i+124 +: 1]; 266 assign s_axis_data_thas_time[i] = s_axis_data_tuser[128*i+125 +: 1]; 267 assign s_axis_data_ttimestamp[64*i+:64] = s_axis_data_tuser[128*i+ 0 +: 64]; 268 269 // TODO Readback register for number of FIR filter taps 270 always @(*) begin 271 case(rb_addr[i*8+7:i*8]) 272 RB_COMPAT_NUM : rb_data[i*64+63:i*64] <= {COMPAT_MAJOR, COMPAT_MINOR}; 273 RB_NUM_HB : rb_data[i*64+63:i*64] <= NUM_HB; 274 RB_CIC_MAX_INTERP : rb_data[i*64+63:i*64] <= CIC_MAX_INTERP; 275 default : rb_data[i*64+63:i*64] <= 64'h0BADC0DE0BADC0DE; 276 endcase 277 end 278 279 //////////////////////////////////////////////////////////// 280 // 281 // Timed CORDIC 282 // - Implements timed cordic tunes. Placed between AXI Wrapper 283 // and AXI Rate Change due to it needing access to the 284 // vita time of the samples. 285 // 286 //////////////////////////////////////////////////////////// 287 wire [31:0] m_axis_rc_tdata; 288 wire m_axis_rc_tlast; 289 wire m_axis_rc_tvalid; 290 wire m_axis_rc_tready; 291 wire [127:0] m_axis_rc_tuser; 292 293 dds_timed #( 294 .SR_FREQ_ADDR(SR_FREQ_ADDR), 295 .SR_SCALE_IQ_ADDR(SR_SCALE_IQ_ADDR)) 296 dds_timed ( 297 .clk(ce_clk), .reset(ce_rst), .clear(clear_tx_seqnum[i]), 298 .timed_cmd_fifo_full(), 299 .set_stb(set_stb_int), .set_addr(set_addr_int), .set_data(set_data_int), 300 .set_time(set_time_int), .set_has_time(set_has_time_int), 301 .i_tdata(m_axis_rc_tdata), .i_tlast(m_axis_rc_tlast), .i_tvalid(m_axis_rc_tvalid), 302 .i_tready(m_axis_rc_tready), .i_tuser(m_axis_rc_tuser), 303 .o_tdata(s_axis_data_tdata[ITEM_W*i+:ITEM_W]), .o_tlast(s_axis_data_tlast[i]), .o_tvalid(s_axis_data_tvalid[i]), 304 .o_tready(s_axis_data_tready[i]), .o_tuser(s_axis_data_tuser[128*i+:128])); 305 306 //////////////////////////////////////////////////////////// 307 // 308 // Increase Rate 309 // 310 //////////////////////////////////////////////////////////// 311 wire [31:0] sample_tdata, sample_duc_tdata; 312 wire sample_tvalid, sample_tready; 313 wire sample_duc_tvalid, sample_duc_tready; 314 axi_rate_change #( 315 .WIDTH(32), 316 .MAX_N(1), 317 .MAX_M(MAX_M), 318 .SR_N_ADDR(SR_N_ADDR), 319 .SR_M_ADDR(SR_M_ADDR), 320 .SR_CONFIG_ADDR(SR_CONFIG_ADDR), 321 .SR_TIME_INCR_ADDR(SR_TIME_INCR_ADDR)) 322 axi_rate_change ( 323 .clk(ce_clk), .reset(ce_rst), .clear(clear_tx_seqnum[i]), .clear_user(clear_user), 324 .src_sid(src_sid[16*i+15:16*i]), .dst_sid(next_dst_sid[16*i+15:16*i]), 325 .set_stb(set_stb_int), .set_addr(set_addr_int), .set_data(set_data_int), 326 .i_tdata(m_axis_data_tdata[ITEM_W*i+:ITEM_W]), .i_tlast(m_axis_data_tlast[i]), .i_tvalid(m_axis_data_tvalid[i]), 327 .i_tready(m_axis_data_tready[i]), .i_tuser(m_axis_data_tuser[128*i+:128]), 328 .o_tdata(m_axis_rc_tdata), .o_tlast(m_axis_rc_tlast), .o_tvalid(m_axis_rc_tvalid), 329 .o_tready(m_axis_rc_tready), .o_tuser(m_axis_rc_tuser), 330 .m_axis_data_tdata({sample_tdata}), .m_axis_data_tlast(), .m_axis_data_tvalid(sample_tvalid), 331 .m_axis_data_tready(sample_tready), 332 .s_axis_data_tdata(sample_duc_tdata), .s_axis_data_tlast(1'b0), .s_axis_data_tvalid(sample_duc_tvalid), 333 .s_axis_data_tready(sample_duc_tready), 334 .warning_long_throttle(), .error_extra_outputs(), .error_drop_pkt_lockup()); 335 336 //////////////////////////////////////////////////////////// 337 // 338 // Digital Up Converter 339 // 340 //////////////////////////////////////////////////////////// 341 duc #( 342 .SR_INTERP_ADDR(SR_INTERP_ADDR), 343 .NUM_HB(NUM_HB), 344 .CIC_MAX_INTERP(CIC_MAX_INTERP)) 345 duc ( 346 .clk(ce_clk), .reset(ce_rst), .clear(clear_duc), 347 .set_stb(set_stb_int), .set_addr(set_addr_int), .set_data(set_data_int), 348 .i_tdata(sample_tdata), .i_tuser(128'b0), .i_tvalid(sample_tvalid), .i_tready(sample_tready), 349 .o_tdata(sample_duc_tdata), .o_tuser(), .o_tvalid(sample_duc_tvalid), .o_tready(sample_duc_tready)); 350 351 end 352 endgenerate 353 354endmodule 355