1 # Copyright (C) 2012 Vermeer Manufacturing Co.
2 # License: GPLv3 with additional permissions (see README).
4 from math
import cos
, pi
5 from scipy
import signal
7 from migen
.fhdl
.structure
import *
8 from migen
.fhdl
import verilog
9 from migen
.corelogic
.misc
import optree
10 from migen
.fhdl
import autofragment
11 from migen
.sim
.generic
import Simulator
12 from migen
.sim
.icarus
import Runner
14 # A synthesizable FIR filter.
16 def __init__(self
, coef
, wsize
=16):
19 self
.i
= Signal(BV(self
.wsize
, True))
20 self
.o
= Signal(BV(self
.wsize
, True))
22 def get_fragment(self
):
27 sreg
= Signal(BV(self
.wsize
, True))
28 sync
.append(sreg
.eq(src
))
30 c_fp
= int(c
*2**(self
.wsize
- 1))
31 c_e
= Constant(c_fp
, BV(bits_for(c_fp
), True))
33 sum_full
= Signal(BV(2*self
.wsize
-1, True))
34 sync
.append(sum_full
.eq(optree("+", muls
)))
35 comb
= [self
.o
.eq(sum_full
[self
.wsize
-1:])]
36 return Fragment(comb
, sync
)
38 # A test bench for our FIR filter.
39 # Generates a sine wave at the input and records the output.
41 def __init__(self
, fir
, frequency
):
43 self
.frequency
= frequency
47 def do_simulation(self
, s
):
48 f
= 2**(self
.fir
.wsize
- 1)
49 v
= 0.1*cos(2*pi
*self
.frequency
*s
.cycle_counter
)
50 s
.wr(self
.fir
.i
, int(f
*v
))
52 self
.outputs
.append(s
.rd(self
.fir
.o
)/f
)
54 def get_fragment(self
):
55 return Fragment(sim
=[self
.do_simulation
])
58 # Compute filter coefficients with SciPy.
59 coef
= signal
.remez(80, [0, 0.1, 0.1, 0.5], [1, 0])
62 # Combine the FIR filter with its test bench.
63 fragment
= autofragment
.from_local()
64 sim
= Simulator(fragment
, Runner())
66 # Print data from the input and output waveforms.
67 # When matplotlib works easily with Python 3, we could
68 # display them graphically here.