at the moment i try to realize a FIR-Filter using the FPGA. In the picture below you can see the problem i have at the moment. The blue line is an unedited signal, the yellow line is the same signal with an active filter (1 coefficient = 0.5 ). This problem only appears when the sum of all coefficients is below 1, or better say between 1 and -1. If the sum of the coefficients equals 1 or is even higher the problem doesn't appear.
As you see in the picture the problem appears when it's crossing the 0-voltage line. I also getting random peaks at 0V. If i add a voltage offset and the signal doesn't cross the 0-line everything is working fine. It’s seems like an issue with the calculation of 0. The signal jumps to the value of 2*Umax which should be caused by a wrong Bit which is set.
The input and calculation of the coefficients and the sampling rate I realized in C, but I'am really sure it's a problem inside my Verilog code. If you have some problems understanding my code Iam ready to explain. Hope to get some help with this issue. Not sure where this problem comes from.
Verilog code of filter module:
Code: Select all
`timescale 1ns / 1ps
module filter_a(
//Filter calculation
input clk_in, //ADC Clock = 125Mhz
input rst_in, //reset, active low
input signed [14-1:0] data_in, //input Ch1
output wire signed [14-1:0] data_out, //Output Ch1
//System bus connection
input sys_clk_i , //!< bus clock
input sys_rstn_i , //!< bus reset - active low
input sys_wen_i , //read
input sys_ren_i , //write
input [ 32-1: 0] sys_addr_i , //!< bus address
input [ 32-1: 0] sys_wdata_i , //!< bus write data in
output reg [ 32-1: 0] sys_rdata_o , //date out
output reg sys_err_o , //error indicator
output reg sys_ack_o //acknowledge
);
reg signed [14-1:0] out; //Output Channel 1
reg signed [14-1:0] filter_output; //Output Filter 1
reg signed [14-1:0] sig_in[20-1:0]; //incoming signals + shifting
reg signed [15-1:0] a[20-1:0]; //Coefficients (+1 für VZ)
reg signed [28-1:0] mult; //Zwischenvariable um DSPs zu sparen
reg [8-1:0] i;
reg [0:0] filter_on; //filter on/off
reg [14:0] counter_clk = 0; //Zählt Taktzyklen
reg [14:0] sampling_rate; //gewünschte Abtastrate, eingabe und berechnung in C
//---------------------------------------------------------------------------------
//
// Filter
always @(posedge clk_in) begin
counter_clk = counter_clk + 1;
if ((sampling_rate == counter_clk) && rst_in && filter_on)
begin
filter_output = 0;
for(i = 20-1; i > 0; i = i - 1) begin
sig_in[i] = sig_in[i-1]; //shifting
mult = sig_in[i] * a[i][13:0]; //multiplication
if(a[i][14] == 0) //Abfrage VZ-Bit
filter_output = filter_output + mult[28-1:14]; //addition
else
filter_output = filter_output - mult[28-1:14];
end
mult = sig_in[0] * a[0][13:0];
if(a[0][14] == 0)
filter_output = filter_output + mult[28-1:14];
else
filter_output = filter_output - mult[28-1:14];
sig_in[0] = data_in;
counter_clk = 0;
end
end
//---------------------------------------------------------------------------------
//
// Output
always @(*) begin
if(filter_on) //filter active
out = filter_output;
else //filter not active
out = data_in;
end
assign data_out = out;
//---------------------------------------------------------------------------------
//
// System bus connection - FREE space
always @(posedge sys_clk_i) begin
if (sys_rstn_i == 1'b0) begin
filter_on <= 0'b0;
sampling_rate <= 14'h0;
for(i = 0; i < 20; i = i + 1)begin
a[i] <= 15'h0 ; end
end
else begin
if (sys_wen_i) begin
if (sys_addr_i[19:0]==20'h00) filter_on <= sys_wdata_i [0:0] ;
if (sys_addr_i[19:0]==20'h04) sampling_rate <= sys_wdata_i [14:0] ;
for(i = 0; i < 20; i = i + 1)begin
if (sys_addr_i[19:0]==20'h08+4*i) a[i] <= sys_wdata_i[15-1:0] ; end
end
end
end
always @(*) begin
sys_err_o <= 1'b0 ;
if(sys_addr_i[19:0] == 20'h00000)
begin sys_ack_o <= 1'b1; sys_rdata_o <= {{32- 1{1'b0}}, filter_on } ; end
if(sys_addr_i[19:0] == 20'h00004)
begin sys_ack_o <= 1'b1; sys_rdata_o <= {{32- 14{1'b0}}, sampling_rate } ; end
for(i = 0; i < 20; i = i +1)begin
if(sys_addr_i[19:0] == 20'h0008+4*i)
begin sys_ack_o <= 1'b1; sys_rdata_o <= {{32- 15{1'b0}}, a[i] }; end
end
end
endmodule