examples: FIR filter simulation
[litex.git] / examples / fir.py
1 from scipy import signal
2 from math import cos, pi
3
4 from migen.fhdl.structure import *
5 from migen.fhdl import verilog
6 from migen.corelogic.misc import optree
7 from migen.fhdl import autofragment
8 from migen.sim.generic import Simulator
9 from migen.sim.icarus import Runner
10
11 class FIR:
12 def __init__(self, coef, wsize=16):
13 self.coef = coef
14 self.wsize = wsize
15 self.i = Signal(BV(self.wsize, True))
16 self.o = Signal(BV(self.wsize, True))
17
18 def get_fragment(self):
19 muls = []
20 sync = []
21 src = self.i
22 for c in self.coef:
23 sreg = Signal(BV(self.wsize, True))
24 sync.append(sreg.eq(src))
25 src = sreg
26 c_fp = int(c*2**(self.wsize - 1))
27 c_e = Constant(c_fp, BV(bits_for(c_fp), True))
28 muls.append(c_e*sreg)
29 sum_full = Signal(BV(2*self.wsize-1, True))
30 sync.append(sum_full.eq(optree("+", muls)))
31 comb = [self.o.eq(sum_full[self.wsize-1:])]
32 return Fragment(comb, sync)
33
34 class TB:
35 def __init__(self, fir, frequency):
36 self.fir = fir
37 self.frequency = frequency
38 self.inputs = []
39 self.outputs = []
40
41 def do_simulation(self, s):
42 f = 2**(self.fir.wsize - 1)
43 v = 0.1*cos(2*pi*self.frequency*s.cycle_counter)
44 s.wr(self.fir.i, int(f*v))
45 self.inputs.append(v)
46 self.outputs.append(s.rd(self.fir.o)/f)
47
48 def get_fragment(self):
49 return Fragment(sim=[self.do_simulation])
50
51 def main():
52 coef = signal.remez(80, [0, 0.1, 0.1, 0.5], [1, 0])
53 fir = FIR(coef)
54 tb = TB(fir, 0.3)
55 fragment = autofragment.from_local()
56 sim = Simulator(fragment, Runner())
57 sim.run(200)
58 print(tb.inputs)
59 print(tb.outputs)
60
61 main()