Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A basic direct form I FIR filter and tests #4

Merged
merged 3 commits into from Jun 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 37 additions & 0 deletions filter_blocks/fda/fir_test.py
@@ -0,0 +1,37 @@
import myhdl as hdl
from filter_blocks.support import Samples
from .filter_hw import FilterHardware
from ..fir import fir_df1

class FIRFilter(FilterHardware):
def __init__(self, b, a):
super().__init__(b, a)
self.filter_type = 'direct_form'
self.n_cascades = 0
self.direct_form_type = 1

def set_cascade(self, n_cascades):
self.n_cascades = n_cascades

@hdl.block
def filter_block(self, glbl, sigin, sigout, b, w):
# this elaboration code will select the different structure and implementations
xt = Samples(sigin.min, sigin.max)
yt = Samples(sigout.min, sigout.max)
xt.data = sigin.val
xt.valid = bool(1)
if self.filter_type == 'direct_form':
if self.direct_form_type == 1:
# all filters will need the same interface ports, this should be do able
dfilter = fir_df1.filter_fir

if self.n_cascades > 0:
filter_insts = [None for _ in range(self.n_cascades)]
for ii in range(self.n_cascades):
filter_insts[ii] = fir_df1.filter_fir(
glbl, sigin[ii], sigout[ii], b
)
else:
filter_insts = dfilter(glbl, xt, yt, b)

return filter_insts
69 changes: 69 additions & 0 deletions filter_blocks/fir/fir_df1.py
@@ -0,0 +1,69 @@
import myhdl as hdl
from myhdl import Signal, intbv, always_seq

from filter_blocks.support import Samples, Signals

@hdl.block
def filter_fir(glbl, sigin, sigout, b, shared_multiplier=False):
"""Basic FIR direct-form I filter.

Ports:
glbl (Global): global signals.
sigin (SignalBus): input digital signal.
sigout (SignalBus): output digitla signal.

Args:
b (tuple, list): numerator coefficents.

Returns:
inst (myhdl.Block, list):
"""
assert isinstance(sigin, Samples)
assert isinstance(sigout, Samples)
assert isinstance(b, tuple)
# All the coefficients need to be an `int`

rb = [isinstance(bb, int) for bb in b]
assert all(rb)

w = sigin.word_format
ymax = 2**(w[0]-1)
vmax = 2**(2*w[0]) # double width max and min
vmin = -vmax
ymin = -ymax
N = len(b)-1
clock, reset = glbl.clock, glbl.reset
xdv = sigin.valid
y, ydv = sigout.data, sigout.valid
x = Signal(intbv(0, min=vmin, max=vmax))
# Delay elements, list-of-signals
ffd = Signals(intbv(0, min=ymin, max=ymax), N)
yacc = Signal(intbv(0, min=vmin, max=vmax)) #verify the length of this
dvd = Signal(bool(0))

@hdl.always(clock.posedge)
def beh_direct_form_one():
if sigin.valid:
x.next = sigin.data

for i in range(N-1):
ffd[i+1].next = ffd[i]

ffd[0].next = x
# sum-of-products loop
c = b[0]
sop = x*c

for ii in range(N):
c = b[ii+1]
sop = sop + (c * ffd[ii])
yacc.next = sop
print(yacc)

@always_seq(clock.posedge, reset=reset)
def beh_output():
dvd.next = xdv
y.next = yacc.signed()
ydv.next = dvd

return beh_direct_form_one, beh_output
36 changes: 36 additions & 0 deletions tests/test_fir/test.txt
@@ -0,0 +1,36 @@
1
2
1
3
4
10
20
10
1
2
3
5
3
6
15
14
10
1
1
2
3
4
1
4
5
23
30
35
20
10
5
6
7
1
2
3
37 changes: 37 additions & 0 deletions tests/test_fir/test_df1.py
@@ -0,0 +1,37 @@
import myhdl as hdl
from myhdl import Signal, intbv, StopSimulation
from filter_blocks.support import Clock, Reset, Global
from filter_blocks.fir import fir_df1
from filter_blocks.fda import fir_test as ft

@hdl.block
def test_fir_df1():
clock = Clock(0, frequency=50e6)
reset = Reset(0, active=0, async=True)
glbl = Global(clock, reset)
tbclk = clock.process()
x = Signal(intbv(0)[8:])
y = Signal(intbv(0)[8:])
a = (1)
b = (1, 2, 1)
w = (24, 23, 0)
fir_test = ft.FIRFilter(b, a)
fir = fir_test.filter_block(glbl, x, y, b, w)

@hdl.instance
def stimulus():
"input for test bench taken from text file test.txt"
for line in open('test.txt'):
x.next = int(line)
yield clock.posedge
raise StopSimulation

return fir, stimulus, tbclk

def main():
test_bench = test_fir_df1()
test_bench.run_sim()


if __name__ == '__main__':
main()