fpga: rfnoc: reverse FIR filter coefficients to get embedded in DSPE48

Original-commit: ea164a936b924b05a5b4cb9dd50df8acc3700c1a
This commit is contained in:
Max Köhler
2024-04-26 15:19:23 -05:00
committed by Wade Fife
parent fa95da3f7f
commit c719cf1406
6 changed files with 47 additions and 33 deletions
+22 -21
View File
@@ -33,6 +33,7 @@
// Notes: // Notes:
// - If using USE_EMBEDDED_REGS_COEFFS, coefficients must be written at least once as COEFFS_VEC is ignored! // - 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 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 #( module axi_fir_filter #(
parameter IN_WIDTH = 16, parameter IN_WIDTH = 16,
@@ -106,9 +107,9 @@ module axi_fir_filter #(
end else begin end else begin
if (s_axis_reload_tvalid & s_axis_reload_tready) begin if (s_axis_reload_tvalid & s_axis_reload_tready) begin
for (k = NUM_SLICES-1; k > 0; k = k - 1) begin for (k = NUM_SLICES-1; k > 0; k = k - 1) begin
coeffs[k-1] <= coeffs[k]; coeffs[k] <= coeffs[k-1];
end end
coeffs[NUM_SLICES-1] <= s_axis_reload_tdata; coeffs[0] <= s_axis_reload_tdata;
end end
coeff_load_stb <= s_axis_reload_tvalid & s_axis_reload_tready & s_axis_reload_tlast; coeff_load_stb <= s_axis_reload_tvalid & s_axis_reload_tready & s_axis_reload_tlast;
end end
@@ -156,18 +157,18 @@ module axi_fir_filter #(
// | | // | |
// v v // v v
// +-----+ +-----+ // +-----+ +-----+
// *----------------------* | | | | // | | | |
// | Note: Coeffs are | +-----+ +-----+ // +-----+ +-----+
// | loaded backwards | | | // | |
// | for proper alignment | | .----------------------^----------------< // | |
// *----------------------* | | | // | |
// +--+ +--+ v | +--+ +--+ v // +--+ v +--+ v
// Coeff In | | | | +------------+ | | | | | +------------+ // Coeff In | | +------------+ | | +------------+
// .--->| |-->| |-->| Multiplier | '-->| |-->| |->| Multiplier | // +-------->| |--------->| Multiplier | .--->| |----->| Multiplier |
// | | | | | +------------+ | | | | | +------------+ // | | | +------------+ | | | | +------------+
// | +--+ +--+ | +--+ | +--+ | // +--+ | | | +--+ | |
// | | | | // | | | | |
// '------------------------^------------------' | // '----------^-----------' '--------^-------------->
// | Coeff | // | Coeff |
// v Forward v // 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 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_in[0] = s_axis_data_tdata;
assign sample_accum[0] = 0; 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) // Build up FIR filter with multiply-accumulate slices (fir_filter_slice)
for (i = 0; i < NUM_SLICES; i = i + 1) begin for (i = 0; i < NUM_SLICES; i = i + 1) begin
@@ -252,13 +253,13 @@ module axi_fir_filter #(
sample_accum_reg <= sample_accum[i]; sample_accum_reg <= sample_accum[i];
end end
if (coeff_load_stb) begin if (coeff_load_stb) begin
coeff_in_reg <= coeff_forward[i+1]; coeff_in_reg <= coeff_forward[i];
end end
end end
end end
assign sample_in[i+1] = sample_in_reg[1]; assign sample_in[i+1] = sample_in_reg[1];
assign sample_accum[i+1] = sample_accum_reg; assign sample_accum[i+1] = sample_accum_reg;
assign coeff_forward[i] = coeff_in_reg; assign coeff_forward[i+1] = coeff_in_reg;
end else begin end else begin
fir_filter_slice #( fir_filter_slice #(
.IN_WIDTH(IN_WIDTH), .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_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]), .sample_forward(sample_in[i+1]),
// For proper coeffient loading, coeff_forward must be shifted in backwards. coeffs[] is already backwards. // 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_in(((USE_EMBEDDED_REGS_COEFFS == 1) && (RELOADABLE_COEFFS == 1)) ? coeff_forward[i] : coeffs[i]),
.coeff_forward(coeff_forward[i]), .coeff_forward(coeff_forward[i+1]),
.coeff_load_stb(coeff_load_stb), .coeff_load_stb(coeff_load_stb),
.sample_accum(sample_accum[i]), .sample_accum(sample_accum[i]),
.sample_out(sample_accum[i+1])); .sample_out(sample_accum[i+1]));
@@ -132,7 +132,7 @@ module noc_shell_fir_filter #(
wire [63:0] data_o_flush_done; wire [63:0] data_o_flush_done;
backend_iface #( backend_iface #(
.NOC_ID (32'hF1120000), .NOC_ID (32'hF1120002),
.NUM_DATA_I (0+NUM_PORTS), .NUM_DATA_I (0+NUM_PORTS),
.NUM_DATA_O (0+NUM_PORTS), .NUM_DATA_O (0+NUM_PORTS),
.CTRL_FIFOSIZE ($clog2(32)), .CTRL_FIFOSIZE ($clog2(32)),
@@ -27,7 +27,7 @@ module rfnoc_block_fir_filter_tb #(
// Local Parameters // Local Parameters
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
localparam int NOC_ID = 32'hF112_0000; localparam int NOC_ID = 32'hF112_0002;
// Simulation parameters // Simulation parameters
localparam real CHDR_CLK_PER = 6.0; // 166 MHz 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 using embedded register, coefficients must be preloaded
if (USE_EMBEDDED_REGS_COEFFS) begin if (USE_EMBEDDED_REGS_COEFFS) begin
int i; 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]); write_reg(port, REG_FIR_LOAD_COEFF, COEFFS_VEC_0[COEFF_WIDTH*i +: COEFF_WIDTH]);
end end
write_reg(port, REG_FIR_LOAD_COEFF_LAST, COEFFS_VEC_0[COEFF_WIDTH*i +: COEFF_WIDTH]); 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 end
test.start_test("Load new coefficients", 20us); 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]); write_reg(port, REG_FIR_LOAD_COEFF, COEFFS_VEC_1[COEFF_WIDTH*i +: COEFF_WIDTH]);
end end
write_reg(port, REG_FIR_LOAD_COEFF_LAST, COEFFS_VEC_1[COEFF_WIDTH*i +: COEFF_WIDTH]); write_reg(port, REG_FIR_LOAD_COEFF_LAST, COEFFS_VEC_1[COEFF_WIDTH*i +: COEFF_WIDTH]);
@@ -108,6 +108,8 @@ module rfnoc_fir_filter_core #(
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Registers // Registers
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
localparam COMPAT_MAJOR = 16'h1;
localparam COMPAT_MINOR = 16'h1;
`include "rfnoc_fir_filter_regs.vh" `include "rfnoc_fir_filter_regs.vh"
@@ -154,6 +156,9 @@ module rfnoc_fir_filter_core #(
if (reg_addr == REG_FIR_NUM_COEFFS) begin if (reg_addr == REG_FIR_NUM_COEFFS) begin
s_ctrlport_resp_data <= NUM_COEFFS; s_ctrlport_resp_data <= NUM_COEFFS;
s_ctrlport_resp_ack <= 1; 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 end
end end
@@ -49,3 +49,13 @@ localparam REG_FIR_LOAD_COEFF = 'h4;
// [COEFF_WIDTH-1:0] : The next coefficient to be loaded // [COEFF_WIDTH-1:0] : The next coefficient to be loaded
// //
localparam REG_FIR_LOAD_COEFF_LAST = 'h8; 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;
+5 -7
View File
@@ -37,7 +37,7 @@ module fir_filter_slice #(
reg signed [IN_WIDTH-1:0] a_reg[0:1]; reg signed [IN_WIDTH-1:0] a_reg[0:1];
reg signed [IN_WIDTH-1:0] d_reg; reg signed [IN_WIDTH-1:0] d_reg;
reg signed [IN_WIDTH:0] ad_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 [IN_WIDTH+COEFF_WIDTH:0] m_reg;
reg signed [ACCUM_WIDTH-1:0] p_reg; reg signed [ACCUM_WIDTH-1:0] p_reg;
@@ -46,8 +46,7 @@ module fir_filter_slice #(
a_reg[0] <= 0; a_reg[0] <= 0;
a_reg[1] <= 0; a_reg[1] <= 0;
d_reg <= 0; d_reg <= 0;
b_reg[0] <= 0; b_reg <= 0;
b_reg[1] <= 0;
ad_reg <= 0; ad_reg <= 0;
m_reg <= 0; m_reg <= 0;
p_reg <= 0; p_reg <= 0;
@@ -57,17 +56,16 @@ module fir_filter_slice #(
a_reg[1] <= a_reg[0]; a_reg[1] <= a_reg[0];
d_reg <= sample_in_b; d_reg <= sample_in_b;
ad_reg <= a_reg[1] + d_reg; 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; p_reg <= sample_accum + m_reg;
end end
if (coeff_load_stb) begin if (coeff_load_stb) begin
b_reg[0] <= coeff_in; b_reg <= coeff_in;
end end
b_reg[1] <= b_reg[0];
end end
end end
assign coeff_forward = b_reg[0]; assign coeff_forward = b_reg;
assign sample_forward = a_reg[1]; assign sample_forward = a_reg[1];
assign sample_out = p_reg[OUT_WIDTH-1:0]; assign sample_out = p_reg[OUT_WIDTH-1:0];