0
\$\begingroup\$

I am trying to design an FIR filter which reads very small 10 bit decimal fractions of 2 integer bits and 8 fractional bits as the input and coefficients. But anytime I run the testbench my data_in and data_out registers initialize as 0000 or xxxx. Please can I know what is the problem with my design that IO am unable to get an output.

This is the module:

`default_nettype none
`include "RTL.svh"

module multiplier #(
    parameter WIDTH = 10
) (
    input clk,
    input rst_n,
    input signed [WIDTH-1:0] data_in1,
    input signed [WIDTH-1:0] data_in2,
    output signed [WIDTH-1:0] mul_out
);
    logic signed mul_reg;

    always_ff @(posedge clk or negedge rst_n) begin
      if (!rst_n) begin
        mul_reg <= '0;
      end else begin
        mul_reg <= data_in1 * data_in2;
      end
    end

    assign mul_out = mul_reg;
endmodule

module summer #(
    parameter WIDTH = 10
) (
    input clk,
    input rst_n,
    input signed [WIDTH-1:0] data_in1,
    input signed [WIDTH:0] data_in2,
    output signed [WIDTH-1:0] sum_out
);
    logic signed sum_reg;

    always_ff @(posedge clk or negedge rst_n) begin
          if (!rst_n) begin
            sum_reg <= '0;
          end else begin
            sum_reg <= (data_in1 + data_in2);
          end
        end    
    
    assign sum_out = sum_reg;
endmodule

