1// 2// Copyright 2020 Ettus Research, a National Instruments Brand 3// 4// SPDX-License-Identifier: LGPL-3.0-or-later 5// 6// Module: rfnoc_block_vector_iir 7// 8// Description: 9// 10// This module implements an IIR filter with a variable length delay line. 11// Transfer Function: 12// beta 13// H(z) = ------------------ 14// 1 - alpha*z^-delay 15// Where: 16// - beta is the feedforward tap 17// - alpha is the feedback tap 18// - delay is the feedback tap delay 19// 20// Parameters: 21// 22// THIS_PORTID : Control crossbar port to which this block is connected 23// CHDR_W : AXIS-CHDR data bus width 24// MTU : Maximum transmission unit (i.e., maximum packet size in 25// CHDR words is 2**MTU). 26// NUM_PORTS : Number of Vector IIR instances to instantiate 27// MAX_DELAY : The maximum supported filter delay. This should correspond 28// to the maximum SPP. Optimal values are a power of two, minus 29// one (e.g, 2047). 30// 31 32`default_nettype none 33 34 35module rfnoc_block_vector_iir #( 36 parameter [9:0] THIS_PORTID = 10'd0, 37 parameter CHDR_W = 64, 38 parameter [5:0] MTU = 10, 39 parameter NUM_PORTS = 1, 40 parameter MAX_DELAY = (2**MTU*CHDR_W/32-1) 41) ( 42 // RFNoC Framework Clocks and Resets 43 input wire rfnoc_chdr_clk, 44 input wire rfnoc_ctrl_clk, 45 input wire ce_clk, 46 // RFNoC Backend Interface 47 input wire [ 511:0] rfnoc_core_config, 48 output wire [ 511:0] rfnoc_core_status, 49 // AXIS-CHDR Input Ports (from framework) 50 input wire [(0+NUM_PORTS)*CHDR_W-1:0] s_rfnoc_chdr_tdata, 51 input wire [ (0+NUM_PORTS)-1:0] s_rfnoc_chdr_tlast, 52 input wire [ (0+NUM_PORTS)-1:0] s_rfnoc_chdr_tvalid, 53 output wire [ (0+NUM_PORTS)-1:0] s_rfnoc_chdr_tready, 54 // AXIS-CHDR Output Ports (to framework) 55 output wire [(0+NUM_PORTS)*CHDR_W-1:0] m_rfnoc_chdr_tdata, 56 output wire [ (0+NUM_PORTS)-1:0] m_rfnoc_chdr_tlast, 57 output wire [ (0+NUM_PORTS)-1:0] m_rfnoc_chdr_tvalid, 58 input wire [ (0+NUM_PORTS)-1:0] m_rfnoc_chdr_tready, 59 // AXIS-Ctrl Input Port (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 // AXIS-Ctrl Output Port (to framework) 65 output wire [ 31:0] m_rfnoc_ctrl_tdata, 66 output wire m_rfnoc_ctrl_tlast, 67 output wire m_rfnoc_ctrl_tvalid, 68 input wire m_rfnoc_ctrl_tready 69); 70 71 `include "rfnoc_block_vector_iir_regs.vh" 72 73 // Make sure MAX_DELAY isn't too big for REG_MAX_DELAY 74 if (MAX_DELAY >= 2**REG_MAX_DELAY_LEN) begin 75 MAX_DELAY_is_too_large_for_REG_MAX_DELAY(); 76 end 77 78 79 //--------------------------------------------------------------------------- 80 // Signal Declarations 81 //--------------------------------------------------------------------------- 82 83 // CtrlPort Master 84 wire m_ctrlport_req_wr; 85 wire m_ctrlport_req_rd; 86 wire [19:0] m_ctrlport_req_addr; 87 wire [31:0] m_ctrlport_req_data; 88 wire m_ctrlport_resp_ack; 89 wire [31:0] m_ctrlport_resp_data; 90 // Payload Stream to User Logic: in 91 wire [NUM_PORTS*32*1-1:0] m_in_payload_tdata; 92 wire [ NUM_PORTS-1:0] m_in_payload_tlast; 93 wire [ NUM_PORTS-1:0] m_in_payload_tvalid; 94 wire [ NUM_PORTS-1:0] m_in_payload_tready; 95 // Context Stream to User Logic: in 96 wire [NUM_PORTS*CHDR_W-1:0] m_in_context_tdata; 97 wire [ NUM_PORTS*4-1:0] m_in_context_tuser; 98 wire [ NUM_PORTS-1:0] m_in_context_tlast; 99 wire [ NUM_PORTS-1:0] m_in_context_tvalid; 100 wire [ NUM_PORTS-1:0] m_in_context_tready; 101 // Payload Stream to User Logic: out 102 wire [NUM_PORTS*32*1-1:0] s_out_payload_tdata; 103 wire [ NUM_PORTS-1:0] s_out_payload_tlast; 104 wire [ NUM_PORTS-1:0] s_out_payload_tvalid; 105 wire [ NUM_PORTS-1:0] s_out_payload_tready; 106 // Context Stream to User Logic: out 107 wire [NUM_PORTS*CHDR_W-1:0] s_out_context_tdata; 108 wire [ NUM_PORTS*4-1:0] s_out_context_tuser; 109 wire [ NUM_PORTS-1:0] s_out_context_tlast; 110 wire [ NUM_PORTS-1:0] s_out_context_tvalid; 111 wire [ NUM_PORTS-1:0] s_out_context_tready; 112 113 114 //--------------------------------------------------------------------------- 115 // NoC Shell 116 //--------------------------------------------------------------------------- 117 118 wire ce_rst; 119 120 noc_shell_vector_iir #( 121 .CHDR_W (CHDR_W), 122 .THIS_PORTID (THIS_PORTID), 123 .MTU (MTU), 124 .NUM_PORTS (NUM_PORTS) 125 ) noc_shell_vector_iir_i ( 126 //--------------------- 127 // Framework Interface 128 //--------------------- 129 130 // Clock Inputs 131 .rfnoc_chdr_clk (rfnoc_chdr_clk), 132 .rfnoc_ctrl_clk (rfnoc_ctrl_clk), 133 .ce_clk (ce_clk), 134 // Reset Outputs 135 .rfnoc_chdr_rst (), 136 .rfnoc_ctrl_rst (), 137 .ce_rst (ce_rst), 138 // RFNoC Backend Interface 139 .rfnoc_core_config (rfnoc_core_config), 140 .rfnoc_core_status (rfnoc_core_status), 141 // CHDR Input Ports (from framework) 142 .s_rfnoc_chdr_tdata (s_rfnoc_chdr_tdata), 143 .s_rfnoc_chdr_tlast (s_rfnoc_chdr_tlast), 144 .s_rfnoc_chdr_tvalid (s_rfnoc_chdr_tvalid), 145 .s_rfnoc_chdr_tready (s_rfnoc_chdr_tready), 146 // CHDR Output Ports (to framework) 147 .m_rfnoc_chdr_tdata (m_rfnoc_chdr_tdata), 148 .m_rfnoc_chdr_tlast (m_rfnoc_chdr_tlast), 149 .m_rfnoc_chdr_tvalid (m_rfnoc_chdr_tvalid), 150 .m_rfnoc_chdr_tready (m_rfnoc_chdr_tready), 151 // AXIS-Ctrl Input Port (from framework) 152 .s_rfnoc_ctrl_tdata (s_rfnoc_ctrl_tdata), 153 .s_rfnoc_ctrl_tlast (s_rfnoc_ctrl_tlast), 154 .s_rfnoc_ctrl_tvalid (s_rfnoc_ctrl_tvalid), 155 .s_rfnoc_ctrl_tready (s_rfnoc_ctrl_tready), 156 // AXIS-Ctrl Output Port (to framework) 157 .m_rfnoc_ctrl_tdata (m_rfnoc_ctrl_tdata), 158 .m_rfnoc_ctrl_tlast (m_rfnoc_ctrl_tlast), 159 .m_rfnoc_ctrl_tvalid (m_rfnoc_ctrl_tvalid), 160 .m_rfnoc_ctrl_tready (m_rfnoc_ctrl_tready), 161 162 //--------------------- 163 // Client Interface 164 //--------------------- 165 166 // CtrlPort Clock and Reset 167 .ctrlport_clk (), 168 .ctrlport_rst (), 169 // CtrlPort Master 170 .m_ctrlport_req_wr (m_ctrlport_req_wr), 171 .m_ctrlport_req_rd (m_ctrlport_req_rd), 172 .m_ctrlport_req_addr (m_ctrlport_req_addr), 173 .m_ctrlport_req_data (m_ctrlport_req_data), 174 .m_ctrlport_resp_ack (m_ctrlport_resp_ack), 175 .m_ctrlport_resp_data (m_ctrlport_resp_data), 176 177 // AXI-Stream Payload Context Clock and Reset 178 .axis_data_clk (), 179 .axis_data_rst (), 180 // Payload Stream to User Logic: in 181 .m_in_payload_tdata (m_in_payload_tdata), 182 .m_in_payload_tkeep (), 183 .m_in_payload_tlast (m_in_payload_tlast), 184 .m_in_payload_tvalid (m_in_payload_tvalid), 185 .m_in_payload_tready (m_in_payload_tready), 186 // Context Stream to User Logic: in 187 .m_in_context_tdata (m_in_context_tdata), 188 .m_in_context_tuser (m_in_context_tuser), 189 .m_in_context_tlast (m_in_context_tlast), 190 .m_in_context_tvalid (m_in_context_tvalid), 191 .m_in_context_tready (m_in_context_tready), 192 // Payload Stream from User Logic: out 193 .s_out_payload_tdata (s_out_payload_tdata), 194 .s_out_payload_tkeep (), 195 .s_out_payload_tlast (s_out_payload_tlast), 196 .s_out_payload_tvalid (s_out_payload_tvalid), 197 .s_out_payload_tready (s_out_payload_tready), 198 // Context Stream from User Logic: out 199 .s_out_context_tdata (s_out_context_tdata), 200 .s_out_context_tuser (s_out_context_tuser), 201 .s_out_context_tlast (s_out_context_tlast), 202 .s_out_context_tvalid (s_out_context_tvalid), 203 .s_out_context_tready (s_out_context_tready) 204 ); 205 206 // Context is not used because output packets have the same format as input 207 // packets, so we pass through the context unchanged. 208 assign s_out_context_tdata = m_in_context_tdata; 209 assign s_out_context_tuser = m_in_context_tuser; 210 assign s_out_context_tlast = m_in_context_tlast; 211 assign s_out_context_tvalid = m_in_context_tvalid; 212 assign m_in_context_tready = s_out_context_tready; 213 214 215 //--------------------------------------------------------------------------- 216 // CtrlPort Splitter 217 //--------------------------------------------------------------------------- 218 219 wire [NUM_PORTS* 1-1:0] dec_ctrlport_req_wr; 220 wire [NUM_PORTS* 1-1:0] dec_ctrlport_req_rd; 221 wire [NUM_PORTS*20-1:0] dec_ctrlport_req_addr; 222 wire [NUM_PORTS*32-1:0] dec_ctrlport_req_data; 223 wire [NUM_PORTS* 1-1:0] dec_ctrlport_resp_ack; 224 wire [NUM_PORTS*32-1:0] dec_ctrlport_resp_data; 225 226 ctrlport_decoder #( 227 .NUM_SLAVES (NUM_PORTS), 228 .SLAVE_ADDR_W (VECTOR_IIR_ADDR_W) 229 ) ctrlport_decoder_i ( 230 .ctrlport_clk (ce_clk), 231 .ctrlport_rst (ce_rst), 232 .s_ctrlport_req_wr (m_ctrlport_req_wr), 233 .s_ctrlport_req_rd (m_ctrlport_req_rd), 234 .s_ctrlport_req_addr (m_ctrlport_req_addr), 235 .s_ctrlport_req_data (m_ctrlport_req_data), 236 .s_ctrlport_req_byte_en (4'hF), 237 .s_ctrlport_req_has_time (1'b0), 238 .s_ctrlport_req_time (64'b0), 239 .s_ctrlport_resp_ack (m_ctrlport_resp_ack), 240 .s_ctrlport_resp_status (), 241 .s_ctrlport_resp_data (m_ctrlport_resp_data), 242 .m_ctrlport_req_wr (dec_ctrlport_req_wr), 243 .m_ctrlport_req_rd (dec_ctrlport_req_rd), 244 .m_ctrlport_req_addr (dec_ctrlport_req_addr), 245 .m_ctrlport_req_data (dec_ctrlport_req_data), 246 .m_ctrlport_req_byte_en (), 247 .m_ctrlport_req_has_time (), 248 .m_ctrlport_req_time (), 249 .m_ctrlport_resp_ack (dec_ctrlport_resp_ack), 250 .m_ctrlport_resp_status ({NUM_PORTS{2'b0}}), 251 .m_ctrlport_resp_data (dec_ctrlport_resp_data) 252 ); 253 254 255 //--------------------------------------------------------------------------- 256 // Port Instances 257 //--------------------------------------------------------------------------- 258 259 genvar port; 260 generate 261 for (port = 0; port < NUM_PORTS; port = port+1) begin : gen_ports 262 263 //----------------------------------------------------------------------- 264 // Signal Selection 265 //----------------------------------------------------------------------- 266 // 267 // Grab the appropriate CtrlPort and AXIS payload signals for this port. 268 // 269 //----------------------------------------------------------------------- 270 271 wire ctrlport_req_wr; 272 wire ctrlport_req_rd; 273 wire [19:0] ctrlport_req_addr; 274 wire [31:0] ctrlport_req_data; 275 reg ctrlport_resp_ack; 276 reg [31:0] ctrlport_resp_data; 277 278 assign ctrlport_req_wr = dec_ctrlport_req_wr[port]; 279 assign ctrlport_req_rd = dec_ctrlport_req_rd[port]; 280 assign ctrlport_req_addr = dec_ctrlport_req_addr[port*20 +: 20]; 281 assign ctrlport_req_data = dec_ctrlport_req_data[port*32 +: 32]; 282 // 283 assign dec_ctrlport_resp_ack[port] = ctrlport_resp_ack; 284 assign dec_ctrlport_resp_data[port*32 +: 32] = ctrlport_resp_data; 285 286 wire [31:0] in_tdata; 287 wire in_tlast; 288 wire in_tvalid; 289 wire in_tready; 290 wire [31:0] out_tdata; 291 wire out_tlast; 292 wire out_tvalid; 293 wire out_tready; 294 295 assign in_tdata = m_in_payload_tdata [port*32 +: 32]; 296 assign in_tlast = m_in_payload_tlast [port]; 297 assign in_tvalid = m_in_payload_tvalid[port]; 298 assign m_in_payload_tready[port] = in_tready; 299 // 300 assign s_out_payload_tdata [port*32+:32] = out_tdata; 301 assign s_out_payload_tlast [ port] = out_tlast; 302 assign s_out_payload_tvalid[ port] = out_tvalid; 303 assign out_tready = s_out_payload_tready[port]; 304 305 306 //----------------------------------------------------------------------- 307 // Registers 308 //----------------------------------------------------------------------- 309 310 reg [$clog2(MAX_DELAY+1)-1:0] reg_delay; 311 reg [ REG_ALPHA_LEN-1:0] reg_alpha; 312 reg [ REG_BETA_LEN-1:0] reg_beta; 313 314 reg reg_changed; 315 316 always @(posedge ce_clk) begin 317 if (ce_rst) begin 318 reg_delay <= 'bX; 319 reg_alpha <= 'bX; 320 reg_beta <= 'bX; 321 reg_changed <= 1'b0; 322 end else begin 323 // Default assignments 324 ctrlport_resp_ack <= 1'b0; 325 ctrlport_resp_data <= 32'b0; 326 reg_changed <= 1'b0; 327 328 //----------------------------------------- 329 // Register Reads 330 //----------------------------------------- 331 332 if (ctrlport_req_rd) begin 333 ctrlport_resp_ack <= 1; 334 case (ctrlport_req_addr) 335 REG_DELAY : begin 336 ctrlport_resp_data[REG_MAX_DELAY_POS +: REG_DELAY_LEN] <= MAX_DELAY; 337 ctrlport_resp_data[REG_DELAY_POS +: REG_DELAY_LEN] <= reg_delay; 338 end 339 REG_ALPHA : 340 ctrlport_resp_data[REG_ALPHA_POS +: REG_ALPHA_LEN] <= reg_alpha; 341 REG_BETA : 342 ctrlport_resp_data[REG_BETA_POS +: REG_BETA_LEN] <= reg_beta; 343 endcase 344 345 //----------------------------------------- 346 // Register Writes 347 //----------------------------------------- 348 349 end else if (ctrlport_req_wr) begin 350 ctrlport_resp_ack <= 1; 351 case (ctrlport_req_addr) 352 REG_DELAY : begin 353 reg_delay <= ctrlport_req_data[REG_DELAY_POS +: REG_DELAY_LEN]; 354 reg_changed <= 1'b1; 355 end 356 REG_ALPHA : begin 357 reg_alpha <= ctrlport_req_data[REG_ALPHA_POS +: REG_ALPHA_LEN]; 358 reg_changed <= 1'b1; 359 end 360 REG_BETA : begin 361 reg_beta <= ctrlport_req_data[REG_BETA_POS +: REG_BETA_LEN]; 362 reg_changed <= 1'b1; 363 end 364 endcase 365 end 366 end 367 end 368 369 370 //----------------------------------------------------------------------- 371 // Vector IIR Block 372 //----------------------------------------------------------------------- 373 374 vector_iir #( 375 .MAX_VECTOR_LEN (MAX_DELAY), 376 .ALPHA_W (REG_ALPHA_LEN), 377 .BETA_W (REG_BETA_LEN) 378 ) inst_vector_iir ( 379 .clk (ce_clk), 380 .reset (ce_rst | reg_changed), 381 .set_vector_len (reg_delay), 382 .set_alpha (reg_alpha), 383 .set_beta (reg_beta), 384 .i_tdata (in_tdata), 385 .i_tlast (in_tlast), 386 .i_tvalid (in_tvalid), 387 .i_tready (in_tready), 388 .o_tdata (out_tdata), 389 .o_tlast (out_tlast), 390 .o_tvalid (out_tvalid), 391 .o_tready (out_tready) 392 ); 393 394 end 395 endgenerate 396 397endmodule // rfnoc_block_vector_iir 398 399 400`default_nettype wire 401