FIR数字滤波器实现过程中的RM

        我们在设计好数字滤波器时总会有一个必要的过程,即定点化和数据比对,我们需要设计相应RM(reference model)来生成golden 数据,以便FPGA部署的正确性,即Verilog 仿真结果与RM比对成功才能表面我们的FPGA实现的结果,正是我们想要的FIR数字滤波器。下面是一段简单的python 脚本来对RM编写做一个示例。同时示例代码中还对MATLAB 数据与Python 脚本交互,即读取.mat文件做了一个说明。FIR滤波器设计在传统的数字信号处理中是一项必备的技能,希望能对大家有一定的帮助。

import numpy as np
import math
from scipy.fftpack import fft
import scipy.io as scio
import matplotlib.pyplot as plt

def matlab_round(din):
    """
    python version of the original MATLAB built-in function round
    :param din: input data, must be a real number
    :return dout: output data
    """

    if din >= 0:
        if din - np.floor(din) >= 0.5:
            dout = np.ceil(din)
        else:
            dout = np.floor(din)
    else:
        if din - np.floor(din) > 0.5:
            dout = np.ceil(din)
        else:
            dout = np.floor(din)

    return dout

def matlab_nearest(din):
    """
    python version of the origianl MATLAB built-in function nearest
    :param din: input data, must be a real number
    :return dout: output data
    """

    if din >= 0:
        if din - np.floor(din) >= 0.5:
            dout = np.ceil(din)
        else:
            dout = np.floor(din)
    else:
        if din - np.floor(din) >= 0.5:
            dout = np.ceil(din)
        else:
            dout = np.floor(din)

    return dout

def matlab_fix(din):
    """
    python version of the original MATLAB built-in function fix
    :param din: input data, must be a real number
    :return dout: output data
    """

    if din >= 0:
        dout = np.floor(din)
    else:
        dout = np.ceil(din)

    return dout

def bit_width_process_real(din, cut_bit, cut_type, out_bit, sat_type):
    """
    python version of the original customized MATLAB function bit_width_process_real
    :param din: input data, must be a real number
    :param cut_bit: number of bit to trunc
    :param cut_type: truncation type; 0: round, 1: nearest, 2: floor, 3: fix, 4: unchanged
    :param out_bit: bitwidth of output data
    :param sat_type: saturation type; 0: signed, 1: unsigned, 2: symmetric
    :return dout: output data
    :return ovf: overflow flag; 0: not overflowed, 1: overflowed
    """

    # cut
    if cut_type == 0:
        cut_out = matlab_round(din / math.pow(2, cut_bit))
    elif cut_type == 1:
        cut_out = matlab_nearest(din / math.pow(2, cut_bit))
    elif cut_type == 2:
        cut_out = np.floor(din / math.pow(2, cut_bit))  # numpy.floor is equivalent to MATLAB built-in function floor
    elif cut_type == 3:
        # cut_out = np.fix(din / math.math.pow(2, cut_bit))
        cut_out = matlab_fix(din / math.pow(2, cut_bit))
    else:
        cut_out = din

    # saturation
    if sat_type == 0:
        max_value = math.pow(2, out_bit - 1) - 1
        min_value = -math.pow(2, out_bit - 1)
    elif sat_type == 1:
        max_value = math.pow(2, out_bit) - 1
        min_value = 0
    else:
        max_value = math.pow(2, out_bit - 1) - 1
        min_value = -max_value

    if cut_out < min_value:
        dout = min_value
        ovf = 1
    elif cut_out > max_value:
        dout = max_value
        ovf = 1
    else:
        dout = cut_out
        ovf = 0

    return dout, ovf

def bit_width_process_cplx(din_iq, cut_bit, cut_type, out_bit, sat_type):
    """
    python version of the original customized MATLAB function bit_width_process, but ONLY process complex data
    :param din_iq: input data, must be a complex number
    :param cut_bit: number of bit to trunc
    :param cut_type: truncation type; 0: round, 1: nearest, 2: floor, 3: fix, 4: unchanged
    :param out_bit: bitwidth of output data
    :param sat_type: saturation type; 0: signed, 1: unsigned, 2: symmetric
    :return: dout: output data
    :return: ovf: overflow flag; 0: not overflowed, 1: overflowed
    """
    dout_i, ovf_i = bit_width_process_real(np.real(din_iq), cut_bit, cut_type, out_bit, sat_type)
    dout_q, ovf_q = bit_width_process_real(np.imag(din_iq), cut_bit, cut_type, out_bit, sat_type)

    dout_iq = complex(dout_i, dout_q)
    ovf = ovf_i or ovf_q

    return dout_iq, ovf