module FIR_TAP64 #(
    parameter NUMBER_OF_TAPS = 8,
    parameter DATA_WIDTH = 10
) (
    input logic clk,
    input logic rst_n,
    input signed [DATA_WIDTH-1:0] data_in,
    input signed [DATA_WIDTH-1:0] h [0:NUMBER_OF_TAPS-1],
    output signed [DATA_WIDTH-1:0] data_out
);
    logic signed [DATA_WIDTH+DATA_WIDTH-1:0] product [0:NUMBER_OF_TAPS-1];
    logic signed [DATA_WIDTH-1:0] delay_line [0:NUMBER_OF_TAPS-1];
    logic signed [DATA_WIDTH-1:0] data_in_reg;
    logic signed [DATA_WIDTH-1:0] sum [0:NUMBER_OF_TAPS-1];
    logic signed [DATA_WIDTH-1:0] accumulator;
    localparam DIVISOR = 2**DATA_WIDTH-1;

    logic en = 1;

    always_ff @( posedge clk or negedge rst_n ) begin
      if (!rst_n) begin
        data_in_reg <= '0;
      end else begin
          data_in_reg <= data_in;
      end
    end
    
    `FF(delay_line[0], data_in_reg, clk, en, rst_n, '0);
    assign product[0] = h[0] * data_in_reg; 
    assign sum[0] = product[0];

    genvar i;
    generate
      for(i=1; i<NUMBER_OF_TAPS; i=i+1) begin
        `FF(delay_line[i], delay_line[i-1], clk, en, rst_n, '0);
        multiplier mul0 (.clk(clk), .rst_n(rst_n), .data_in1(h[i]), .data_in2(delay_line[i]), .mul_out(product[i]));
        summer sum0 (.clk(clk), .rst_n(rst_n), .data_in1(product[i]), .data_in2(sum[i-1]), .sum_out(sum[i]));
      end
    endgenerate

    
    assign data_out = product[0];
    
endmodule

and this is the testbench

`include "FIR_tap64.sv"


module FIR64_tb ();
    parameter NUMBER_OF_TAPS = 63;
    parameter DATA_WIDTH = 10;
    logic clk = 0;
    logic rst_n;
    logic signed [DATA_WIDTH-1:0] data_in;
    logic signed [DATA_WIDTH-1:0] data_out;
    logic signed [DATA_WIDTH-1:0] data_in_print;
    logic signed [DATA_WIDTH-1:0] data_out_print;
    logic signed [DATA_WIDTH-1:0] h [0:NUMBER_OF_TAPS-1];
    int i;
    

    logic signed [DATA_WIDTH-1:0] data_in_import [0:62];

    FIR_TAP64 #(.NUMBER_OF_TAPS(NUMBER_OF_TAPS), .DATA_WIDTH(DATA_WIDTH)) FIR_0 (
        .clk(clk),
        .rst_n(rst_n),
        .h(h),
        .data_in(data_in),
        .data_out(data_out)
    );

    always begin
        #10 clk = ~clk;
    end

    initial begin
        for ( i=0 ; i<NUMBER_OF_TAPS; i++) begin
            // #500;
            #10 data_in = data_in_import[i];
        end
        $finish;
    end

    initial begin
      #10 $readmemb("./filter_taps.txt", h);
    end

    initial begin       
       rst_n = 0;
       #10;
       rst_n = 1;
        $readmemb("input_samples.txt", data_in_import);
        $monitor("Output Data=%h, Input Data=%h FIR_data_reg=%h, FIR_coefficient=%h", data_out, data_in, FIR_0.data_in_reg, FIR_0.h[0]);
        #1100 $finish;
    end

    initial begin
        $dumpfile("fir64.vcd");
        $dumpvars(0, FIR64_tb);
    end
endmodule

These are the results

Output Data=000, Input Data=xxx FIR_data_reg=000, FIR_coefficient=000
Output Data=000, Input Data=169 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=0f2 FIR_data_reg=0f2, FIR_coefficient=000
Output Data=xxx, Input Data=3e5 FIR_data_reg=0f2, FIR_coefficient=000
Output Data=xxx, Input Data=2e8 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=299 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=32a FIR_data_reg=32a, FIR_coefficient=000
Output Data=xxx, Input Data=03f FIR_data_reg=32a, FIR_coefficient=000
Output Data=xxx, Input Data=12e FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=160 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=0b7 FIR_data_reg=0b7, FIR_coefficient=000
Output Data=xxx, Input Data=39d FIR_data_reg=0b7, FIR_coefficient=000
Output Data=xxx, Input Data=2c0 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=2aa FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=369 FIR_data_reg=369, FIR_coefficient=000
Output Data=xxx, Input Data=086 FIR_data_reg=369, FIR_coefficient=000
Output Data=xxx, Input Data=150 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=148 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=075 FIR_data_reg=075, FIR_coefficient=000
Output Data=xxx, Input Data=359 FIR_data_reg=075, FIR_coefficient=000
Output Data=xxx, Input Data=2a4 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=2c9 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=3af FIR_data_reg=3af, FIR_coefficient=000
Output Data=xxx, Input Data=0c7 FIR_data_reg=3af, FIR_coefficient=000
Output Data=xxx, Input Data=164 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=123 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=02d FIR_data_reg=02d, FIR_coefficient=000
Output Data=xxx, Input Data=31c FIR_data_reg=02d, FIR_coefficient=000
Output Data=xxx, Input Data=298 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=2f4 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=3f7 FIR_data_reg=3f7, FIR_coefficient=000
Output Data=xxx, Input Data=0ff FIR_data_reg=3f7, FIR_coefficient=000
Output Data=xxx, Input Data=169 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=0f2 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=3e5 FIR_data_reg=3e5, FIR_coefficient=000
Output Data=xxx, Input Data=2e8 FIR_data_reg=3e5, FIR_coefficient=000
Output Data=xxx, Input Data=299 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=32a FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=03f FIR_data_reg=03f, FIR_coefficient=000
Output Data=xxx, Input Data=12e FIR_data_reg=03f, FIR_coefficient=000
Output Data=xxx, Input Data=160 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=0b7 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=39d FIR_data_reg=39d, FIR_coefficient=000
Output Data=xxx, Input Data=2c0 FIR_data_reg=39d, FIR_coefficient=000
Output Data=xxx, Input Data=2aa FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=369 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=086 FIR_data_reg=086, FIR_coefficient=000
Output Data=xxx, Input Data=150 FIR_data_reg=086, FIR_coefficient=000
Output Data=xxx, Input Data=148 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=075 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=359 FIR_data_reg=359, FIR_coefficient=000
Output Data=xxx, Input Data=2a4 FIR_data_reg=359, FIR_coefficient=000
Output Data=xxx, Input Data=2c9 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=3af FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=0c7 FIR_data_reg=0c7, FIR_coefficient=000
Output Data=xxx, Input Data=164 FIR_data_reg=0c7, FIR_coefficient=000
Output Data=xxx, Input Data=123 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=02d FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=31c FIR_data_reg=31c, FIR_coefficient=000
Output Data=xxx, Input Data=298 FIR_data_reg=31c, FIR_coefficient=000
Output Data=xxx, Input Data=2f4 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=3f7 FIR_data_reg=000, FIR_coefficient=000
Output Data=xxx, Input Data=0ff FIR_data_reg=0ff, FIR_coefficient=000

These are the simulation results

The input samples

0101101001
0011110010
1111100101
1011101000
1010011001
1100101010
0000111111
0100101110
0101100000
0010110111
1110011101
1011000000
1010101010
1101101001
0010000110
0101010000
0101001000
0001110101
1101011001
1010100100
1011001001
1110101111
0011000111
0101100100
0100100011
0000101101
1100011100
1010011000
1011110100
1111110111
0011111111
0101101001
0011110010
1111100101
1011101000
1010011001
1100101010
0000111111
0100101110
0101100000
0010110111
1110011101
1011000000
1010101010
1101101001
0010000110
0101010000
0101001000
0001110101
1101011001
1010100100
1011001001
1110101111
0011000111
0101100100
0100100011
0000101101
1100011100
1010011000
1011110100
1111110111
0011111111

The coefficients

0000000000
1111111111
1111111110
1111111100
1111111101
0000000000
0000000010
0000000001
1111111111
1111111101
0000000000
0000000100
0000000001
1111111100
1111111100
0000000010
0000000111
0000000000
1111110111
1111111100
0000001001
0000001010
1111111010
1111101111
0000000000
0000011000
0000001101
1111100010
1111010110
0000100010
0010011110
0011011011
0010011110
0000100010
1111010110
1111100010
0000001101
0000011000
0000000000
1111101111
1111111010
0000001010
0000001001
1111111100
1111110111
0000000000
0000000111
0000000010
1111111100
1111111100
0000000001
0000000100
0000000000
1111111101
1111111111
0000000001
0000000010
0000000000
1111111101
1111111100
1111111110
1111111111
0000000000

The `FF macro is flip-flop, but I don't own the file RTL.svh so I can't share it on here.

I generated the binary numbers using this Python script

from binary_fractions import TwosComplement
import numpy as np
from fxpmath import Fxp

# Define parameters for the sinusoidal waves
frequency1 = 1000  # Half of the sampling frequency 2kHz
amplitude1 = 0.5
phase1 = 0 

frequency2 = 1000 
amplitude2 = 0.5  
phase2 = np.pi / 2  

BIT_FORMAT = Fxp(None, signed=True, n_word=10, n_frac=9, overflow='wrap')
t = np.linspace(0, 1, 63)  


sinusoid1 = amplitude1 * np.sin(2 * np.pi * frequency1 * t + phase1)
sinusoid2 = amplitude2 * np.sin(2 * np.pi * frequency2 * t + phase2)


result = sinusoid1 + sinusoid2

binary_inputs = []
for sample in result:
    binary_str = Fxp(sample).like(BIT_FORMAT)
    binary_str_acceptable = binary_str.bin(frac_dot=False)
    binary_inputs.append(binary_str_acceptable)

# Write the binary numbers to a text file
with open('input_samples.txt', 'w') as file:
    file.write('\n'.join(binary_inputs))
    # for sample in binary_inputs:
    #     file.write(str(sample) + '\n')

# binary_inputs = []
# for sample in result:
#     binary_inputs.append(TwosComplement(sample))

# with open('input_samples.txt', 'w') as file:
#     for sample in binary_inputs:
#         file.write(str(sample) + '\n')
        
binary_coefficients = []
coefficients = [-0.0004117552538703652,
-0.0022005629703482667,
-0.005637111945119,
-0.008508207526889725,
-0.006961403836246138,
-0.00037696296324285484,
0.00549195991066055,
0.003828134022559271,
-0.003541629331746648,
-0.006271936854317565,
0.0007656418064318525,
0.008025107850443499,
0.003369889335487059,
-0.008206013204920714,
-0.008585723836131997,
0.005809220627959144,
0.01390351960490267,
-0.00011257104666066737,
-0.017751892390193383,
-0.009041533447465578,
0.018164359203061864,
0.021094396882056773,
-0.01292498785907307,
-0.034799773558235304,
-0.0006235651863995896,
0.04840821684199907,
0.027139106785120184,
-0.059978973023938925,
-0.08220931010867867,
0.06774833981643534,
0.30999537280732714,
0.42951451981666044,
0.30999537280732714,
0.06774833981643534,
-0.08220931010867867,
-0.059978973023938925,
0.027139106785120184,
0.04840821684199907,
-0.0006235651863995896,
-0.034799773558235304,
-0.01292498785907307,
0.021094396882056773,
0.018164359203061864,
-0.009041533447465578,
-0.017751892390193383,
-0.00011257104666066737,
0.01390351960490267,
0.005809220627959144,
-0.008585723836131997,
-0.008206013204920714,
0.003369889335487059,
0.008025107850443499,
0.0007656418064318525,
-0.006271936854317565,
-0.003541629331746648,
0.003828134022559271,
0.00549195991066055,
-0.00037696296324285484,
-0.006961403836246138,
-0.008508207526889725,
-0.005637111945119,
-0.0022005629703482667,
-0.0004117552538703652]

for sample in coefficients:
    binary_str = Fxp(sample).like(BIT_FORMAT)
    binary_str_acceptable = binary_str.bin(frac_dot=False)

    binary_coefficients.append(binary_str_acceptable)

with open('filter_taps.txt', 'w') as file:
    for sample in binary_coefficients:
        file.write(str(sample) + '\n')
\$\endgroup\$
5
  • \$\begingroup\$ I'm sorry, what is the question? Edit this so there's a concise question. \$\endgroup\$
    – MiNiMe
    Oct 1, 2023 at 15:14
  • \$\begingroup\$ Please, How do I get my design to work because my data_out port is giving me xxxx instead of bit values. I just edited it. \$\endgroup\$
    – topeagb
    Oct 1, 2023 at 15:40
  • \$\begingroup\$ @toolic I have just put in everything in the txt files and the python script I've used to make the design in my question. I don't have the rights to share the RTL.svh but I'm using a basic flip flop and '0 is the reset value of the flip flop. \$\endgroup\$
    – topeagb
    Oct 1, 2023 at 16:03
  • \$\begingroup\$ I presume the RTL.svh file is this one? If so, providing a link would have been useful - save asking people to guess. \$\endgroup\$ Oct 1, 2023 at 21:26
  • \$\begingroup\$ @TomCarpenter Sorry, it was provided by my professor so I didn't know if he made it publicly available. \$\endgroup\$
    – topeagb
    Oct 1, 2023 at 23:49

1 Answer 1

0
\$\begingroup\$

Part of the problem lies in the part of the code you haven't included in your question.

I am going to assume that the file you import called RTL.svh is the one hosted on Github here.

If I am correct in that you are using the `FF() macro from the aforementioned link. In which case you are using the macro wrong. The arguments to the macro are `FF(data_in, data_out, ...). You are using it as `FF(data_out, data_in, ...) which is causing undefined values to propagate through your design and contention.

Correct the two backwards macro uses in your code and you're one step closer to it doing something sensible.

My advice would be to not use weird obfuscating macros where a nice clear always_ff/always_comb block would do, or if you are desperate use a module which will allow named port connections and avoid these issues.


You also have a separate issue in both your summer and multiplier modules. You've declared the internal register signals as single-bit wires rather than being of the correct width. You've also declared the multiplier output signal to be the wrong width (should be [WIDTH+WIDTH-1:0]). Also the data_in2 signal width of the summer module is the wrong width (should be [WIDTH-1:0]).


As to why the output is always 000, your output is set to data_out = product[0]; and product[0] = h[0] * data_in_reg;. Given that h[0] equals 0, your output is unsurprisingly always 0.

I'm guessing you actually want data_out = sum[NUMBER_OF_TAPS/2-1];.

Furthermore, your simulation is being stopped before all the data has been fed in to the filter by the #1100 $finish; statement in the test bench. Furthermore you have a $finish; just after the data is fed in which also stops the simulation too soon. FIR filters have a lag so it will take some time for the calculated value to propagate through. Modify these to suit.


Correct these and you eventually start getting "values" coming out. No idea if they are the right value, that's up to you to figure out.

Values coming from the simulation.

\$\endgroup\$
3
  • \$\begingroup\$ Oh sorry I used that last line to debug to my code to see what was wrong \$\endgroup\$
    – topeagb
    Oct 1, 2023 at 15:23
  • \$\begingroup\$ @topeagb if you want to monitor internal signals, you can use the . syntax - e.g. adding FIR_0.product[0] to the monitor would print out the value of the product[0] signal inside the instance called FIR_0. You can go as many levels deep as you want. \$\endgroup\$ Oct 1, 2023 at 15:28
  • \$\begingroup\$ I just added a snapshot of my simulation, all the sum and product elements are all 0000 for some reason \$\endgroup\$
    – topeagb
    Oct 1, 2023 at 15:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.