From c719cf140652d3307c2400547c17bbd7db2ece3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20K=C3=B6hler?= Date: Mon, 18 Mar 2024 11:53:38 +0100 Subject: [PATCH] fpga: rfnoc: reverse FIR filter coefficients to get embedded in DSPE48 Original-commit: ea164a936b924b05a5b4cb9dd50df8acc3700c1a --- lib/rfnoc/axi_fir_filter.v | 43 ++++++++++--------- .../noc_shell_fir_filter.v | 2 +- .../rfnoc_block_fir_filter_tb.sv | 6 +-- .../rfnoc_fir_filter_core.v | 5 +++ .../rfnoc_fir_filter_regs.vh | 12 +++++- lib/rfnoc/fir_filter_slice.v | 12 +++--- 6 files changed, 47 insertions(+), 33 deletions(-) diff --git a/lib/rfnoc/axi_fir_filter.v b/lib/rfnoc/axi_fir_filter.v index 5c63b1d..d9a60df 100644 --- a/lib/rfnoc/axi_fir_filter.v +++ b/lib/rfnoc/axi_fir_filter.v @@ -33,6 +33,7 @@ // Notes: // - If using USE_EMBEDDED_REGS_COEFFS, coefficients must be written at least once as COEFFS_VEC is ignored! // - If using SYMMETRIC_COEFFS, only send half the coeffients! i.e. NUM_COEFFS = 11, send the first 6. +// - If using RELOADABLE_COEFFS, coefficients must be written in reverse order! // module axi_fir_filter #( parameter IN_WIDTH = 16, @@ -106,9 +107,9 @@ module axi_fir_filter #( end else begin if (s_axis_reload_tvalid & s_axis_reload_tready) begin for (k = NUM_SLICES-1; k > 0; k = k - 1) begin - coeffs[k-1] <= coeffs[k]; + coeffs[k] <= coeffs[k-1]; end - coeffs[NUM_SLICES-1] <= s_axis_reload_tdata; + coeffs[0] <= s_axis_reload_tdata; end coeff_load_stb <= s_axis_reload_tvalid & s_axis_reload_tready & s_axis_reload_tlast; end @@ -156,18 +157,18 @@ module axi_fir_filter #( // | | // v v // +-----+ +-----+ - // *----------------------* | | | | - // | Note: Coeffs are | +-----+ +-----+ - // | loaded backwards | | | - // | for proper alignment | | .----------------------^----------------< - // *----------------------* | | | - // +--+ +--+ v | +--+ +--+ v - // Coeff In | | | | +------------+ | | | | | +------------+ - // .--->| |-->| |-->| Multiplier | '-->| |-->| |->| Multiplier | - // | | | | | +------------+ | | | | | +------------+ - // | +--+ +--+ | +--+ | +--+ | - // | | | | - // '------------------------^------------------' | + // | | | | + // +-----+ +-----+ + // | | + // | | + // | | + // +--+ v +--+ v + // Coeff In | | +------------+ | | +------------+ + // +-------->| |--------->| Multiplier | .--->| |----->| Multiplier | + // | | | +------------+ | | | | +------------+ + // +--+ | | | +--+ | | + // | | | | | + // '----------^-----------' '--------^--------------> // | Coeff | // v Forward v // +-----+ +-----+ @@ -230,7 +231,7 @@ module axi_fir_filter #( wire [COEFF_WIDTH-1:0] coeff_forward[0:NUM_SLICES]; // generate loop easier to read assign sample_in[0] = s_axis_data_tdata; assign sample_accum[0] = 0; - assign coeff_forward[NUM_SLICES] = s_axis_reload_tdata; + assign coeff_forward[0] = s_axis_reload_tdata; // Build up FIR filter with multiply-accumulate slices (fir_filter_slice) for (i = 0; i < NUM_SLICES; i = i + 1) begin @@ -252,13 +253,13 @@ module axi_fir_filter #( sample_accum_reg <= sample_accum[i]; end if (coeff_load_stb) begin - coeff_in_reg <= coeff_forward[i+1]; + coeff_in_reg <= coeff_forward[i]; end end end - assign sample_in[i+1] = sample_in_reg[1]; - assign sample_accum[i+1] = sample_accum_reg; - assign coeff_forward[i] = coeff_in_reg; + assign sample_in[i+1] = sample_in_reg[1]; + assign sample_accum[i+1] = sample_accum_reg; + assign coeff_forward[i+1] = coeff_in_reg; end else begin fir_filter_slice #( .IN_WIDTH(IN_WIDTH), @@ -275,8 +276,8 @@ module axi_fir_filter #( .sample_in_b(((SYMMETRIC_COEFFS == 0) || ((ODD_LEN == 1) && (i == NUM_SLICES-1))) ? {IN_WIDTH{1'b0}} : sample_shift_reg[NUM_COEFFS-1]), .sample_forward(sample_in[i+1]), // For proper coeffient loading, coeff_forward must be shifted in backwards. coeffs[] is already backwards. - .coeff_in(((USE_EMBEDDED_REGS_COEFFS == 1) && (RELOADABLE_COEFFS == 1)) ? coeff_forward[i+1] : coeffs[i]), - .coeff_forward(coeff_forward[i]), + .coeff_in(((USE_EMBEDDED_REGS_COEFFS == 1) && (RELOADABLE_COEFFS == 1)) ? coeff_forward[i] : coeffs[i]), + .coeff_forward(coeff_forward[i+1]), .coeff_load_stb(coeff_load_stb), .sample_accum(sample_accum[i]), .sample_out(sample_accum[i+1])); diff --git a/lib/rfnoc/blocks/rfnoc_block_fir_filter/noc_shell_fir_filter.v b/lib/rfnoc/blocks/rfnoc_block_fir_filter/noc_shell_fir_filter.v index a959463..d46508e 100644 --- a/lib/rfnoc/blocks/rfnoc_block_fir_filter/noc_shell_fir_filter.v +++ b/lib/rfnoc/blocks/rfnoc_block_fir_filter/noc_shell_fir_filter.v @@ -132,7 +132,7 @@ module noc_shell_fir_filter #( wire [63:0] data_o_flush_done; backend_iface #( - .NOC_ID (32'hF1120000), + .NOC_ID (32'hF1120002), .NUM_DATA_I (0+NUM_PORTS), .NUM_DATA_O (0+NUM_PORTS), .CTRL_FIFOSIZE ($clog2(32)), diff --git a/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_block_fir_filter_tb.sv b/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_block_fir_filter_tb.sv index 88995e0..5ae915c 100644 --- a/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_block_fir_filter_tb.sv +++ b/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_block_fir_filter_tb.sv @@ -27,7 +27,7 @@ module rfnoc_block_fir_filter_tb #( // Local Parameters //--------------------------------------------------------------------------- - localparam int NOC_ID = 32'hF112_0000; + localparam int NOC_ID = 32'hF112_0002; // Simulation parameters localparam real CHDR_CLK_PER = 6.0; // 166 MHz @@ -255,7 +255,7 @@ module rfnoc_block_fir_filter_tb #( // If using embedded register, coefficients must be preloaded if (USE_EMBEDDED_REGS_COEFFS) begin int i; - for (i = 0; i < num_coeffs_to_send-1; i++) begin + for (i = num_coeffs_to_send-1; i > 0; i--) begin write_reg(port, REG_FIR_LOAD_COEFF, COEFFS_VEC_0[COEFF_WIDTH*i +: COEFF_WIDTH]); end write_reg(port, REG_FIR_LOAD_COEFF_LAST, COEFFS_VEC_0[COEFF_WIDTH*i +: COEFF_WIDTH]); @@ -351,7 +351,7 @@ module rfnoc_block_fir_filter_tb #( end test.start_test("Load new coefficients", 20us); - for (i = 0; i < num_coeffs_to_send-1; i++) begin + for (i = num_coeffs_to_send-1; i > 0; i--) begin write_reg(port, REG_FIR_LOAD_COEFF, COEFFS_VEC_1[COEFF_WIDTH*i +: COEFF_WIDTH]); end write_reg(port, REG_FIR_LOAD_COEFF_LAST, COEFFS_VEC_1[COEFF_WIDTH*i +: COEFF_WIDTH]); diff --git a/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_fir_filter_core.v b/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_fir_filter_core.v index 60303e6..e83b03d 100644 --- a/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_fir_filter_core.v +++ b/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_fir_filter_core.v @@ -108,6 +108,8 @@ module rfnoc_fir_filter_core #( //--------------------------------------------------------------------------- // Registers //--------------------------------------------------------------------------- + localparam COMPAT_MAJOR = 16'h1; + localparam COMPAT_MINOR = 16'h1; `include "rfnoc_fir_filter_regs.vh" @@ -154,6 +156,9 @@ module rfnoc_fir_filter_core #( if (reg_addr == REG_FIR_NUM_COEFFS) begin s_ctrlport_resp_data <= NUM_COEFFS; s_ctrlport_resp_ack <= 1; + end else if (reg_addr == REG_FIR_COMPAT_NUM) begin + s_ctrlport_resp_data <= {COMPAT_MAJOR, COMPAT_MINOR}; + s_ctrlport_resp_ack <= 1; end end end diff --git a/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_fir_filter_regs.vh b/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_fir_filter_regs.vh index 520396b..3700401 100644 --- a/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_fir_filter_regs.vh +++ b/lib/rfnoc/blocks/rfnoc_block_fir_filter/rfnoc_fir_filter_regs.vh @@ -48,4 +48,14 @@ localparam REG_FIR_LOAD_COEFF = 'h4; // [31:(32-COEFF_WIDTH)] : Reserved // [COEFF_WIDTH-1:0] : The next coefficient to be loaded // -localparam REG_FIR_LOAD_COEFF_LAST = 'h8; \ No newline at end of file +localparam REG_FIR_LOAD_COEFF_LAST = 'h8; + + +// REG_FIR_COMPAT_NUM (R) +// +// Contains the compatibility number of the block. +// +// [31:16] : Returns the major compatibility number (read-only) +// [15:0] : Returns the minor compatibility number (read-only) +// +localparam REG_FIR_COMPAT_NUM = 'hC; diff --git a/lib/rfnoc/fir_filter_slice.v b/lib/rfnoc/fir_filter_slice.v index 3f83f54..afaba04 100644 --- a/lib/rfnoc/fir_filter_slice.v +++ b/lib/rfnoc/fir_filter_slice.v @@ -37,7 +37,7 @@ module fir_filter_slice #( reg signed [IN_WIDTH-1:0] a_reg[0:1]; reg signed [IN_WIDTH-1:0] d_reg; reg signed [IN_WIDTH:0] ad_reg; - reg signed [COEFF_WIDTH-1:0] b_reg[0:1]; + reg signed [COEFF_WIDTH-1:0] b_reg; reg signed [IN_WIDTH+COEFF_WIDTH:0] m_reg; reg signed [ACCUM_WIDTH-1:0] p_reg; @@ -46,8 +46,7 @@ module fir_filter_slice #( a_reg[0] <= 0; a_reg[1] <= 0; d_reg <= 0; - b_reg[0] <= 0; - b_reg[1] <= 0; + b_reg <= 0; ad_reg <= 0; m_reg <= 0; p_reg <= 0; @@ -57,17 +56,16 @@ module fir_filter_slice #( a_reg[1] <= a_reg[0]; d_reg <= sample_in_b; ad_reg <= a_reg[1] + d_reg; - m_reg <= ad_reg * b_reg[1]; + m_reg <= ad_reg * b_reg; p_reg <= sample_accum + m_reg; end if (coeff_load_stb) begin - b_reg[0] <= coeff_in; + b_reg <= coeff_in; end - b_reg[1] <= b_reg[0]; end end - assign coeff_forward = b_reg[0]; + assign coeff_forward = b_reg; assign sample_forward = a_reg[1]; assign sample_out = p_reg[OUT_WIDTH-1:0];