def print2dat_qi(data=0, bw=16, name="file"):
    """
    :param data:打印数据
    :param bw:  位宽
    :param name:打印文件名称
    """
    data_qi = []
    file = str(name + ".dat")
    bwhex = np.ceil(bw / 4)
    modbw = 4 - np.mod(bw, 4)
    with open(file, "w") as f:
        pass
    with open(file, "a") as f:
        for i in range(len(data)):
            if isinstance(data[i, 0], complex):
                # data_rnd = complex(round_new(data[i].real), round_new(data[i].imag))
                data_rnd = data[i, 0]
                data_i = data_rnd.real
                data_q = data_rnd.imag
                if data_i < 0:
                    data_i =  data_i + 2 ** bw
                else:
                    data_i =  data_i

                if data_q < 0:
                    data_q =  data_q + 2 ** bw
                else:
                    data_q =  data_q

                if modbw == 4:
                    bwhexh = bwhex
                    bwhexl = bwhex
                else:
                    data_i = np.mod(data_q, 2 ** modbw) * 2 ** bw + data_i  # 高Q低I
                    data_q = np.floor(data_q / 2 ** modbw)
                    bwhexh = int(np.ceil((bw - modbw) / 4))
                    bwhexl = int(bwhex)

                data_str = "%0" + str(bwhexh) + "x%0" + str(bwhexl) + "x" + "\n"
                f.write(data_str % (int(data_q), int(data_i)))

            else:
                # data_rnd = round_new(data[i])
                data_rnd = data[i,0]
                if data_rnd < 0:
                    data_qi =  data_rnd + 2 ** bw
                else:
                    data_qi =  data_rnd
                data_str = "%0" + str(bwhex) + "x\n"
                f.write(data_str % int(data_qi))

coefFile = './coef_light_fix.mat' //Relative path of FIR fixed coefficients
dataFile = './sign_fix.mat' //Relative path of FIR fixed data in
sign_fix = scio.loadmat(dataFile)
print(sign_fix)
signal_data = sign_fix['sigin_fix']
coef_tmp = scio.loadmat(coefFile)
coef = coef_tmp['coef_light_fix']
signal_data_flatten = signal_data.flatten()
fir_in = signal_data_flatten[32767:32767+8192]
coef_in =  coef.flatten()
intp = 2
fir_in_intp2=np.zeros(len(fir_in)+(len(fir_in)-1)*intp,dtype=complex)
fir_in_intp2[::intp+1]=fir_in

fir_out_3p = np.convolve(fir_in_intp2,coef_in,'same')
# sat 8 bit rnd 15 bit
data_len = len(fir_out_3p)
hbf_cut_sat = np.zeros(data_len, dtype= complex)
ovf = np.zeros(data_len, dtype= int)
for i in range(data_len):
    hbf_cut_sat[i],ovf[i] = bit_width_process_cplx(fir_out_3p[i],15,1,16,0)

coef_in = coef_in*4
print2dat_qi(np.array([hbf_cut_sat[0::2]]).T, 16, "cp_fir_3p2p_out_16bit_0")
print2dat_qi(np.array([hbf_cut_sat[1::2]]).T, 16, "cp_fir_3p2p_out_16bit_1")
print2dat_qi(np.array([hbf_cut_sat]).T, 16, "cp_fir_3p2p_out_16bit_full")
print2dat_qi(np.array([coef_in]).T, 18, "coef_18bit")
print2dat_qi(np.array([fir_in]).T, 16, "fir_in_16bit")



fir_out_3p_0 = np.convolve(fir_in_intp2[1::],coef_in,'same')
fir_out_3p_1 = np.convolve(fir_in_intp2[2::],coef_in,'same')
data_len_0 = len(fir_out_3p_0)
hbf_cut_sat_0 = np.zeros(data_len_0, dtype= complex)
data_len_1 = len(fir_out_3p_1)
hbf_cut_sat_1 = np.zeros(data_len_1, dtype= complex)
for i in range(data_len_0):
    hbf_cut_sat_0[i] = bit_width_process_cplx(fir_out_3p_0[i],15,1,16,0)[0]
for i in range(data_len_1):
    hbf_cut_sat_1[i] = bit_width_process_cplx(fir_out_3p_1[i],15,1,16,0)[0]

print2dat_qi(np.array([hbf_cut_sat_0]).T, 16, "cp_fir_3p2p_out_16bit_full_p0")
print2dat_qi(np.array([hbf_cut_sat_1]).T, 16, "cp_fir_3p2p_out_16bit_full_p1")


data_reshape = fir_in.reshape((4096,2))
data_zeros = np.zeros((4096,1))
data_2to3 = np.hstack((data_reshape,data_zeros))
data_2to3_f = data_2to3.flatten()
print2dat_qi(np.array([data_2to3_f]).T, 16, "fir_in_16bit_2to3")

coef_in_3i  = coef_in[0::3]
coef_in_3i1 = coef_in[1::3]
coef_in_3i2 = coef_in[2::3]
# coef_368 = coef_in_3i + coef_in_3i1
coef_368 = coef_in_3i

