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:
|
// 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
|
||||||
|
|||||||
@@ -48,4 +48,14 @@ localparam REG_FIR_LOAD_COEFF = 'h4;
|
|||||||
// [31:(32-COEFF_WIDTH)] : Reserved
|
// [31:(32-COEFF_WIDTH)] : Reserved
|
||||||
// [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;
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user