Problem inside Verilog code

Applications, development tools, FPGA, C, WEB
Post Reply
TheWickedOne
Posts: 6
Joined: Tue May 12, 2015 9:30 am

Problem inside Verilog code

Post by TheWickedOne » Mon Nov 23, 2015 3:38 pm

Hi guys,

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.


Image

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


Nils Roos
Posts: 1441
Joined: Sat Jun 07, 2014 12:49 pm
Location: Königswinter

Re: Problem inside Verilog code

Post by Nils Roos » Mon Nov 23, 2015 5:03 pm

On a first glance - I can't try it out right now - I find your mixing of signed operations and explicit sign-handling suspicious. You could try to just do

Code: Select all

mult = sig_in[i] * a[i];
filter_output = filter_output + $signed(mult[29-1:15]);
(with appropriately adjusted register widths, of course) and see if it changes anything.

It would also be relevant for further analysis to know how you integrated the filter into the signal flow.

Post Reply
jadalnie klasyczne ekskluzywne meble wypoczynkowe do salonu ekskluzywne meble tapicerowane ekskluzywne meble do sypialni ekskluzywne meble włoskie

Who is online

Users browsing this forum: No registered users and 100 guests