非传统定点数(一)

关注我的公众号c137Lab获取更多相关内容

在这里插入图片描述

非传统定点数(一)

有符号数(Signed Digit Number,SD)

​ SD 和 SM(Signed-Magnitude)不同,具有三重值 { 0 , 1 , − 1 } \{0,1,-1\} { 0,1,1} 其中 -1 也常写成 1 ‾ \overline{1} 1 .已经证明SD数应用在不用进位的加法器和乘法器中能够降低复杂性。

SD码编码示例:
1 4 10 = 1 6 10 − 2 10 = 100 1 ‾ 0 14_{10}=16_{10}-2_{10}=100\overline10 1410=1610210=10010

1 4 10 = 8 10 + 4 10 + 2 10 = 01110 14_{10}=8_{10}+4_{10}+2_{10}=01110 1410=810+410+210=01110

​ 可以看出SD码是不唯一的。事实上,要降低乘法的工作量,需要降低运算中非零元素的数量。我们称拥有最少非零元素的SD码为CSD码。

最佳CSD编码

最佳CSD编码:

  1. 从最低有效位开始,用 10 ⋯ 0 1 ‾ 10\cdots0\overline1 1001 取代所有大于 2 的 1 序列。此外,还需要用 110 1 ‾ 110\overline1 1101 取代 1011 1011 1011
  2. 从最高位开始,用 011 011 011 代替 10 1 ‾ 10\overline1 101

该方法给出一个非零元素最少的SD码,且其中的减法次数最少。

示例:
2 7 10 = 1101 1 C S D = 1110 1 ‾ C S D = 10 1 ‾ 0 1 ‾ C S D 27_{10}=11011_{CSD}=1110\overline1_{CSD}=10\overline10\overline1_{CSD} 2710=11011CSD=11101CSD=10101CSD
虽然第一步没有减少非零元素的个数,但是它使用加法替代了减法。最终,这一算法将 3 次加法简化为了两次减法。

​ 观察 01 1 2 011_2 0112 ,如果将其转换为 10 1 ‾ 10\overline1 101 ,那么实际上是复杂化了运算,将一次加法变成了一次减法。这也就是最佳CSD编码第二步操作的意义。

分数CSD编码

​ 使用整型数实现分数会导致很大的误差,使用CSD编码可以降低这一误差。

例如 y = 7 x / 8 y=7x/8 y=7x/8,可以写成以下几种实现方式:
y 0 = ( 7 x ) / 8 y0=(7x)/8 y0=(7x)/8

y 1 = ( x / 8 ) ∗ 7 y1=(x/8)*7 y1=(x/8)7

y 2 = ( ( 4 + 2 + 1 ) x ) / 8 = ( x / 2 ) + ( x / 4 ) + ( x / 8 ) y2=((4+2+1)x)/8=(x/2)+(x/4)+(x/8) y2=((4+2+1)x)/8=(x/2)+(x/4)+(x/8)

y 3 = ( ( 8 − 1 ) x ) / 8 = x − ( x / 8 ) y3=((8-1)x)/8=x-(x/8) y3=((81)x)/8=x(x/8)

不难看出, y 2 y2 y2 是普通二进制码, y 3 y3 y3 是CSD码

使用Verilog实现上述代码并观察结果(iverilog):

module csd(
 input [4:0] x0,
 
 output [4:0] y0,
 output [4:0] y1,
 output [4:0] y2,
 output [4:0] y3
);

assign y0 = 7*(x0)/8;
assign y1 = (x0/8)*7;
assign y2 = x0/2+x0/4+x0/8;
assign y3 = x0-x0/8;

endmodule
`timescale 1ns/100ps

module csd_tb;


reg [4:0] x0;
wire [4:0] y0;
wire [4:0] y1;
wire [4:0] y2;
wire [4:0] y3;

/*iverilog */
initial
begin            
 $dumpfile("wave.vcd");        //生成的vcd文件名称
 $dumpvars(0, csd_tb);    //tb模块名称
end
/*iverilog */
initial
begin
 x0 = 1;
 #10
     x0 = 3;
 #20
     x0 = 6;
 #30
     x0 = 9;
 #100
     $stop;
end


csd cds_ut0 (
 .x0(x0),

 .y0(y0),
 .y1(y1),
 .y2(y2),
 .y3(y3)
);


endmodule

输出结果如下:

img1

可以看出CSD码有效的降低了量化误差。因为实际上除以2的幂的除法是通过移位实现的,误差最大的 y 1 y1 y1 实际上在第一步就已经损失了低3位。

自由进位加法器

​ SD编码可以实现自由进位加法,通过LUT进行计算,表如下:

img2

​ 实现上表需要一个 2 8 × 4 2^8\times4 28×4 的LUT,计算出 u k u_k uk c k c_k ck 后将 c k c_k ck 左移一位与 u k u_k uk 相加即可得到结果。

乘法-加法器图(Multiplier Adder Graph,MAG)

​ 在最优CSD意义中,经常是先将系数分解成几个因子,再实现具体因子效率比较高。

例如系数93的实现方式可以有以下几种:
93 = 3 × 31 = ( 1 + 2 ) × ( 32 − 1 ) 93=3\times31=(1+2)\times(32-1) 93=3×31=(1+2)×(321)

93 = 64 + 32 − 4 + 1 93=64+32-4+1 93=64+324+1

用流程图表示如下:
在这里插入图片描述

对数系统(Logarithmic Number System,LNS)

​ 对数系统与固定尾数和分数指数构成的浮点数制类似,使用如下方式表示:
x = ± r ± e x x=\pm r^{\pm e_x} x=±r±ex
​ 其中 r r r 是数制的基数, e x e_x ex 是对数数制的指数。

举例说明其在计算机中的格式:

假设一个基数为 2 的 9 位 LNS 数,其构成为两个符号位,三位整数精度和四位分数精度:00 011.0010,格式如下:

符号 S x S_x Sx 指数符号 S e S_e Se 指数整数位 I I I 指数分数位 F F F
0 1 100 1110

其十进制表达式为:
2 − 3 − 1 / 8 = 2 − 3.125 2^{-3-1/8}=2^{-3.125} 231/8=23.125
注意到指数部分使用补码表示。

​ 9 位 LNS 能表示的最大数是 2 8 − 1 / 16 ≈ 256 2^{8-1/16}\approx256 281/16256,最小数是 2 − 8 = 0.0039 2^{-8}=0.0039 28=0.0039,和传统定点数相比 LNS 在数字较小的时候采样率更高,更加精细。

​ 历史上,LNS 的优势在于能够有效实现乘法、除法、求平方根或平方,因其可以将以上运算转换为加法、除法和乘法。但是加法和减法的复杂度会增加,加减法使用如下方式进行:

假设 A > B A>B A>B
KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ C&=A+B=2^{e_a}…
可以得到 e c = e a + l o g 2 ( ϕ + ( Δ ) ) e_c=e^a+log_2(\phi^+(\Delta)) ec=ea+log2(ϕ+(Δ))。同理,对于减法有 ϕ − ( Δ ) = 1 − 2 e b − e a \phi^-(\Delta)=1-2^{e_b-e_a} ϕ(Δ)=12ebea e c = e a + l o g 2 ( ϕ − ( Δ ) ) e^c=e^a+log_2(\phi^-(\Delta)) ec=ea+log2(ϕ(Δ))

参考文献:Digital Signal Processing with Field Programmable Gate Arrays --U.Meyer-Baese

猜你喜欢

转载自blog.csdn.net/verse_monger/article/details/105783652