# Biquad filter produces garbage (solved)

**URL:** <https://discourse.myhdl.org/t/biquad-filter-produces-garbage-solved/261>\
**Category:** Support\
**Created:** [March 29, 2018, 8:38am UTC](https://discourse.myhdl.org/t/biquad-filter-produces-garbage-solved/261 "2018-03-29T08:38:06Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mhavu](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/mhavu/32/86_2.png) [@mhavu](https://discourse.myhdl.org/u/mhavu)\
**Post date:** [March 29, 2018, 8:38am UTC](https://discourse.myhdl.org/t/biquad-filter-produces-garbage-solved/261/1 "2018-03-29T08:38:06Z")

</div>

I’ve been having trouble with the stability of my biquad filter implementation for quite some time now. Today I finally created the following minimal test to find out what is going on. For some reason, looping with _biquad1_ works just fine, while the MyHDL implementation (_biquad2_) produces garbage. Can someone spot what’s wrong here? I’m using MyHDL 0.9.0.

```auto
from myhdl import instance, always_seq, intbv, modbv, delay
from myhdl import ResetSignal, Signal, Simulation, StopSimulation
import matplotlib.pyplot as plt
import numpy as np

b0, b1, b2, a1, a2 = 0x00083371, 0x001066e2, 0x00083371, 0xc172a282, 0x1e9590ee
    
def biquad1(y1, y2):
    """Step response for direct form I biquad filter"""
    return int(intbv(((b0 + b1 + b2) >> 1) -
                     ((intbv(a1)[32:].signed() * intbv(int(y1))[32:].signed()) >> 29) -
                     ((intbv(a2)[32:].signed() * intbv(int(y2))[32:].signed()) >> 29))[32:])

def biquad2(clk, reset, y):
    """Step response for direct form I biquad filter (MyHDL)"""
    y1 = Signal(y.val)
    y2 = Signal(y.val)
    
    @always_seq(clk.posedge, reset=reset)
    def logic():
        y1.next = y
        y2.next = y1
        y.next = int(intbv(((b0 + b1 + b2) >> 1) -
                     ((intbv(a1)[32:].signed() * intbv(int(y1))[32:].signed()) >> 29) -
                     ((intbv(a2)[32:].signed() * intbv(int(y2))[32:].signed()) >> 29))[32:])

    return logic

def testbench():
    clk = Signal(bool(0))
    reset = ResetSignal(0, active=1, async=True)
    out = Signal(modbv(0)[32:])
    filter = biquad2(clk, reset, out)
    
    @instance
    def generate():
        y = np.zeros(250, dtype='uint32')
        for i in range(500):
            yield delay(1)
            clk.next = not clk
            if clk:
                y[i // 2] = out
        plt.plot(y / 2**30)
        raise StopSimulation
            
    return generate, filter

if __name__ == " __main__":
    tb = testbench()
    Simulation(tb).run()

    y = np.zeros(252, dtype='uint32')
    for i in range(2, 252):
        y[i] = biquad1(y[i-1], y[i-2])
    plt.plot(y[2:] / 2**30)

```

I know the _y.next_ assignment looks funny, but it is the way it is to make the two functions as identical as possible.

---

<div class="post-metadata">

**Author:** ![josyb](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/josyb/32/5_2.png) [@josyb](https://discourse.myhdl.org/u/josyb)\
**Post date:** [March 29, 2018, 9:26am UTC](https://discourse.myhdl.org/t/biquad-filter-produces-garbage-solved/261/2 "2018-03-29T09:26:46Z")

</div>

I think this does what you intended:

```python
def biquad2(clk, reset, y):
    """Step response for direct form I biquad filter (MyHDL)"""
    y1 = Signal(y.val)
    y2 = Signal(y.val)
    
    @always_seq(clk.posedge, reset=reset)
    def logic():
# y1.next = y
        y2.next = y1
        y1.next = int(intbv(((b0 + b1 + b2) >> 1) - 
                     ((intbv(a1)[32:].signed() * intbv(int(y1))[32:].signed()) >> 29) - 
                     ((intbv(a2)[32:].signed() * intbv(int(y2))[32:].signed()) >> 29))[32:])

    @always_comb
    def assign():
        y.next = y1
        
    return logic, assign

```

---

<div class="post-metadata">

**Author:** ![mhavu](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/mhavu/32/86_2.png) [@mhavu](https://discourse.myhdl.org/u/mhavu)\
**Post date:** [March 29, 2018, 10:36am UTC](https://discourse.myhdl.org/t/biquad-filter-produces-garbage-solved/261/3 "2018-03-29T10:36:55Z")

</div>

Thanks! Indeed it does, although I can’t quite wrap my head around why the two aren’t equivalent. Makes me wonder whether I have similar structures in my other modules.

---

<div class="post-metadata">

**Author:** ![josyb](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/josyb/32/5_2.png) [@josyb](https://discourse.myhdl.org/u/josyb)\
**Post date:** [March 29, 2018, 5:35pm UTC](https://discourse.myhdl.org/t/biquad-filter-produces-garbage-solved/261/4 "2018-03-29T17:35:28Z")

</div>

You simulation fills the result vector at both clock edges:  
This produces two identical plots:

```python
'''
Created on 29 mrt. 2018

@author: mhavu / josy
'''

from myhdl import instance, always_seq, intbv, modbv, delay
from myhdl import ResetSignal, Signal, Simulation, StopSimulation
import matplotlib.pyplot as plt
import numpy as np
from myhdl._always_comb import always_comb

b0, b1, b2, a1, a2 = 0x00083371, 0x001066e2, 0x00083371, 0xc172a282, 0x1e9590ee

    
def biquad1(y1, y2):
    """Step response for direct form I biquad filter"""
    return int(intbv(((b0 + b1 + b2) >> 1) - 
                     ((intbv(a1)[32:].signed() * intbv(int(y1))[32:].signed()) >> 29) - 
                     ((intbv(a2)[32:].signed() * intbv(int(y2))[32:].signed()) >> 29))[32:])

def biquad2(clk, reset, y):
    """Step response for direct form I biquad filter (MyHDL)"""
    y1 = Signal(y.val)
    y2 = Signal(y.val)
    
    @always_seq(clk.posedge, reset=reset)
    def logic():
# y1.next = y
        y2.next = y1
        y1.next = int(intbv(((b0 + b1 + b2) >> 1) - 
                     ((intbv(a1)[32:].signed() * intbv(int(y1))[32:].signed()) >> 29) - 
                     ((intbv(a2)[32:].signed() * intbv(int(y2))[32:].signed()) >> 29))[32:])

    @always_comb
    def assign():
        y.next = y1
        
    return logic, assign

def testbench():
    clk = Signal(bool(0))
    reset = ResetSignal(0, active=1, async=True)
    out = Signal(modbv(0)[32:])
    
    bqf = biquad2(clk, reset, out)
    
    @instance
    def genclk():
        while True:
            yield delay(1)
            clk.next = not clk
        
    @instance
    def generate():
        y = np.zeros(250, dtype='uint32')
        for i in range(250):
            yield clk.posedge
            y[i] = out
        plt.plot(y / 2 ** 30)
        plt.show()

        raise StopSimulation
            
    return genclk, generate, bqf

if __name__ == " __main__":
    tb = testbench()
    Simulation(tb).run()

    y = np.zeros(250, dtype='uint32')
    for i in range(2, 250):
        y[i] = biquad1(y[i - 1], y[i - 2])
    plt.plot(y / 2 ** 30)
    plt.show()

```

---

<div class="post-metadata">

**Author:** ![mhavu](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/mhavu/32/86_2.png) [@mhavu](https://discourse.myhdl.org/u/mhavu)\
**Post date:** [April 1, 2018, 8:34pm UTC](https://discourse.myhdl.org/t/biquad-filter-produces-garbage-solved/261/5 "2018-04-01T20:34:12Z")

</div>

Yeah, I noticed that when I tried your answer. Hence I edited the plotting code before I responded. I’m still having trouble understanding why the _@always\_comb_ block is necessary, and why the two aren’t equivalent.

---

<div class="post-metadata">

**Author:** ![DrPi](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/drpi/32/36_2.png) [@DrPi](https://discourse.myhdl.org/u/DrPi)\
**Post date:** [April 4, 2018, 7:05am UTC](https://discourse.myhdl.org/t/biquad-filter-produces-garbage-solved/261/6 "2018-04-04T07:05:07Z")

</div>

> [@mhavu](#):
>
> I’m still having trouble understanding why the @always\_comb block is necessary, and why the two aren’t equivalent.

In the following picture, the top diagram is a representation of your code. The bottom diagram is the representation of Josy code.  
 ![image](https://canada1.discourse-cdn.com/flex030/uploads/myhdl/original/1X/db5e437febca16f47c323acfb79dd2964bfb62a9.png)

---

<div class="post-metadata">

**Author:** ![mhavu](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.myhdl.org/mhavu/32/86_2.png) [@mhavu](https://discourse.myhdl.org/u/mhavu)\
**Post date:** [April 5, 2018, 7:15am UTC](https://discourse.myhdl.org/t/biquad-filter-produces-garbage-solved/261/7 "2018-04-05T07:15:19Z")

</div>

Thanks for the wonderful diagrams @DrPi! So there was an extra delay there. I suspected it, but couldn’t see where, no matter how hard I thought about it. Goes to show once again how useful schematics and diagrams are.
