寻找薛定谔的猫

V1

2022/01/06阅读:99主题:默认主题

基于数字IC的下采样CIC滤波器设计(上)

下采样CIC滤波器设计需求

在本章节中,分别介绍了基于数字IC的下采样CIC滤波器(以下均称为CIC滤波器)实现设计思路。关于CIC滤波器的设计需求如下。 在设计数字IC的IP核时,尤其在数字信号处理IP核设计时,往往需要根据数据的输入速率、时钟速率对电路的结构进行优化,从而在满足时序、速率要求的同时,达到最小的设计面积。为此,我们需要充分考虑输入信号的速率以及时钟周期,以期减少计算冗杂及电路冗杂。而设计CIC滤波器IP核时,也是需要遵循面积、速率及功耗最优化原则。在本文中详细介绍了两种CIC滤波器的设计思路——采样率低于时钟主频和采样率等于时钟主频的CIC滤波器IP核设计。 如上图所示,为本设计的CIC滤波器结构图。首先,为了避免计算过程中的数据溢出问题,我们需要确定CIC滤波器的位数,根据前面章节介绍的式子可以计算出CIC滤波器的位宽。

所以,在理论上该滤波器共有10个32位的加法器和10个32位寄存器组成,电路结构相对简单。但是在实际设计中,32位的加法器占用了较多的逻辑资源,为此我们可以通过复用的方式减少系统中的加法器。

下采样CIC滤波器IP核设计思路

若信号的采样率为2M,系统的时钟频率为4M,我们先计算一下采样率与时钟的关系,即通过计算时钟频率与采样率之间的倍数关系。计算可得

时钟频率是信号采样频率的2倍。比较数据可知, 2小于5,且2小于10。若采用一个或两个加法器,无法在两个时钟内完成积分器的运算。鉴于此,我们可以考虑采用三个加法器实现CIC滤波器的设计。为了便于描述,我们对加法器分别命名为:加法器A、加法器B和加法器C。其中,加法器A和加法器B为32位的加法器,加法器C为33位的加法器。 如上图所示,我们主要对加法器使用时分复用的思想实现:加法器A实现积分器第1和第2个加法运算;加法器B实现积分器第3和第4个加法运算;加法器C实现积分器第5个加法运算和五次梳状滤波器运算。但是,上图所示的电路结构的积分器部分是无法实现加法器的时分复用的。

在对CIC滤波器的结构进行改进之前,我们先介绍一下线性系统的结合律。如下图所示,假设输入信号序列为 ,则有输出信号 满足如下表达式。下式表明, 的先后位置并不影响系统的输出结果。

鉴于以上所述,我们对CIC滤波器积分器部分的结构做一定的改进。如下图所示(上),我们在数据输入前加入4个延时。加入四个延时后,并不会对信号的输出特性造成影响。然后我们根据上述所介绍的线性系统的结合律对加入四个延时后的CIC滤波器积分器部分进行等效变换,可得如下图所示(中间)的新型CIC滤波器积分器部分结构。然后我们再将延时(寄存器)进行合并,可以得到如下图所示的最终CIC滤波器积分器部分结构。

通过上述所述,将CIC滤波器微分器与变化后的加分器合并起来,可以得到如下图所示的新型的CIC滤波器结构图。在该结构图下,我们可以有效地使用三个加法器的思路实现CIC滤波器的设计。 但是,若信号的采样率为4M,系统的时钟频率为4M,此时在CIC滤波器的积分器部分无法通过加法器的时分复用来降低系统面积。所以,在该设计需求下,需要使用5个加法器和1个减法器。但是,若采用传统的CIC滤波器结构,组合逻辑路径过长的情况。如下图所示,组合逻辑路径共有5个32位加法器的串行运算。这种现象,若是在时钟速率较高的情况下,会出现时序问题。为了避免时序问题的出现,我们将采样率为4M且系统的时钟频率为4M的CIC滤波器的结构也是采用如上图所示的新型CIC滤波器结构。

CIC滤波器模型验证

