Еще один пример использования MyHDL в Python - реализация фильтра нижних частот. Пример кода:
Полученные коэффициенты фильтра:
И картинка для привлечения внимания: входной сигнал, спектр входного сигнала, выходной сигнал, спектр выходного сигнала
from random import randint
import numpy as np
from myhdl import *
import matplotlib.pyplot as plt
class Cook_book():
def PMC_sum_arg(self, i_arg1, i_arg2):
o_len = 1 + max(len(i_arg1),len(i_arg2))
o_len_signed = o_len-1
return Signal(intbv(0,-2**o_len_signed, 2**o_len_signed))
def PMC_mult_arg(self, i_arg1, i_arg2):
o_len = len(i_arg1) + len(i_arg2)
o_len_signed = o_len-1
return Signal(intbv(0,-2**o_len_signed, 2**o_len_signed))
def PMC_sum(self, i_arg1, i_arg2, o_out):
w_out = self.PMC_sum_arg(i_arg1, i_arg2)
@always_comb
def exits():
o_out.next = w_out
@always_comb
def comb():
w_out.next = i_arg1 + i_arg2
return exits, comb
####w_out
def PMC_mult(self, i_arg1, i_arg2, o_out):
w_out = self.PMC_mult_arg(i_arg1, i_arg2)
@always_comb
def exits():
o_out.next = w_out
@always_comb
def comb():
w_out.next = i_arg1*i_arg2
return exits, comb
def arg_ROM(self, i_adr, CONTENT):
len_content = len(CONTENT)
len_adr = 2**(len(i_adr))
max_width = 0
if len_content > len_adr:
print "arg_ROM WARNING len_content > len_adr"
else:
for i in range(len(CONTENT)):
if CONTENT[i].bit_length() > max_width:
max_width = CONTENT[i].bit_length()
return Signal(intbv(0, -2**max_width, 2**max_width))
def ROM(self, i_clk, i_adr, o_out, CONTENT):
w_out = self.arg_ROM(i_adr, CONTENT)
@always_comb
def exits():
o_out.next = w_out
@always_comb
def comb():
w_out.next = CONTENT[int(i_adr)]
return exits, comb
def shift_arg(self, WIDTH, LEN):
w_signed = WIDTH-1
return [Signal(intbv(0,-2**w_signed, 2**w_signed)) for i in range(LEN)]
def shift_reg(self, i_clk, i_rst, i_en, i_din, o_dout, WIDTH, LEN):
w_signed = WIDTH-1
#o_dout = self.shift_arg(WIDTH, LEN)
r_shift = [Signal(intbv(0,-2**w_signed, 2**w_signed)) for i in range(LEN)]
@always_comb
def exits():
for i in range(LEN):
o_dout[i].next = r_shift[i]
@always(i_clk.posedge, i_rst.negedge)
def seq():
if i_rst == 0:
for i in range(LEN):
r_shift[i].next = 0
elif i_en == 1:
r_shift[0].next = i_din
for i in range(1, LEN):
r_shift[i].next = r_shift[i-1]
return exits, seq
def serial_filter(self, i_clk, i_rst, i_newdata, i_din, o_dout, COEFFS, WIDTH, LEN):
o_out_shift = self.shift_arg(16, len(COEFFS))
uut_shift = self.shift_reg(i_clk, i_rst, i_newdata, i_din, o_out_shift, 16, LEN)
MULT_MSB = 16+16
MULT_WIDTH_SIGNED = 16+16-1
w_mult = [Signal(intbv(0,-2**MULT_WIDTH_SIGNED, 2**MULT_WIDTH_SIGNED)) for i in range(LEN)]
SUM_MSB = MULT_MSB + int(np.log2(LEN))
SUM_WIDTH_SIGNED = MULT_WIDTH_SIGNED + int(np.log2(LEN))
w_sum = Signal(intbv(0, -2**SUM_WIDTH_SIGNED, 2**SUM_WIDTH_SIGNED))
@always_comb
def comb_mult():
for i in range(LEN):
w_mult[i].next = o_out_shift[i] * COEFFS[i]
@always_comb
def comb_sum():
w_sum.next = sum(w_mult)
@always_comb
def exits():
o_dout.next = w_sum[SUM_MSB:SUM_MSB-16].signed()
return uut_shift, comb_mult, comb_sum, exits
from scipy import signal
input_data = []
output_data = []
S_r = 16000.0
Nyq = S_r / 2
Cutoff = 2000.0
clk_rate = 16000.0*16
prescaller = int(clk_rate / S_r)
def tb():
global input_data
global output_data
global S_r
global Nyq
global Cutoff
global precaller
clk = Signal(bool(0))
i_en = Signal(bool(0))
i_rst = Signal(bool(0))
@instance
def clk_gen():
while True:
yield delay(1)
clk.next = not clk
defines = Cook_book()
N = 4
N_signed = N - 1
i_adr = Signal(modbv( 0, 0, 2**N))
n = 2**len(i_adr)
print n
a = signal.firwin(n, cutoff = 0.1, window = "hamming")
fir_coeffs = signal.firwin(n, Cutoff/Nyq)
M = 16-1
CONTENT = [int((-1+2**M)*fir_coeffs[i]) for i in range(n)]
plt.plot(CONTENT, 'r')
print CONTENT
i_din = Signal(intbv(0, -2**M, 2**M))
o_dout = Signal(intbv(0, -2**M, 2**M))
uut = defines.serial_filter(clk, i_rst, i_en, i_din, o_dout, CONTENT, 16, len(CONTENT))
cnt = Signal(intbv(0,0,16))
@instance
def control():
#global prescaller
yield clk.posedge
i_rst.next = 1
yield clk.posedge
yield clk.posedge
yield clk.posedge
i_en.next = 1
while True:
yield clk.posedge
cnt.next = (cnt + 1 ) %16
if cnt.next == 0:
i_en.next = 1
else:
i_en.next = 0
@always(clk.posedge)
def monitor():
if i_en == 1:
tmp = randint(1-2**15, -1+2**15)
input_data.append(tmp)
output_data.append(int(o_dout))
i_din.next = tmp
i_adr.next = i_adr + 1
return clk_gen, monitor, uut, control
inst = traceSignals(tb)
sim = Simulation(inst)
sim.run(2000)
fig, ax = plt.subplots(4,1)
ax[0].plot(input_data)
X_in = np.fft.fft(input_data)
X_in = abs(X_in) / max(abs(X_in))
X_in_db = 20*np.log10(X_in)
ax[1].plot(X_in_db)
ax[2].plot(output_data)
print output_data
X_out = np.fft.fft(output_data)
X_out = abs(X_out) / max(abs(X_out))
X_out_db = 20*np.log10(X_out)
ax[3].plot(X_out_db)
И картинка для привлечения внимания: входной сигнал, спектр входного сигнала, выходной сигнал, спектр выходного сигнала


Комментариев нет:
Отправить комментарий