玩转VHDL-026 开平方 我们首先来看一下10进制数手动开平方的过程: 1°先将被开方数,从小数点位置向左右每隔两位分段,例316.484分成3,16.48,40共4段,从左向右依次称作S1=3,S2=16,S3=48,S4=40,如需进一步扩展有S5=00,S6=00,… 2°定义余数R,平方根r,定义每一步的试商值为x,x是0到9的整数满足式试商关系:(r*20+x)*x≤R*100+Sk且(r*20+x+1)*(x+1)>R*100+Sk,其中k含义如1°所示。 3°初始化R=0,r=0,k=0 4°k=k+1,若k达到规定精度上限则运算结束转到6°,否则到5° 5°求满足试商关系的x,并更新R=R*100+Sk-(r*20+x)*x,r=r*10+x,转到4°。 6°在r适当位置添加小数点后即得所求平方根。 另外,如果在第k步有R=0且Si=0(对于所有i>k)那么获得了精准得平方根值,运算也可以结束。 在接下来的讨论中我们不再关心小数点问题,因为它是一个平凡的小问题,总可以通过移位转换为无小数点问题处理。 对于二进制的手开方过程,类似于10进制开方过程: 1°每2比特为一段把二进制数从右至左分成n段,从左至右记作S1,S2,…,Sn 2°试商值x只可能取值0或1,x = {r, 'b01} <={R,Sk}; 3°初始化R=0,r=0 4°for k =1:n, 按2°求x, R = {R,Sk}- x*{r, 'b01}, r = {r,x}; 5°r为所求平方根 开平方的详细VHDL代码如图所示,代码简单解释如下: sqrt完成 yv = sqrt(xv)功能 输入信号bgn:开始计算开平方指示脉冲。 输出信号qEn:表示平方根yv有效起始时刻。 从bgn到qEn需要yv比特位宽+1个时钟周期。 代码中变量try代表算法中x,root代表r,d_rg(0 toYW+1)代表{R,Sk}那么显然: 行37:实现2°中x的计算。 行42和33:完成对R和r的初始化。 行34:对r的迭代计算r ={r,x}。 行41在38、39行配合下:实现对R的迭代R = {R,Sk}-x*{r, 'b01}。 行44:将root转换成需要的类型输出。 代码中cn是一个计数器,完成对迭代次数的控制,其比特宽度由函数INW计算所得。 本sqrt代码是可以被综合的模块,并已在多个工程中使用,今日特共享,并期待同仁的修改意见再提高。
|