在面的叙述中,我们根据数字线性系统的结合律,给出了新型的CIC滤波器结构。虽然该结构具有足够的理论,但是在实际应用前,还需要建立matlab模型,对该CIC滤波器结构进行验证。建立CIC滤波器模型的主要目的具有以下两个方面:

  • 验证修改后的CIC模型的正确;
  • 生成后期RTL调试所需的原始数据及对比数据。

鉴于此,提供了三个函数,分别是:原型CIC滤波器结构(cic_module_front_to_back.m)函数、变型CIC滤波器结构(cic_module_back_to_ front.m)函数、位数钳制函数(binary_num_clam.m)和主函数。

其中,原型CIC滤波器结构(cic_module_front_to_back.m)函数是变型之前传统的CIC滤波器。该函数主要起到模型验证作用,将输入信号输送到cic_module_front_to_back函数之后得到的输出数据,与将输入信号输送到cic_module_back_to_ front函数之后得到的输出数据进行比较,若相等,则表明变型CIC滤波器结构是正确的。关于原型CIC滤波器结构函数matlab代码如下所示

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  Author       :     Scat Lin
%  Function     :     cic_module_front_to_back.m
%  Description  :     cic滤波器模型,5级CIC,16倍降采样,积分器从前向后计算
%  Inputs       :
%                     cic 滤波器
%                     x input signal
%                     N 滤波器级数
%                     M 滤波器阶数
%                     Dv 抽值倍数
%                     bit_num 输入信号位数
%
%  Time         :    2021/12/11  15:19
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function y = cic_module_front_to_back(x,N,M,Dv,bit_num)
    %% parameters
    Inte_reg = zeros(1,N);
    Comb_reg = zeros(1,N);
    Signal_length = length(x);
    y = zeros(1,fix(Signal_length/Dv));
    ov_bit_num = bit_num + N * log2(M*Dv);
%   ov_bit_num = 52;
    
    ctrl = 1;  % 位数钳制控制
    
    %% CIC
    for loop_S = 1 : Signal_length
        sum_temp = Inte_reg(1,1) + x(loop_S);
        Inte_reg(1,1) = binary_num_clam(sum_temp,ov_bit_num,ctrl);
        for loop_N = 2 : 1 : N
            sum_temp = Inte_reg(1,loop_N) + Inte_reg(1,loop_N-1);
            Inte_reg(1,loop_N) = binary_num_clam(sum_temp,ov_bit_num,ctrl);   % 钳制信号位数
        end
        
        Comb_temp = Inte_reg(1,N);
        if mod(loop_S,Dv) == 0
            for loop_N = 1:N
                temp_reg  = Comb_temp;
                sum_temp = Comb_temp - Comb_reg(1,loop_N);
                Comb_temp = binary_num_clam(sum_temp,ov_bit_num,ctrl);
                Comb_reg(1,loop_N) = temp_reg;
            end
            y(ceil(loop_S/Dv)) = Comb_temp;
        end
    end

其中,变型CIC滤波器结构(cic_module_back_to_ fron.m)函数是变型之后的CIC滤波器。该函数主要起到模型验证作用以及给后期RTL仿真验证提供参考数据的作用。关于变型后的CIC滤波器结构函数matlab代码如下所示。

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  Author       :     Scat Lin
%  Function     :     cic_module_back_to_front.m
%  Description  :     cic滤波器模型,5级CIC,16倍降采样,积分器从后向前计算
%  Inputs       :
%                     cic 滤波器
%                     x input signal
%                     N 滤波器级数
%                     M 滤波器阶数
%                     Dv 抽值倍数
%                     bit_num 输入信号位数
%
%  Time         :    2021/12/11  15:37
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function y = cic_module_back_to_front(x,N,M,Dv,bit_num) 
    %% parameters
    Inte_reg = zeros(1,N);
    Comb_reg = zeros(1,N);
    Signal_length = length(x);
    y = zeros(1,fix(Signal_length/Dv));
    ov_bit_num = bit_num + N * log2(M*Dv);
