寻找薛定谔的猫
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相关话题,还请关注本人公众号
作者介绍