主要内容

使用整数系数创建FIR滤波器

本节提供了一个示例,说明如何创建具有整数系数的过滤器。在本例中,创建了一个带有浮点系数的升余弦过滤器,然后将过滤器系数转换为整数。

定义过滤器系数

为了说明使用带定点过滤器的整数的概念,这个例子将使用一个上升余弦过滤器:

B = rcosdesign(。25, 12.5, 8, 'sqrt');
的系数b被归一化,使通带增益等于1,并且都小于1。为了使它们成为整数,需要对它们进行缩放。如果你想将它们缩放为每个系数使用18位,那么系数的可能值范围将变为:

2 17 2 17 1 131072 131071

因为最大的系数b是正的,它将需要缩放到尽可能接近131071(没有溢出),以尽量减少量化误差。你可以通过执行以下命令来确定比例因子的指数:

B = 18;%的比特数L =地板(log2 ((2 ^ (b - 1) 1) / max (b)));bsc = b*2^L;

或者,你也可以使用定点数字自动缩放工具,如下所示:

bq = fi(b, true, b);% signed = true, B = 18 bits L = bq.FractionLength;

这是一个巧合B而且l在这种情况下都是18,因为最大的系数的值b。的最大值,例如b是0.124,l就是20岁B(比特数)仍然是18。

构建FIR滤波器

首先使用直接形式创建滤波器,抽头延迟线结构:

H = dfilt.dffir(bsc);

为了设置所需的参数,必须将算术设置为定点:

h.算术= 'fixed';h.CoeffWordLength = 18;

你可以检查的系数h都是整数:

所有(h。分子== round(h.分子))ans = 1

现在你可以检查滤波器的大小响应使用fvtool

fvtool(h, 'Color', 'white')

这表明在通带中有117 dB的大增益,这是由于系数的大值-这将导致滤波器的输出比输入大得多。下面几节将讨论解决这个问题的方法。

将筛选参数设置为使用整数

您需要将筛选器的输入参数设置为处理整数的适当值。例如,如果滤波器的输入来自一个12位分辨率的a /D转换器,你应该这样设置输入:

h.InputWordLength = 12;h.InputFracLength = 0;

信息方法返回筛选器设置的摘要。

信息(h)

离散时间FIR滤波器(实)-------------------------------滤波器结构:直接形式FIR滤波器长度:101稳定:是线性相位:是(类型1)算术:固定分子:s18,0 ->[-131072 131072)输入:s12,0 ->[-2048 2048)滤波器内部:全精度输出:s31,0 ->[-1073741824 1073741824)(自动确定)产品:s29,0 ->[-268435456 268435456)(自动确定)累加器:s31,0 ->[-1073741824 1073741824)(自动确定)Round模式:不舍入溢出模式:不溢出

在本例中,所有分数长度现在都设置为零,这意味着过滤器h设置为处理整数。

为滤波器创建一个测试信号

您可以通过使用自动缩放功能量化到12位来为滤波器生成输入信号,或者您可以遵循前面讨论的用于系数的相同过程。在这个例子中,创建一个有两个正弦波的信号:

N = 0:999;F1 = 0.1*pi;第一正弦信号归一化频率f2 = 0.8*pi;第二正弦波归一化频率x = 0.9*sin(0.1*pi*n) + 0.9*sin(0.8*pi*n);Xq = fi(x, true, 12);% signed = true, B = 12 xsc = fi(xq.int, true, 12,0);

对测试信号进行滤波

要对上述产生的输入信号进行过滤,输入以下内容:

Ysc = filter(h, xsc);

在这里ysc是全精度输出,意味着在计算中没有丢弃任何位。这使得ysc在给定12位输入和18位系数的情况下,您可以获得最好的输出。这可以通过使用双精度浮点进行过滤并比较两个过滤操作的结果来验证:

Hd = double(h);Xd = double(xsc);Yd = filter(hd, xd);Norm (yd-double(ysc)) ans = 0

现在您可以将输出与输入进行比较。本例只绘制了最后几个样本,以最小化瞬态的影响:

