fpga: rfnoc: reverse FIR filter coefficients to get embedded in DSPE48
Original-commit: ea164a936b924b05a5b4cb9dd50df8acc3700c1a
This commit is contained in:
+22
-21
@@ -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]));
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user