上两篇博文Cordic算法——圆周系统之旋转模式Cordic算法——圆周系统之向量模式做了理论分析和实现,但是所用到的变量依然是浮点型,而cordic真正的用处是基于FPGA等只能处理定点的平台。只需将满足精度的浮点数,放大2^n倍,取整,再进行处理。

1. 旋转模式

假设要通过FPGA计算极坐标(55.6767°,1)的直角坐标。首先,角度值为浮点数,需要进行放大处理,放大10000倍。则预设的旋转角度同样要放大10000倍。

实现伪旋转(忽略模长补偿因子)的代码如下所示,注意,因为是整型运算,起始旋转时x放大了215,放大倍数决定计算精度,满足需求即可。最后得到的x,y在缩小215,即得到伪旋转后的x,y。最后进行模长波长运算(因为是浮点,同样需要放大)。

#include <stdio.h>
#include <stdlib.h> int cordic_c(int a,int r);
int x = 32768, y = 0; //以X轴为旋转起始点,放大倍数2^15 int main(viod)
{ int remain = cordic_c(556767,1); //极坐标值(极角,极径)
printf("旋转角度误差:%d, 直角坐标:x = %d, y = %d\n",remain,x,y);
return 0;
} int cordic_c(int a,int r)
{
const int theta[] = {450000,265651,140362,71250,35763,17899,8952,4476,2238,1119,560,280,140,70,35,17,9,4,2,1}; //旋转角度 int i = 0;
int x_temp = 0, y_temp = 0;
int angle_new = 0; //旋转后终止角度
int angle_remain = a; //旋转后,剩余角度
char detection; //旋转方向 for( i=0; i<20;i++)
{
if(angle_remain > 0)
{
angle_new = angle_new + theta[i];
angle_remain = a - angle_new;
x_temp = (x - (y >>i));
y_temp = (y + (x >> i));
x = x_temp;
y = y_temp;
detection = '+';
}
else
{
angle_new = angle_new - theta[i];
angle_remain = a - angle_new;
x_temp = (x + (y>>i));
y_temp = (y - (x>>i));
x = x_temp;
y = y_temp;
detection = '-';
}
printf(" x = %-8d, y = %-8d, 旋转次数 = %-8d 旋转角度 = %-12d 旋转方向:%-8c 终点角度 = %-8d\n", x,y,i+1, theta[i],detection,angle_new);
}
x = r*x;
y = r*y;
return angle_remain;
}

完整的FPGA实现过程,包含预处理和后处理,支持{-π,π}的角度,采用流水线方式实现,Verilog完整代码如下,注意在移位过程中要用算术移位(>>>),才能保证带符号的数正确移位:


/****************************************************/
//预处理
module Cordic_Pre(
clk,
rst_n,
phi, phi_pre,
quadrant_flag
); /****************************************************/ input clk;
input rst_n;
input signed [23:0] phi; output signed [23:0] phi_pre; //预处理后的角度值
output [1:0] quadrant_flag; //象限标记 /****************************************************/ parameter ANGLE_P90 = 24'sd90_0000, //输入角度范围{-pi,pi},角度值放大了10000倍
ANGLE_N90 = -24'sd90_0000,
ANGLE_0 = 24'sd00_0000; /****************************************************/ reg signed [23:0] phi_pre_r;
reg [1:0] quadrant_flag_r; /****************************************************/ always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
phi_pre_r <= 24'sd0;
quadrant_flag_r <= 2'b00;
end
else if(phi >= ANGLE_0 && phi <= ANGLE_P90) //第一象限
begin
phi_pre_r <= phi;
quadrant_flag_r <= 2'b01;
end
else if(phi > ANGLE_P90 ) //第二象限
begin
phi_pre_r <= phi - ANGLE_P90;
quadrant_flag_r <= 2'b10;
end
else if(phi < ANGLE_0 && phi >= ANGLE_N90) //第四象限
begin
phi_pre_r <= phi;
quadrant_flag_r <= 2'b00;
end
else
begin //第三象限
phi_pre_r <= phi - ANGLE_N90;
quadrant_flag_r <= 2'b11;
end
end /****************************************************/ assign phi_pre = phi_pre_r;
assign quadrant_flag = quadrant_flag_r; /****************************************************/ endmodule

我的设计要求精度较高,所以采用20次旋转,旋转过程的代码如下:

/****************************************************/

module	Cordic_Rotate(
clk,
rst_n,
phi_pre,
quadrant_flag, ret_x,
ret_y,
quadrant
); /****************************************************/ input clk;
input rst_n;
input signed [23:0] phi_pre;
input [1:0] quadrant_flag; output signed [16:0] ret_x;
output signed [16:0] ret_y;
output [1:0] quadrant;
/****************************************************/ parameter X_ORIGN = 17'sd32768; //旋转时x的起始大小,根据精度要求而定。
//每次旋转的固定角度值
parameter ANGLE_1 = 24'sd450000, ANGLE_2 = 24'sd265651,
ANGLE_3 = 24'sd140362, ANGLE_4 = 24'sd71250,
ANGLE_5 = 24'sd35763, ANGLE_6 = 24'sd17899,
ANGLE_7 = 24'sd8952, ANGLE_8 = 24'sd4476,
ANGLE_9 = 24'sd2238, ANGLE_10 = 24'sd1119,
ANGLE_11 = 24'sd560, ANGLE_12 = 24'sd280,
ANGLE_13 = 24'sd140, ANGLE_14 = 24'sd70,
ANGLE_15 = 24'sd35, ANGLE_16 = 24'sd17,
ANGLE_17 = 24'sd9, ANGLE_18 = 24'sd4,
ANGLE_19 = 24'sd2, ANGLE_20 = 24'sd1; /****************************************************/ reg signed [16:0] x_r [20:0];
reg signed [16:0] y_r [20:0];
reg signed [23:0] angle_remain [20:0];
reg signed [1:0] quadrant_r [20:0]; /****************************************************/
//旋转的流水线过程
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[0] <= 17'sd0;
y_r[0] <= 17'sd0;
angle_remain[0] <= 24'sd0;
end
else
begin
x_r[0] <= X_ORIGN;
y_r[0] <= 17'sd0;
angle_remain[0] <= phi_pre;
end
end
//第1次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[1] <= 17'sd0;
y_r[1] <= 17'sd0;
angle_remain[1] <= 24'sd0;
end else if(angle_remain[0] > 24'sd0)
begin
x_r[1] <= x_r[0] - y_r[0];
y_r[1] <= y_r[0] + x_r[0];
angle_remain[1] <= angle_remain[0] - ANGLE_1;
end
else
begin
x_r[1] <= x_r[0] + y_r[0];
y_r[1] <= y_r[0] - x_r[0];
angle_remain[1] <= angle_remain[0] + ANGLE_1;
end
end
//第2次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[2] <= 17'sd0;
y_r[2] <= 17'sd0;
angle_remain[2] <= 24'sd0;
end
else if(angle_remain[1] > 24'sd0) //比较时,符号标记s必须带上,对结果有影响
begin
x_r[2] <= x_r[1] - (y_r[1] >>> 1);
y_r[2] <= y_r[1] + (x_r[1] >>> 1); //二元加的优先级高于算术移位
angle_remain[2] <= angle_remain[1] - ANGLE_2;
end
else
begin
x_r[2] <= x_r[1] + (y_r[1] >>> 1);
y_r[2] <= y_r[1] - (x_r[1] >>> 1);
angle_remain[2] <= angle_remain[1] + ANGLE_2;
end
end
//第3次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[3] <= 17'sd0;
y_r[3] <= 17'sd0;
angle_remain[3] <= 24'sd0;
end
else if(angle_remain[2] > 24'sd0)
begin
x_r[3] <= x_r[2] - (y_r[2] >>> 2);
y_r[3] <= y_r[2] + (x_r[2] >>> 2);
angle_remain[3] <= angle_remain[2] - ANGLE_3;
end
else
begin
x_r[3] <= x_r[2] + (y_r[2] >>> 2);
y_r[3] <= y_r[2] - (x_r[2] >>> 2);
angle_remain[3] <= angle_remain[2] + ANGLE_3;
end
end
//第4次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[4] <= 17'sd0;
y_r[4] <= 17'sd0;
angle_remain[4] <= 24'sd0;
end
else if(angle_remain[3] > 24'sd0)
begin
x_r[4] <= x_r[3] - (y_r[3] >>> 3);
y_r[4] <= y_r[3] + (x_r[3] >>> 3);
angle_remain[4] <= angle_remain[3] - ANGLE_4;
end
else
begin
x_r[4] <= x_r[3] + (y_r[3] >>> 3);
y_r[4] <= y_r[3] - (x_r[3] >>> 3);
angle_remain[4] <= angle_remain[3] + ANGLE_4;
end
end
//第5次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[5] <= 17'sd0;
y_r[5] <= 17'sd0;
angle_remain[5] <= 24'sd0;
end
else if(angle_remain[4] > 24'sd0)
begin
x_r[5] <= x_r[4] - (y_r[4] >>> 4);
y_r[5] <= y_r[4] + (x_r[4] >>> 4);
angle_remain[5] <= angle_remain[4] - ANGLE_5;
end
else
begin
x_r[5] <= x_r[4] + (y_r[4] >>> 4);
y_r[5] <= y_r[4] - (x_r[4] >>> 4);
angle_remain[5] <= angle_remain[4] + ANGLE_5;
end
end
//第6次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[6] <= 17'sd0;
y_r[6] <= 17'sd0;
angle_remain[6] <= 24'sd0;
end
else if(angle_remain[5] > 24'sd0)
begin
x_r[6] <= x_r[5] - (y_r[5] >>> 5);
y_r[6] <= y_r[5] + (x_r[5] >>> 5);
angle_remain[6] <= angle_remain[5] - ANGLE_6;
end
else
begin
x_r[6] <= x_r[5] + (y_r[5] >>> 5);
y_r[6] <= y_r[5] - (x_r[5] >>> 5);
angle_remain[6] <= angle_remain[5] + ANGLE_6;
end
end
//第7次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[7] <= 17'sd0;
y_r[7] <= 17'sd0;
angle_remain[7] <= 24'sd0;
end
else if(angle_remain[6] > 24'sd0)
begin
x_r[7] <= x_r[6] - (y_r[6] >>> 6);
y_r[7] <= y_r[6] + (x_r[6] >>> 6);
angle_remain[7] <= angle_remain[6] - ANGLE_7;
end
else
begin
x_r[7] <= x_r[6] + (y_r[6] >>> 6);
y_r[7] <= y_r[6] - (x_r[6] >>> 6);
angle_remain[7] <= angle_remain[6] + ANGLE_7;
end
end
//第8次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[8] <= 17'sd0;
y_r[8] <= 17'sd0;
angle_remain[8] <= 24'sd0;
end
else if(angle_remain[7] > 24'sd0)
begin
x_r[8] <= x_r[7] - (y_r[7] >>> 7);
y_r[8] <= y_r[7] + (x_r[7] >>> 7);
angle_remain[8] <= angle_remain[7] - ANGLE_8;
end
else
begin
x_r[8] <= x_r[7] + (y_r[7] >>> 7);
y_r[8] <= y_r[7] - (x_r[7] >>> 7);
angle_remain[8] <= angle_remain[7] + ANGLE_8;
end
end
//第9次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[9] <= 17'sd0;
y_r[9] <= 17'sd0;
angle_remain[9] <= 24'sd0;
end
else if(angle_remain[8] > 24'sd0)
begin
x_r[9] <= x_r[8] - (y_r[8] >>> 8);
y_r[9] <= y_r[8] + (x_r[8] >>> 8);
angle_remain[9] <= angle_remain[8] - ANGLE_9;
end
else
begin
x_r[9] <= x_r[8] + (y_r[8] >>> 8);
y_r[9] <= y_r[8] - (x_r[8] >>> 8);
angle_remain[9] <= angle_remain[8] + ANGLE_9;
end
end
//第10次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[10] <= 17'sd0;
y_r[10] <= 17'sd0;
angle_remain[10] <= 24'sd0;
end
else if(angle_remain[9] > 24'sd0)
begin
x_r[10] <= x_r[9] - (y_r[9] >>> 9);
y_r[10] <= y_r[9] + (x_r[9] >>> 9);
angle_remain[10] <= angle_remain[9] - ANGLE_10;
end
else
begin
x_r[10] <= x_r[9] + (y_r[9] >>> 9);
y_r[10] <= y_r[9] - (x_r[9] >>> 9);
angle_remain[10] <= angle_remain[9] + ANGLE_10;
end
end
//第11次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[11] <= 17'sd0;
y_r[11] <= 17'sd0;
angle_remain[11] <= 24'sd0;
end
else if(angle_remain[10] > 24'sd0)
begin
x_r[11] <= x_r[10] - (y_r[10] >>> 10);
y_r[11] <= y_r[10] + (x_r[10] >>> 10);
angle_remain[11] <= angle_remain[10] - ANGLE_11;
end
else
begin
x_r[11] <= x_r[10] + (y_r[10] >>> 10);
y_r[11] <= y_r[10] - (x_r[10] >>> 10);
angle_remain[11] <= angle_remain[10] + ANGLE_11;
end
end
//第12次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[12] <= 17'sd0;
y_r[12] <= 17'sd0;
angle_remain[12] <= 24'sd0;
end
else if(angle_remain[11] > 24'sd0)
begin
x_r[12] <= x_r[11] - (y_r[11] >>> 11);
y_r[12] <= y_r[11] + (x_r[11] >>> 11);
angle_remain[12] <= angle_remain[11] - ANGLE_12;
end
else
begin
x_r[12] <= x_r[11] + (y_r[11] >>> 11);
y_r[12] <= y_r[11] - (x_r[11] >>> 11);
angle_remain[12] <= angle_remain[11] + ANGLE_12;
end
end
//第13次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[13] <= 17'sd0;
y_r[13] <= 17'sd0;
angle_remain[13] <= 24'sd0;
end
else if(angle_remain[12] > 24'sd0)
begin
x_r[13] <= x_r[12] - (y_r[12] >>> 12);
y_r[13] <= y_r[12] + (x_r[12] >>> 12);
angle_remain[13] <= angle_remain[10] - ANGLE_13;
end
else
begin
x_r[13] <= x_r[12] + (y_r[12] >>> 12);
y_r[13] <= y_r[12] - (x_r[12] >>> 12);
angle_remain[13] <= angle_remain[12] + ANGLE_13;
end
end
//第14次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[14] <= 17'sd0;
y_r[14] <= 17'sd0;
angle_remain[14] <= 24'sd0;
end
else if(angle_remain[13] > 24'sd0)
begin
x_r[14] <= x_r[13] - (y_r[13] >>> 13);
y_r[14] <= y_r[13] + (x_r[13] >>> 13);
angle_remain[14] <= angle_remain[13] - ANGLE_14;
end
else
begin
x_r[14] <= x_r[13] + (y_r[13] >>> 13);
y_r[14] <= y_r[13] - (x_r[13] >>> 13);
angle_remain[14] <= angle_remain[13] + ANGLE_14;
end
end
//第15次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[15] <= 17'sd0;
y_r[15] <= 17'sd0;
angle_remain[15] <= 24'sd0;
end
else if(angle_remain[14] > 24'sd0)
begin
x_r[15] <= x_r[14] - (y_r[14] >>> 14);
y_r[15] <= y_r[14] + (x_r[14] >>> 14);
angle_remain[15] <= angle_remain[14] - ANGLE_15;
end
else
begin
x_r[15] <= x_r[14] + (y_r[14] >>> 14);
y_r[15] <= y_r[14] - (x_r[14] >>> 14);
angle_remain[15] <= angle_remain[14] + ANGLE_15;
end
end
//第16次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[16] <= 17'sd0;
y_r[16] <= 17'sd0;
angle_remain[16] <= 24'sd0;
end
else if(angle_remain[15] > 24'sd0)
begin
x_r[16] <= x_r[15] - (y_r[15] >>> 15);
y_r[16] <= y_r[15] + (x_r[15] >>> 15);
angle_remain[16] <= angle_remain[15] - ANGLE_16;
end
else
begin
x_r[16] <= x_r[15] + (y_r[15] >>> 15);
y_r[16] <= y_r[15] - (x_r[15] >>> 15);
angle_remain[16] <= angle_remain[15] + ANGLE_16;
end
end
//第17次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[17] <= 17'sd0;
y_r[17] <= 17'sd0;
angle_remain[17] <= 24'sd0;
end
else if(angle_remain[16] > 24'sd0)
begin
x_r[17] <= x_r[16] - (y_r[16] >>> 16);
y_r[17] <= y_r[16] + (x_r[16] >>> 16);
angle_remain[17] <= angle_remain[16] - ANGLE_17;
end
else
begin
x_r[17] <= x_r[16] + (y_r[16] >>> 16);
y_r[17] <= y_r[16] - (x_r[16] >>> 16);
angle_remain[17] <= angle_remain[16] + ANGLE_17;
end
end
//第18次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[18] <= 17'sd0;
y_r[18] <= 17'sd0;
angle_remain[18] <= 24'sd0;
end
else if(angle_remain[17] > 24'sd0)
begin
x_r[18] <= x_r[17] - (y_r[17] >>> 17);
y_r[18] <= y_r[17] + (x_r[17] >>> 17);
angle_remain[18] <= angle_remain[17] - ANGLE_18;
end
else
begin
x_r[18] <= x_r[17] + (y_r[17] >>> 17);
y_r[18] <= y_r[17] - (x_r[17] >>> 17);
angle_remain[18] <= angle_remain[17] + ANGLE_18;
end
end
//第19次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[19] <= 17'sd0;
y_r[19] <= 17'sd0;
angle_remain[19] <= 24'sd0;
end
else if(angle_remain[18] > 24'sd0)
begin
x_r[19] <= x_r[18] - (y_r[15] >>> 18);
y_r[19] <= y_r[18] + (x_r[15] >>> 18);
angle_remain[19] <= angle_remain[18] - ANGLE_19;
end
else
begin
x_r[19] <= x_r[18] + (y_r[18] >>> 18);
y_r[19] <= y_r[18] - (x_r[18] >>> 18);
angle_remain[19] <= angle_remain[18] + ANGLE_19;
end
end
//第20次旋转
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
x_r[20] <= 17'sd0;
y_r[20] <= 17'sd0;
angle_remain[20] <= 24'sd0;
end
else if(angle_remain[19] > 24'sd0)
begin
x_r[20] <= x_r[19] - (y_r[19] >>> 19);
y_r[20] <= y_r[19] + (x_r[19] >>> 19);
angle_remain[20] <= angle_remain[19] - ANGLE_20;
end
else
begin
x_r[20] <= x_r[19] + (y_r[19] >>> 19);
y_r[20] <= y_r[19] - (x_r[19] >>> 19);
angle_remain[20] <= angle_remain[19] + ANGLE_20;
end
end
/****************************************************/
//每个phi值的所在现象的流水线延迟
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
quadrant_r[0] <= 2'b00; //不能合并着写
quadrant_r[1] <= 2'b00;
quadrant_r[2] <= 2'b00;
quadrant_r[3] <= 2'b00;
quadrant_r[4] <= 2'b00;
quadrant_r[5] <= 2'b00;
quadrant_r[6] <= 2'b00;
quadrant_r[7] <= 2'b00;
quadrant_r[8] <= 2'b00;
quadrant_r[9] <= 2'b00;
quadrant_r[10] <= 2'b00;
quadrant_r[11] <= 2'b00;
quadrant_r[12] <= 2'b00;
quadrant_r[13] <= 2'b00;
quadrant_r[14] <= 2'b00;
quadrant_r[15] <= 2'b00;
quadrant_r[16] <= 2'b00;
quadrant_r[17] <= 2'b00;
quadrant_r[18] <= 2'b00;
quadrant_r[19] <= 2'b00;
quadrant_r[20] <= 2'b00;
end
else
begin
quadrant_r[0] <= quadrant_flag;
quadrant_r[1] <= quadrant_r[0];
quadrant_r[2] <= quadrant_r[1];
quadrant_r[3] <= quadrant_r[2];
quadrant_r[4] <= quadrant_r[3];
quadrant_r[5] <= quadrant_r[4];
quadrant_r[6] <= quadrant_r[5];
quadrant_r[7] <= quadrant_r[6];
quadrant_r[8] <= quadrant_r[7];
quadrant_r[9] <= quadrant_r[8];
quadrant_r[10] <= quadrant_r[9];
quadrant_r[11] <= quadrant_r[10];
quadrant_r[12] <= quadrant_r[11];
quadrant_r[13] <= quadrant_r[12];
quadrant_r[14] <= quadrant_r[13];
quadrant_r[15] <= quadrant_r[14];
quadrant_r[16] <= quadrant_r[15];
quadrant_r[17] <= quadrant_r[16];
quadrant_r[18] <= quadrant_r[17];
quadrant_r[19] <= quadrant_r[18];
quadrant_r[20] <= quadrant_r[19];
end end /****************************************************/
assign ret_x = x_r[20];
assign ret_y = y_r[20];
assign quadrant = quadrant_r[20];
/****************************************************/
endmodule

后处理将象限变换过的坐标还原:

/****************************************************/

module	Cordic_Post(
clk,
rst_n,
ret_x,
ret_y,
quadrant, sin_phi,
cos_phi
); /****************************************************/
input clk;
input rst_n;
input signed [16:0] ret_x;
input signed [16:0] ret_y;
input [1:0] quadrant; output signed [16:0] sin_phi;
output signed [16:0] cos_phi; /****************************************************/ reg signed [16:0] sin_phi_r;
reg signed [16:0] cos_phi_r; /****************************************************/ always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
sin_phi_r <= 17'sd0;
cos_phi_r <= 17'sd0;
end
else
case(quadrant) //根据原始角度所在象限,还原其三角函数值sin_phi和cos_phi
2'd01: //若再乘上极径和模长补偿因子,则实现直角坐标系变换
begin
cos_phi_r <= ret_x;
sin_phi_r <= ret_y;
end
2'd10:
begin
cos_phi_r <= ~ret_y + 1'b1;
sin_phi_r <= ret_x;
end
2'd11:
begin
cos_phi_r <= ret_y;
sin_phi_r <= ~ret_x + 1'b1;
end
2'd00:
begin
cos_phi_r <= ret_x;
sin_phi_r <= ret_y;
end
default:
begin
sin_phi_r <= 17'sd0;
cos_phi_r <= 17'sd0;
end
endcase end /****************************************************/
assign sin_phi = sin_phi_r;
assign cos_phi = cos_phi_r;
/****************************************************/
endmodule

在四个象限分别选取一个角度进行仿真,仿真结果如下图所示:

角度从输入到转换完毕,一共延时21个时钟周期。正好是预处理(1个周期)+旋转(20个周期)的结果。

2. 向量模式

至于向量模式,只要理解的算法思想,在编程上大同小异,如果要处理的坐标比较少,可以不采用流水线的方式。FPGA上用非流水线方式实现,Verilog主要代码片段如下,这次是用ROM存着旋转的固定角度值,利用addr地址线来读取相应的旋转角度:

3'd2:
if(times < 5'd16)
begin
if( yn_r !==22'd0) //当旋转到y=0时,提前结束,否则继续旋转反而影响精度
begin
if((yn_r[21])) //yn最高位为1时,即坐标在第四象限,则逆时针旋转
begin
xn_r <= xn_r - (yn_r >>> times);
yn_r <= yn_r + (xn_r >>> times);
addr_r <= addr_r + 1'd1;
times <= addr_r;
zn_r <= zn_r-angle;
i <= 3'd2;
end
else
begin //反之,坐标在第一象限,则顺时针旋转
xn_r <= xn_r + (yn_r >>> times);
yn_r <= yn_r - (xn_r >>> times);
addr_r <= addr_r + 1'd1;
times <= addr_r;
zn_r <= zn_r+angle;
i <= 3'd2;
end
end
else
begin
i <= i +1'b1;
end
end
else
begin
i <= i +1'b1;
end

至此,cordic基于圆周系统的算法总结完毕,至于还有基于线性系统、双曲系统来实现其它运算,等有机会了再学习。

参考

学习cordic算法所得(流水线结构、Verilog标准)

FPGA算法学习(1) -- Cordic(Verilog实现)的更多相关文章

  1. FPGA算法学习(1) -- Cordic(圆周系统之旋转模式)

    三角函数的计算是个复杂的主题,有计算机之前,人们通常通过查找三角函数表来计算任意角度的三角函数的值.这种表格在人们刚刚产生三角函数的概念的时候就已经有了,它们通常是通过从已知值(比如sin(π/2)= ...

  2. FPGA算法学习(1) -- Cordic(圆周系统之向量模式)

    旋转模式用来解决三角函数,实现极坐标到直角坐标的转换,基础理论请参考Cordic算法--圆周系统之旋转模式.那么,向量模式则用来解决反三角函数的问题,体现的应用主要是直角坐标向极坐标转换,即已知一点的 ...

  3. 【转载】FPGA算法设计随笔

    FPGA设计算法依次需要完成MATLAB浮点仿真 MATLAB定点仿真 verilogHDL定点运算以及数据对比的流程.其中浮点到定点的转换尤为重要,需要在数据表示范围和精度之间做出权衡.另外掌握定点 ...

  4. DSP算法学习-过采样技术

    DSP算法学习-过采样技术 彭会锋 2015-04-27 23:23:47 参考论文: 1 http://wr.lib.tsinghua.edu.cn/sites/default/files/1207 ...

  5. 算法学习之C语言基础

    算法学习,先熟悉一下C语言哈!!! #include <conio.h> #include<stdio.h> int main(){ printf(+); getch(); ; ...

  6. Python之路,Day21 - 常用算法学习

    Python之路,Day21 - 常用算法学习   本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的 ...

  7. C / C++算法学习笔记(8)-SHELL排序

    原始地址:C / C++算法学习笔记(8)-SHELL排序 基本思想 先取一个小于n的整数d1作为第一个增量(gap),把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组 ...

  8. 算法学习之BFS、DFS入门

    算法学习之BFS.DFS入门 0x1 问题描述 迷宫的最短路径 给定一个大小为N*M的迷宫.迷宫由通道和墙壁组成,每一步可以向相邻的上下左右四格的通道移动.请求出从起点到终点所需的最小步数.如果不能到 ...

  9. 二次剩余Cipolla算法学习笔记

    对于同余式 \[x^2 \equiv n \pmod p\] 若对于给定的\(n, P\),存在\(x\)满足上面的式子,则乘\(n\)在模\(p\)意义下是二次剩余,否则为非二次剩余 我们需要计算的 ...

随机推荐

  1. IERS-OSPF基本工作原理

    IERS-OSPF基本工作原理 一.邻居建立建立过程 1.Router ID 用于在自治系统中唯一标识一台运行OSPF的路由器,每台运行OSPF的路由器都有一个ROUTER ID Route ID 是 ...

  2. CMake是用于生成make文件的跨平台编译文件

    参考: https://www.cnblogs.com/hbccdf/p/introduction_of_cmake.html https://elloop.github.io/tools/2016- ...

  3. easyui学习笔记2—在行内进行表格的增删改操作

    第一篇笔记中记录了如何实现表格的增删改,那个是点击之后跳出来一个对话框然后进行的,这里是在表格本身上进行的操作,也很简单,但是这里发现一个版本问题,也可以说是兼容性问题. 1.首先我们看引用的js和c ...

  4. Micro

    Micro 架构与设计   Micro 架构与设计 翻译自 Micro architecture & design patterns for microservices 注: 原文作者即 Mi ...

  5. BZOJ 3680: 吊打XXX (模拟退火)

    //yy:今天简单入门学了下ORZ 爬山算法:兔子朝着比现在高的地方跳去.它找到了不远处的最高山峰.但是这座山不一定是珠穆朗玛峰.这就是爬山算法,它不能保证局部最优值就是全局最优值. 模拟退火:兔子喝 ...

  6. js递归错误

    错误信息:Uncaught RangeError: Maximum call stack size exceeded 问题代码: js代码:$(function(){        selectTog ...

  7. 【题解】洛谷P2661 [NOIP2015TG] 信息传递

    题目来源:洛谷P2661 思路 运用并查集查找图中最小环的长度 如果A传递信息给B 就从A加一条边指向B 并更新A的父节点 从A到父节点的路径长度为B到父节点的路径长度+1 如果有两个点的祖先相同而且 ...

  8. sharePoint中简单的父页面跳转子页面代码!

    1,SharePoint中挺简单的一个父页面跳转到子页面的Js代码!常常用到,每次都到以前的项目中去找代码,挺麻烦! (1)父页面代码. function imgAddParentclick() { ...

  9. HDBS之应用代码优化

    一.目录结构树 总体概述 代码检测工具sonar HDBS代码优化 总结开发注意点 二.总体概述 进入现在这家公司我的第一个任务就是对HDBS进行代码质量优化.HDBS可能大家不是很了解,现在给大家简 ...

  10. Unity 游戏框架搭建 2018 (二) 单例的模板与最佳实践

    Unity 游戏框架搭建 2018 (二) 单例的模板与最佳实践 背景 很多开发者或者有经验的老手都会建议尽量不要用单例模式,这是有原因的. 单例模式是设计模式中最简单的也是大家通常最先接触的一种设计 ...