IIR filter in SystemVerilog

Status
Not open for further replies.

Haraldovs

Newbie level 3
Joined
Apr 7, 2018
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
48
Hello,

I am trying to implement a 2.order IIR filter using SystemVerilog, and I am having some trouble.

a0*y[n] = -a1*y[n-1] - a2*y[n-2] + b0*x[n] + b1*x[n-1] + b2*x[n-2]

The simulation results i get using a square wave input and low- or highpass coefficients is garbage, but when running audio through a cascade of 12 allpass filters i hear no difference from original.

I reckon the filter doesn't work, but with the allpass filters I start thinking it works, but only for positive only coefficients.

I have only had DSP in school, and my SystemVerilog skills are slightly noobish, if anyone
can look at my code below i'd be grateful.


Code:
module second_order_iir #(parameter B0=1732852,B1=3465704,B2=1732852, A1=-3099820,A2=1642621)
(
output logic signed [23:0] out, 
output logic output_ready,
input logic signed [23:0] in,
input logic clk, rst, input_ready
);

 typedef logic signed [23:0] coeffs;
const coeffs [4:0] coefficients = {A2[23:0], A1[23:0], B2[23:0], B1[23:0], B0[23:0]};


logic [2:0] address;
logic signed [4:0][23:0] samples;

enum {waiting,loading, processing,done} state, next_state;

logic load, reset_sum, count, save_output;

logic signed [23:0] coefficient, sample;
logic signed [47:0] sum, product;

always_ff @(posedge clk, negedge rst)
if(~rst)
 begin
  out <= '0;
  state<= waiting;
  samples <= '0;
  end
  else
  begin
  state <= next_state;
  
  if(save_output)
    out <= sum[46:23];
	
  if(load)
    begin
  samples[4] <= samples[3];
  samples[3] <= out;
  samples[2] <= samples[1];
  samples[1] <= samples[0];
  samples[0] <= in;
     end
	 
  end
  
 always_ff @(posedge clk)
if(reset_sum)
  sum <= '0;
else
 if(address < 3'b011)
  sum <= sum + product;
 else
  sum <= sum - product;    //subtract y[n-1] & y[n-2]
 
 always_ff @ (posedge clk)
 if(!count)
   address <= '0;
 else
   address <= address + 1;
   
 always_comb
 coefficient = coefficients[address];
 
 always_comb
  sample = samples[address];

always_comb
   product = sample * coefficient;



  
  
  
always_comb
begin
next_state = state;
load = 0;
reset_sum = 0;
save_output = 0;
count = 0;
output_ready = 0;

case(state)
  waiting: begin
  if(input_ready)
    next_state = loading;
  reset_sum = 1;
  
end
loading: begin
  next_state = processing;
  reset_sum = 1;
  load = 1;
end
processing: begin
 if(address == 3'b100)
   next_state = done;
 count = 1;
end
done: begin
next_state = waiting;
save_output = 1;
output_ready = 1;
end
endcase  
end


endmodule
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…