%   ov_bit_num = 52;
    
    ctrl = 1;  % 位数钳制控制
    
    %% CIC
    for loop_S = 1 : Signal_length
        for loop_N = N : -1 : 2
            sum_temp = Inte_reg(1,loop_N) + Inte_reg(1,loop_N-1);
            Inte_reg(1,loop_N) = binary_num_clam(sum_temp,ov_bit_num,ctrl);   % 钳制信号位数
        end
        sum_temp = Inte_reg(1,1) + x(loop_S);
        Inte_reg(1,1) = binary_num_clam(sum_temp,ov_bit_num,ctrl);
        
        Comb_temp = Inte_reg(1,N);
        if mod(loop_S,Dv) == 0
            for loop_N = 1:N
                temp_reg  = Comb_temp;
                sum_temp = Comb_temp - Comb_reg(1,loop_N);
                Comb_temp = binary_num_clam(sum_temp,ov_bit_num,ctrl);
                Comb_reg(1,loop_N) = temp_reg;
            end
            y(ceil(loop_S/Dv)) = Comb_temp;
        end
    end

关于位数钳制函数(binary_num_clam.m),主要起到限制CIC滤波器实际二进制位数的作用,在仿真中,判断设计的位数是否会导致CIC滤波器发生溢出现象。该函数运算方式参考如下所示代码的头文件。另外,在matlab专题下的“二进制位数钳制章节”也有该函数的详细介绍,该章节的链接为http://mp.weixin.qq.com/s?__biz=MzUzMzkxOTQyMQ==&mid=2247484734&idx=1&sn=268ca808560eaf959ed14caad22e6869&chksm=fa9de6eccdea6ffaa2162db7986aa2255bcce50bdb5a94822fb7b20db54c708d47d8780daa0b#rd

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  Author       :     Scat Lin
%  Function     :     binary_num_clam.m
%  Description  :     钳制二进制位数
%  Inputs       :     
%                     dec_num  输入十进制数据
%                     bit_num  钳制位数
%                     ctrl     控制,默认为1,在为0时不进行位数钳制
%  Example      :     钳制位数为 4
%                    -->  binary_num_clam(5,4)  =  5
%                            5 = '0101'
%                    -->  binary_num_clam(25,4) = -7
%                            25 = '011001'
%                    -->  binary_num_clam(-5,4)  =  5
%                            -5 = '1011'
%                    -->  binary_num_clam(-25,4)  =  7
%                            -25 = '100111'
%
%  Time         :    2021/12/18  15:02
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function bin_sum = binary_num_clam(dec_num,bit_num,ctrl)
    
    ctrl_t = 1;
    if nargin == 3
        ctrl_t = ctrl;
    end
    
    if ctrl_t == 0
        bin_sum = dec_num;
        return;
    end
    
    if dec_num >= 0
        bin_num = dec2bin(dec_num);
        if length(bin_num) < bit_num
            bin_sum = dec_num;
        else
            bit_temp = bin_num(end - bit_num + 1 : end);
            if bit_temp(1) == '1'
                bin_sum = bin2dec(bit_temp) - power(2,bit_num);
            else
                bin_sum = bin2dec(bit_temp);
            end
        end
    else
        if dec_num < -power(2,bit_num-1)
            cnt_bit = bit_num;
            while dec_num < -power(2,cnt_bit)
                cnt_bit = cnt_bit + 1;
            end
            bin_num = dec2bin(power(2,cnt_bit)+dec_num,cnt_bit);
            bit_temp = bin_num(end - bit_num + 1 : end);
            if bit_temp(1) == '1'
                bin_sum = bin2dec(bit_temp) - power(2,bit_num);
            else
                bin_sum = bin2dec(bit_temp);
            end
        else
            bin_sum = dec_num;
        end
    end

其中,主函数是验证模型的顶层函数,主要完成的功能为:生成验证所用的正弦信号、验证模型函数(变型CIC滤波器)的正确性、生成RTL验证所用的十六进制数据。其中值得注意的是,在本文中,对于输入到原型滤波器的数据,需要先加入四个延时。关于主函数matlab代码如下所示。

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  Author       :     Scat Lin
%  Function     :     test_cic_filter.m
%  Description  :     用于测试cic滤波器,5级CIC,16倍降采样
%
%  ---> 测试CIC滤波器模型;
%  ---> 测试CIC滤波器RTL:
%                1、生成十六进制测试序列
%                2、生成十六进制对照序列
%                3、读取生成序列序列,,matlab分析
%
%  Time         :    2021/12/11  15:19
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear,clc

