2015-09-12 07:34:07 -04:00
|
|
|
from functools import reduce
|
|
|
|
from operator import add
|
|
|
|
|
2012-03-08 14:49:36 -05:00
|
|
|
from math import cos, pi
|
2012-03-10 13:38:39 -05:00
|
|
|
from scipy import signal
|
2012-06-07 17:20:59 -04:00
|
|
|
import matplotlib.pyplot as plt
|
2012-03-08 14:49:36 -05:00
|
|
|
|
2015-09-12 07:34:07 -04:00
|
|
|
from migen import *
|
2012-03-08 14:49:36 -05:00
|
|
|
from migen.fhdl import verilog
|
|
|
|
|
2015-04-13 14:45:35 -04:00
|
|
|
|
2012-03-10 13:38:39 -05:00
|
|
|
# A synthesizable FIR filter.
|
2013-03-19 06:46:27 -04:00
|
|
|
class FIR(Module):
|
2015-04-13 14:07:07 -04:00
|
|
|
def __init__(self, coef, wsize=16):
|
|
|
|
self.coef = coef
|
|
|
|
self.wsize = wsize
|
|
|
|
self.i = Signal((self.wsize, True))
|
|
|
|
self.o = Signal((self.wsize, True))
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2015-04-13 14:07:07 -04:00
|
|
|
###
|
2013-03-19 06:46:27 -04:00
|
|
|
|
2015-04-13 14:07:07 -04:00
|
|
|
muls = []
|
|
|
|
src = self.i
|
|
|
|
for c in self.coef:
|
|
|
|
sreg = Signal((self.wsize, True))
|
|
|
|
self.sync += sreg.eq(src)
|
|
|
|
src = sreg
|
|
|
|
c_fp = int(c*2**(self.wsize - 1))
|
|
|
|
muls.append(c_fp*sreg)
|
|
|
|
sum_full = Signal((2*self.wsize-1, True))
|
2015-09-10 16:56:56 -04:00
|
|
|
self.sync += sum_full.eq(reduce(add, muls))
|
2015-09-11 00:44:14 -04:00
|
|
|
self.comb += self.o.eq(sum_full >> self.wsize-1)
|
2012-03-08 14:49:36 -05:00
|
|
|
|
2015-04-13 14:45:35 -04:00
|
|
|
|
2012-03-10 13:38:39 -05:00
|
|
|
# A test bench for our FIR filter.
|
|
|
|
# Generates a sine wave at the input and records the output.
|
2015-09-11 00:44:14 -04:00
|
|
|
def fir_tb(dut, frequency, inputs, outputs):
|
|
|
|
f = 2**(dut.wsize - 1)
|
|
|
|
for cycle in range(200):
|
|
|
|
v = 0.1*cos(2*pi*frequency*cycle)
|
|
|
|
yield dut.i, int(f*v)
|
|
|
|
inputs.append(v)
|
|
|
|
outputs.append((yield dut.o)/f)
|
|
|
|
yield
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2012-03-08 14:49:36 -05:00
|
|
|
|
2014-01-26 16:19:43 -05:00
|
|
|
if __name__ == "__main__":
|
2015-04-13 14:07:07 -04:00
|
|
|
# Compute filter coefficients with SciPy.
|
|
|
|
coef = signal.remez(30, [0, 0.1, 0.2, 0.4, 0.45, 0.5], [0, 1, 0])
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2015-04-13 14:07:07 -04:00
|
|
|
# Simulate for different frequencies and concatenate
|
|
|
|
# the results.
|
|
|
|
in_signals = []
|
|
|
|
out_signals = []
|
|
|
|
for frequency in [0.05, 0.1, 0.25]:
|
2015-09-11 00:44:14 -04:00
|
|
|
dut = FIR(coef)
|
|
|
|
tb = fir_tb(dut, frequency, in_signals, out_signals)
|
|
|
|
Simulator(dut, tb).run()
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2015-04-13 14:07:07 -04:00
|
|
|
# Plot data from the input and output waveforms.
|
|
|
|
plt.plot(in_signals)
|
|
|
|
plt.plot(out_signals)
|
|
|
|
plt.show()
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2015-04-13 14:07:07 -04:00
|
|
|
# Print the Verilog source for the filter.
|
|
|
|
fir = FIR(coef)
|
|
|
|
print(verilog.convert(fir, ios={fir.i, fir.o}))
|