CORDIC的FPGA实现

输入:I,Q,

输出:相位,幅度

 

CORDIC算法的核心在于利用加减和位移运算(对于FPGA很合适的运算),计算一个矢量的相位和幅度。

我们知道FPGA上没有开根号这样的运算,所以如果给定I,Q信号,计算其幅度sqrt(I^2+Q^2),无法直接使用该公式。

一个矢量P0旋转一定角度后变为P1,其坐标的关系如下:

每一步移动一个角度,角度越小,移位的越大。在N步的计算中,K是一个固定值,趋近于1.6.真正需要迭代的公式如下:

    Xn+1 = Xn - SnYn2-n

     Yn+1 = Yn + SnXn2-n

    Zn+1 = Zn – Sntan-1(2-n)

其中Sn是旋转方向,Sn=1或-1,可以直观地看出,当Sn=1,X变小,Y变大,说明矢量向Y轴靠近。由此确定了编程思路,在N步内,让矢量反复迭代,如向X轴正半轴靠近,顺时针旋转。每次迭代后,如果Y>0,说明可以继续旋转,Sn=1,如果Y<0,说明旋转过度,需要反转,Sn=-1。于是有:

for(i=0; i>i) :  X[i] +(-Y[i]>>i);
 Y[i+1] <= (Y[i][SIG]==0)? Y[i] - (X[i]>>i) :  Y[i] +( X[i]>>i);
 signal_arry[i+1] <= signal_arry[i];
 end


上面signal_arry则记录了该矢量所处的象限。

对于相位信息,记录每一次转过的角度和其旋转方向,于是有:

pha[0] <= 0;
	pha[1] <= (Y[0][SIG]==0)? pha[0] + 13'd4500 : pha[0] - 13'd4500;
	pha[2] <= (Y[1][SIG]==0)? pha[1] + 12'd2656 : pha[1] - 12'd2656;
	pha[3] <= (Y[2][SIG]==0)? pha[2] + 12'd1403 : pha[2] - 12'd1403;
	pha[4] <= (Y[3][SIG]==0)? pha[3] +  10'd712 : pha[3] -  10'd712;
	pha[5] <= (Y[4][SIG]==0)? pha[4] +  9'd358 : pha[4] -  9'd358;
	pha[6] <= (Y[5][SIG]==0)? pha[5] +  8'd179 : pha[5] -  8'd179;
	pha[7] <= (Y[6][SIG]==0)? pha[6] +   7'd89 : pha[6] -   7'd89;
	pha[8] <= (Y[7][SIG]==0)? pha[7] +   6'd44 : pha[7] -   6'd44;
	pha[9] <= (Y[8][SIG]==0)? pha[8] +   5'd22 : pha[8] -   5'd22;
	pha[10]<= (Y[9][SIG]==0)? pha[9] +   4'd11 : pha[9] -   4'd11;
	pha[11]<= (Y[10][SIG]==0)? pha[10] +    3'd6 : pha[10] -    3'd6;
	pha[12]<= (Y[11][SIG]==0)? pha[11] +    2'd3 : pha[11] -    2'd3;
	pha[13]<= (Y[12][SIG]==0)? pha[12] +    1'd1 : pha[12] -    1'd1;

		if(X[arry_length]==0)
			phase_out<=0;
		else begin
			if(signal_arry[arry_length]==00)
			phase_out <= pha[arry_length];
			else if(signal_arry[arry_length]==2'b01)
			phase_out <= 22'd18000 - pha[arry_length];
			else if(signal_arry[arry_length]==2'b11)
			phase_out <= 22'd18000 +	pha[arry_length];
			else if(signal_arry[arry_length]==2'b10)
			phase_out <= 22'd36000 - pha[arry_length];
		end

从中看到度数扩大了100倍,每一次旋转4500,第二次转2656,依次类推。其中signal_arry所存储的相位信息在相位输出的时候做较正。如,某矢量为150度,先将I,Q值绝对值化,使其变为30度,并存储其相位信息。相位流水迭代完毕后计算出该角30度,输出的时候做校正,if(该角在第2象限),输出=180-旋转角180-30=150度。

仿真结果分析看出,其相位精度达到2/1000度,幅度精度为1/4500。

在编译的时候有许多很重要的小事,小问题影响着大结果。从编程上来看,如果要计算幅度,则只需2行代码,而计算相位却复杂得多,要考虑到各种情况。


 

 

 

你可能感兴趣的:(信号处理,FPGA)