主要内容

创建一个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;

这是一个巧合Bl在这种情况下,都是18吗,因为最大的系数b.例如,如果b是0.124,l将是20B(位的数目)将保持18。

构建FIR滤波器

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

h = dfilt.dffir (bsc);

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

h.Arithmetic = '固定';h.CoeffWordLength = 18;

你可以检查一下h都是整数:

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

现在你可以用fvtool

fvtool (h,“颜色”,“白”)

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

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

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

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

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

信息(h)

离散时间FIR滤波器(实数)-------------------------------滤波器结构:直式FIR滤波器长度:101稳定:是线性相位:是(Type 1)算术:固定分子:s18,0 ->[-131072 131072)输入:s12,0 ->[-2048 2048)滤波器内部:全精度输出:s31,0 -> [-1073741824 1073741824) (auto determined)产品:s29,0 -> [-268435456 268435456) (auto determined)蓄能器:s31,0 -> [-1073741824 1073741824) (auto determined) Round Mode:无舍入溢出模式:无溢出

在这种情况下,所有的小数长度现在都被设置为零,这意味着过滤器h设置为处理整数。

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

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

n = 0:999;f1 = 0.1 *π;%第一正弦信号归一化频率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位系数,您可以实现的最佳输出。这可以通过使用双精度浮点进行过滤并比较两种过滤操作的结果来验证:

高清=双(h);xd =双(xsc);Yd = filter(hd, xd);Norm (yd-double(ysc)) ans = 0

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

idx = 800:950;xscext =双(xsc (idx) ');Gd = grpdelay(h, [f1 f2]);Yidx = idx + gd(1);yscext =双(ysc (yidx) ');阀杆(n (idx)”,[xscext yscext]);轴([800 950 -2.5e8 2.5e8]);传奇(“输入”、“输出”);集(gcf,“颜色”,“白”);

由于这两种信号在尺度上有很大的差异,因此比较图中的两种信号比较困难。这是由于滤波器的增益很大,所以需要补偿滤波器增益:

阀杆(n (idx)”,[2 ^ 18 * xscext yscext]);轴([800 950 -5e8 5e8]);传奇(“缩放输入”、“输出”);

如上图所示,您可以看到,一旦缩放完成,信号的比较就容易得多了。

截断输出的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;Yout2 = filter(h, xsc);

你可以验证结果是相同的两种方式:

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

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

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

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

茎(n (yidx),[双(你(yidx)”),双(ysc (yidx) '));轴([850 950 -2.5e8 2.5e8]);传奇(“缩放输入”、“输出”);集(gcf,“颜色”,“白”);

规模的输出

因为这个例子中的滤波器有如此大的增益,输出与输入的比例是不同的。然而,这种缩放纯粹是理论上的,你可以根据自己的喜好缩放数据。在本例中,输出为16位,但可以附加您选择的任何比例。很自然地可以重新解释输出,使LSB的权值为2^0(或L = 0)。这相当于将输出信号缩小2^(-14)倍。然而,不涉及计算或舍入误差。你可以执行以下命令:

Yri = fi(yout.int, true, 16, 0);阀杆(n (idx)”,[xscext、双套(yidx) '));轴([800 950 -1.5e4 1.5e4]);传奇(“输入”、“新输出”);

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

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

这张图显示通带增益仍然高于0 dB。

为了将投入和产出放在同一尺度上,MSBs必须同等加权。输入MSB的权重为2^11,而按比例输出的MSB的权重为2^(29-14)= 2^15。你需要给输出MSB一个2^11的权重如下:

Yf = fi(zero (size(yri)), true, 16, 4); / / Yf = 0;yf.bin = yri.bin;阀杆(n (idx)”,[xscext、双(yf (yidx) '));传奇(“输入”、“新输出”);

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

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

上面的图显示了一个0db增益在通频带,如所希望的。

在输出的最终版本中,yf不再是整数。然而,这只是由于解释-整数表示的位yf和二进制表示的1是一样的吗.你可以通过比较它们来验证:

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

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

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

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

h = dfilt.dffir (b);h.Arithmetic = '固定';

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

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

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

info(h) Discrete-Time FIR Filter (real) ------------------------------- Filter Structure: Direct-Form FIR Filter Length: 101 Stable: Yes Linear Phase: Yes (Type 1) Arithmetic: fixed molecule: s18,0 -> [-131072 131072) Input: s12,0 -> [-2048 2048) Filter Internals: Full Precision Output:全精度输出:s31,0 -> [-1073741824 1073741824) (auto determined)产品:s29,0 -> [-268435456 268435456) (auto determined)蓄能器:s31,0 -> [-1073741824 1073741824) (auto determined) Round Mode:无舍入溢出模式:无溢出

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

重新解释输出

您可以将输出与双精度浮点参考输出进行比较,并验证由过滤器完成的计算h是完全精确的。

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

然后你可以截断输出到只有16位:

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

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

王= yout.WordLength;FL =你。FractionLength + log2 (g);yf2 = fi(zero (size(yout)), true, WL, FL);yf2.bin = yout.bin;阀杆(n (idx)”,[xscext、双(yf2 (yidx) '));轴([800 950 -2e3 2e3]);传奇(“输入”、“新输出”);

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