上一篇博客我从算法的原理出发,进而通过公式步步推导,完成圆周系统中旋转模式的验证工作。这次我打算从一个小实例出发,来说说我这个cordic算法除了能做些干什么!
有很多同学知道可以用来做DDS 但是对于现在这个“内存过剩”的年代,采用运算的方式实现DDS远远不如LUT来得方便。。。。PS(cordic算法提出的年代,那是在遥远的20世纪五六十年代,那时候内存非常的宝贵!)于是乎我也就不介绍DDS实现方式。。。
众所周知想要得到FFT的运算结果前一步必须取模,这里取模运算包括了平方,相加,开根这三个基本运算,其中前两个运算没啥问题,关键是开根!单片机通过调用数学函数可以解决这个问题,但是FPGA实现就没这么容易了,需要自己写这套取模的电路。
于是乎我就搬来了大杀器(圆周系统之向量模式):
仔细观察这个得到结果,不要有畏惧心理。发现得到的xn正是我们想要的答案!有同学会说不是还要乘上一个An?放心An约等于一个常数1.64676到时候除去就行。另外再仔细观察学过通信基础的可以发现这个公式很眼熟,稍微改改不就可以求相位了么。。。做过载波同步的同学笑了。。。
接下来我们理理思路开始考虑如何编写硬件电路,好,首先我们知道在这个向量模式下初始角度为0,并输入向量值假定他为(1,2)随后观察上述运算公式发现这是个迭代的过程,这就好办了,如果是C的话就用for循环好了,在verilog里面为了提高运算速度,把运算一次作为一个运算单元,然后输入输出相连,把n的结果作为n+1的初始值,循环往复。
最后在运算的过程中,存在tan-1这个值那我们做查找表好了,在做查找表的过程中我们要对其进行定点化,45/1 45/2 45/4 45/8…把这些数通通乘上256保证其精度。然后带入其中运算。
好下面给出一个运算单元的veriliog,其余大家复制粘贴,你懂得。。。
always @ (posedge clk or negedge rst_n) //cell 2
begin
if(!rst_n)
begin
x1_buf <= 16'd0;
y1_buf <= 16'd0;
z1_buf <= 16'd0;
end
else
begin
if (y0_buf[15]==1'b1)
begin
x1_buf <= x0_buf - (y0_buf >>> 1);
y1_buf <= y0_buf + (x0_buf >>> 1);
z1_buf <= z0_buf - 16'sd6801;
end
else
begin
x1_buf <= x0_buf + (y0_buf >>> 1);
y1_buf <= y0_buf - (x0_buf >>> 1);
z1_buf <= z0_buf + 16'sd6801;
end
end
end
这段小程序很快就能分析清楚,通过判断y的符号位,来得到其旋转方向。
结果是945,好我们这样算945/255/1.64676=2.24
那么根号5的结果:2.236可以说是基本吻合了。
用户1737577 2014-10-11 08:07