fir_out_368 = np.convolve(data_2to3_f,coef_in,'full')
# sat 8 bit rnd 15 bit
data_len_368 = len(fir_out_368)
hbf_cut_sat_368 = np.zeros(data_len_368, dtype= complex)
for i in range(data_len_368):
    hbf_cut_sat_368[i] = bit_width_process_cplx(fir_out_368[i],15,1,16,0)[0]
print2dat_qi(np.array([hbf_cut_sat_368]).T, 16, "fir_out_368_16b")
print('hello world')

<think>好的,用户想了解CIC滤波器IP核在FPGA或其他硬件设计中的实现细节、使用方法和购买来源。首先,我需要回忆CIC滤波器的基本概念,以及它在FPGA中的应用场景。CIC滤波器通常用于多速率信号处理,比如抽取和插值,这在数字信号处理中很常见,比如通信系统和音频处理。 接下来,用户提到的IP核,应该是指FPGA厂商提供的预先设计好的CIC滤波器模块,比如Xilinx的Vivado中的CIC IP核或者Intel FPGA的Quartus中的相关IP。这些IP核可以简化设计流程,节省开发时间。 需要回答实现细节,可能包括配置参数、接口说明、时序要求等。使用方法可能涉及IP核的例化、参数设置、仿真测试等步骤。购买来源的话,通常这些IP核是FPGA厂商自带的,用户可能需要购买相应的开发工具或许可证,不过具体情况可能因厂商而异。 然后,我需要参考用户提供的引用内容。引用1和2提到了Vivado的CIC滤波器设计案例,说明Xilinx的FPGA有相关的IP核。引用3讨论了多级CIC滤波器的设计考虑,比如通带衰减的问题,这可能在使用IP核时需要注意的参数设置。 用户可能还想知道如何选择合适的参数,比如级数、抽取/插值因子,以及如何评估性能。此外,应用场景如软件无线电、雷达系统等也是重要的点。 需要确保回答结构清晰,分点说明实现方法、参数配置、应用场景和资源获取。同时生成相关的问题,帮助用户进一步探索。 最后,检查是否符合系统级指令:使用正确的中文,LaTeX格式,引用标识正确,生成相关问题等。确保引用的内容自然融入回答,比如在讨论参数设计时引用[^3]关于级数影响的内容。</think>### CIC滤波器IP核的FPGA实现与应用 #### 一、CIC滤波器IP核的硬件实现细节 CIC(级联积分梳状)滤波器是一种高效的多速率滤波器,常用于数字信号处理的抽取(Decimation)和插值(Interpolation)场景。在FPGA中,CIC滤波器IP核通过预定义模块简化设计流程,其实现细节包括: 1. **参数配置** - **抽取/插值因子(R)**:决定速率转换倍数,需满足$R \geq 1$[^2]。 - **滤波器级数(N)**:级数增加会提升阻带衰减,但通带范围变窄,需平衡性能需求[^3]。 - **位宽扩展**:输出位宽需根据输入位宽$B$和级数计算,公式为$B_{\text{max}} = B + N \cdot \log_2(RM)$($M$为差分延迟)[^2]。 2. **接口与时序** - 输入/输出接口支持AXI-Stream或并行数据总线。 - 时序需满足多速率要求,抽取模式下输出时钟频率降为$f_s/R$,插值模式下升为$f_s \cdot R$[^1]。 3. **资源占用** - CIC滤波器无需乘法器,仅用加法器和寄存器,适合FPGA高效实现。 --- #### 二、IP核使用方法(以Xilinx Vivado为例) 1. **IP核调用** 在Vivado中通过IP Catalog搜索**CIC Compiler**,配置参数后生成HDL代码。 2. **关键配置项** ```verilog // 示例:5倍抽取、3级滤波器 cic_compiler_0 cic_inst ( .aclk(clk), // 输入时钟 .s_axis_data_tdata(data_in),// 输入数据 .m_axis_data_tdata(data_out)// 输出数据 ); ``` 3. **仿真验证** 使用MATLAB或Vivado Simulator验证频率响应,确保阻带衰减满足要求(例如50kHz信号衰减41dB[^2])。 --- #### 三、应用场景 1. **软件无线电(SDR)**:用于基带信号的速率转换与抗混叠滤波。 2. **雷达信号处理**:实现脉冲压缩前的数据降采样。 3. **音频处理**:在Δ-Σ ADC/DAC中完成插值与噪声整形[^1]。 --- #### 四、IP核获取途径 1. **FPGA厂商原生IP** - **Xilinx**:Vivado工具内置CIC Compiler IP核(需购买Vivado许可证)[^1]。 - **Intel FPGA**:通过Quartus的FIR Compiler II支持CIC模式。 2. **第三方IP提供商** - **Analog Devices**:提供针对高速数据采集的优化IP核。 3. **开源实现** - GitHub等平台有Verilog/VHDL开源CIC代码,但需自行验证功能。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值