%% control sel
%--> 0 : 对CIC的matlab模型验证
%--> 1 : 生成待测试的数据,十六进制 + testbench校验用的数据,十六进制
ctrl_sel = 0 ;     

%% parameters 
cycle_num =    40;      % 仿真周期数,信号为正弦波
N_bit     =    8;       % 数据位数,二进制
fs        =    256000;  % 过采样,采样率
fz        =    100;     % 信号的频率
wr_addr_s =    'D:\work\Study\CIC\signal_quantified.txt';   %% 没有经过CIC下采样滤波的信号
wr_addr_n =    'D:\work\Study\CIC\signal_aftercic.txt';   %% 经过CIC下采样滤波的信号,来来进行testbench比较

%% 生成采样信号
% 带符号数据
time_s       =   0 : 1/fs : (((cycle_num*fs)/fz)-1)/fs;
y_initial    =   sin(2*pi*fz*time_s);
y_quantified =   fix((power(2,N_bit-1)-1).*y_initial);
if ctrl_sel == 1    % 输出txt文件
    fid = fopen(wr_addr_s,'wt');
    for loopi = 1 : length(y_quantified)
        % 十进制转带符号十六进制(二进制)
        if y_quantified(loopi) < 0
            temp_hex = dec2hex(power(2,N_bit)+y_quantified(loopi),ceil(N_bit/4));
        else
            temp_hex = dec2hex(y_quantified(loopi),ceil(N_bit/4));
        end
        fprintf(fid,'%s\n',temp_hex);
    end
    fclose(fid);
end
% display quantified signal
figure(1
plot(time_s,y_quantified);
title('原数据波形')
        
%% matlab 模型验证 or 生成测试用比较用例
% 与matlab自带的cic模型进行比较
% 对于输入到原型滤波器的数据,需要先加入四个延时
if (ctrl_sel == 0) || ( ctrl_sel == 1 )
    matlab_y = cic_module_back_to_front(y_quantified,5,1,16,N_bit);
    y        = cic_module_front_to_back([zeros(1,4),y_quantified(1:end-4)],5,1,16,N_bit);
    figure(2
    plot(downsample(time_s,16),y','r',downsample(time_s,16),matlab_y,'k');
    figure(3)
    plot(downsample(time_s,16),matlab_y,'r');
    title('CIC滤波数据波形')
    figure(4)
    plot(downsample(time_s,16),y,'r');
    title('CIC滤波数据波形')
end

%% 
% 信号经过cic滤波之后的数据
if ctrl_sel == 1    % 输出txt文件
    fid = fopen(wr_addr_n,'wt');
    for loopi = 1 : length(y)
        % 十进制转带符号十六进制(二进制)
        if y(loopi) < 0
            temp_hex = dec2hex(power(2,CIC_bit)+y(loopi),ceil(CIC_bit/4));
        else
            temp_hex = dec2hex(y(loopi),ceil(CIC_bit/4));
        end
        fprintf(fid,'%s\n',temp_hex);
    end
    fclose(fid);
end

if ctrl_sel == 0    % 模型验证比较
    cmp_y_m = matlab_y - y;
    figure
    plot(cmp_y_m);
    
    if sum(cmp_y_m) == 0
        fprintf('模型是正确的!!!!\n');
    else
        fprintf('模型验证失败\n');
    end
end

在进行模式验证阶段,我们设定ctrl_sel = 0,运行代码后,可以直接在命令行得到验证信息,如下所示,表示模型验证正确。若命令行窗口输出的是“模型验证失败”,表明模型验证两个输出数据不相等。 另外我们还可以通过波形查看比较结果。如下图所示(左图),如果模型验证成功,两个信号的波形应该是完全重合;如下图所示(右图),如果模型验证成功,两个输出信号相减恒为0.

本文PDF格式文件及代码下载链接如下 链接:https://pan.baidu.com/s/1MKeA0esKDLqfe-K65a7xsQ 提取码:0000

若喜欢DSP相关话题,还请关注本人公众号

分类:

前端

标签:

前端

作者介绍

寻找薛定谔的猫
V1