Idx = 800:950;Xscext = double(xsc(idx)');Gd = grpdelay(h, [f1 f2]);Yidx = idx + gd(1);Yscext = double(ysc(yidx)');Stem (n(idx)', [xscext, yscext]);轴([800 950 -2.5e8 2.5e8]);传奇(“输入”、“输出”);Set (gcf, 'color', 'white');

这张图中的两个信号由于尺度差异较大,很难进行比较。这是由于滤波器的增益很大,所以你将需要补偿滤波器增益:

Stem (n(idx)', [2^18*xscext, yscext]);轴([800 950 -5e8 5e8]);Legend ('scaled input', 'output');

在缩放完成后,您可以更容易地看到信号的比较,如上图所示。

截断输出的WordLength

如果检查输出的字长,

ysc。WordLength ans = 31

您将注意到输出中的比特数比输入中的比特数要大得多。由于表示数据的比特数的这种增长可能不可取,因此可能需要截断输出的字长。最好的方法是丢弃最不重要的位,以尽量减少错误。但是,如果你知道有未使用的高阶位,你也应该丢弃这些位。

要确定是否有未使用的最高有效位(msb),可以查看计算中WordLength增长的位置。在这种情况下,比特增长是为了适应输入(12位)和系数(18位)的乘积相加的结果。下载188bet金宝搏这些产品中的每一个都是29位下载188bet金宝搏长(您可以使用信息(h)).由于积的积累而产生的比特增长取决于滤波器长度和系数值-然而,这是最坏情况下的决定,因为没有对输入信号做任何假设,因此可能会有未使用的msb。不过,您必须小心,因为被错误地视为未使用的msb将导致溢出。

假设你想为输出保留16位。在这种情况下,由于添加没有增加位,因此输出位设置为字长16,分数长度-14。

由于过滤已经完成,您可以从ysc

Yout = fi(ysc, true, 16, -14);

或者,你可以直接设置滤波器输出位长(如果你打算过滤很多信号,这很有用):

specifyall (h);h.OutputWordLength = 16;h.OutputFracLength = -14;youout2 = filter(h, xsc);

你可以用两种方法验证结果是否相同:

Norm (double(yout) - double(yout2)) ans = 0

然而,如果你将其与全精度输出进行比较,你会注意到由于丢弃的比特而存在舍入误差:

Norm (double(yout)-double(ysc)) ans = 1.446323386867543e+005

在这种情况下,绘制数据时很难发现差异,如下图所示:

茎(n (yidx),[双(你(yidx)”),双(ysc (yidx) '));轴([850 950 -2.5e8 2.5e8]);legend('Scaled Input', 'Output');Set (gcf, 'color', 'white');

调整输出

由于本例中的滤波器具有如此大的增益,因此输出与输入的规模不同。不过,这种伸缩只是理论上的,您可以随意伸缩数据。在本例中,输出有16位,但是您可以附加任何您选择的比例。对于LSB,重新解释输出使其权值为2^0(或L = 0)是很自然的。这相当于将输出信号按2^(-14)的因子缩小。然而,没有计算或舍入误差涉及。你可以通过执行以下命令来做到这一点:

Yri = fi(yout.int, true, 16,0);Stem (n(idx)', [xscext, double(yri(yidx)')]);轴([800 950 -1.5e4 1.5e4]);Legend ('input', 'rescale output');

这幅图显示输出仍然大于输入。如果您在双精度浮点中进行过滤,则不会出现这种情况——因为这里用于输出的比特比用于输入的比特多,因此msb的权重不同。你可以通过观察缩放滤波器的幅度响应来看到另一种方式:

[H,w] = freqz(H);情节(w /π,20 * log10 (2 ^ (-14) * abs (H)));

该图显示,通带增益仍然高于0分贝。

要把投入和产出放在同一个比额上,各服务提供者的权重必须相等。输入MSB的权值为2^11,而缩放后的输出MSB的权值为2^(29-14)= 2^15。你需要给输出MSB一个2^11的权重,如下所示:

Yf = fi(零(大小(yri)), true, 16,4);Yf.bin = yri.bin;Stem (n(idx)', [xscext, double(yf(yidx)')]);Legend ('input', 'rescale output');

这个操作相当于将滤波器增益缩小2^(-18)。

[H,w] = freqz(H);情节(w /π,20 * log10 (2 ^ (-18) * abs (H)));

上图显示了一个0db增益在通带,如所愿。

有了这个最终版本的输出,yf不再是整数。然而,这只是由于解释-整数表示的位yf和里面的位表示的是一样的吗。你可以通过比较来验证这一点:

Max (abs(yf.int - yri.int)) ans = 0

使用set2int方法配置过滤参数以处理整数

将筛选参数设置为使用整数

set2int方法提供了设置筛选器参数以处理整数的方便方法。该方法的工作原理是将系数缩放为整数,并将系数和输入分数长度设置为零。这使得直接使用浮点系数成为可能。

H = dfilt.dffir(b);h.算术= 'fixed';

系数用18位表示,输入信号用12位表示:

G = set2int(h, 18,12);g_dB = 20*log10(g) g_dB = 1.083707984390332e+002

set2int方法通过将系数缩放为整数来返回过滤器的增益,因此增益总是2的幂。你可以验证我们在这里得到的增益与之前滤波器的增益是一致的。现在你还可以检查滤镜h正确地设置为处理整数:

info(h)离散时间FIR滤波器(实)-------------------------------滤波器结构:直接形式FIR滤波器长度:101稳定:是线性相位:是(类型1)算术:固定分子:s18,0 ->[-131072 131072)输入:s120,0 ->[- 20482048)滤波器内部:全精度输出:s31,0 ->[-1073741824 1073741824)(自动确定)产品:s29,0 ->[-268435456 268435456)(自动确定)累加器:s31,0 ->[-1073741824 1073741824)(自动确定)Round模式:不舍入溢出模式:不溢出

在这里,您可以看到所有的分数长度现在都被设置为0,因此这个过滤器被正确地设置为处理整数。

重新解释输出

您可以将输出与双精度浮点引用输出进行比较,并验证筛选器完成的计算h是完全精确的。

Yint = filter(h, xsc);Norm (yd - double(yint)) ans = 0

然后你可以将输出截断为16位:

Yout = fi(yint, true, 16);Stem (n(yidx), [xscext, double(yout(yidx)')]);轴([850 950 -2.5e8 2.5e8]);传奇(“输入”、“输出”);

再一次,图表显示了输入和输出在不同的尺度上。为了缩放输出,以便在图中更容易地比较信号,您将需要适当地对msb进行称重。当系数为整数时,您可以使用过滤器的增益计算新的分数长度:

WL = youout . wordlength;FL = yout。FractionLength + log2(g);yf2 = fi(0 (size(yout)), true, WL, FL);Yf2.bin = youout .bin;Stem (n(idx)', [xscext, double(yf2(yidx)')]);Axis ([800 950 -2e3 2e3]);Legend ('input', 'rescale output');

最后一个图显示了重新缩放以匹配输入比例的过滤数据。