Cordic算法——verilog实现

举报
李锐博恩 发表于 2021/07/15 03:03:18 2021/07/15
【摘要】   转载自:https://www.cnblogs.com/rouwawa/p/7102173.html   上两篇博文Cordic算法——圆周系统之旋转模式、Cordic算法——圆周系统之向量模式做了理论分析和实现,但是所用到的变量依然是浮点型,而cordic真正的用处是基于FPGA等只能处理定点的平台。只需将满足精度的浮点数,放大2^n倍,取整,...

 

转载自:https://www.cnblogs.com/rouwawa/p/7102173.html

 

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

1. 旋转模式

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

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


  
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int cordic_c(int a,int r);
  4. int x = 32768, y = 0; //以X轴为旋转起始点,放大倍数2^15
  5. int main(viod)
  6. {
  7. int remain = cordic_c(556767,1); //极坐标值(极角,极径)
  8. printf("旋转角度误差:%d, 直角坐标:x = %d, y = %d\n",remain,x,y);
  9. return 0;
  10. }
  11. int cordic_c(int a,int r)
  12. {
  13. const int theta[] = {450000,265651,140362,71250,35763,17899,8952,4476,2238,1119,560,280,140,70,35,17,9,4,2,1}; //旋转角度
  14. int i = 0;
  15. int x_temp = 0, y_temp = 0;
  16. int angle_new = 0; //旋转后终止角度
  17. int angle_remain = a; //旋转后,剩余角度
  18. char detection; //旋转方向
  19. for( i=0; i<20;i++)
  20. {
  21. if(angle_remain > 0)
  22. {
  23. angle_new = angle_new + theta[i];
  24. angle_remain = a - angle_new;
  25. x_temp = (x - (y >>i));
  26. y_temp = (y + (x >> i));
  27. x = x_temp;
  28. y = y_temp;
  29. detection = '+';
  30. }
  31. else
  32. {
  33. angle_new = angle_new - theta[i];
  34. angle_remain = a - angle_new;
  35. x_temp = (x + (y>>i));
  36. y_temp = (y - (x>>i));
  37. x = x_temp;
  38. y = y_temp;
  39. detection = '-';
  40. }
  41. printf(" x = %-8d, y = %-8d, 旋转次数 = %-8d 旋转角度 = %-12d 旋转方向:%-8c 终点角度 = %-8d\n", x,y,i+1, theta[i],detection,angle_new);
  42. }
  43. x = r*x;
  44. y = r*y;
  45. return angle_remain;
  46. }

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


  
  1. /****************************************************/
  2. //预处理
  3. module Cordic_Pre(
  4. clk,
  5. rst_n,
  6. phi,
  7. phi_pre,
  8. quadrant_flag
  9. );
  10. /****************************************************/
  11. input clk;
  12. input rst_n;
  13. input signed [23:0] phi;
  14. output signed [23:0] phi_pre; //预处理后的角度值
  15. output [1:0] quadrant_flag; //象限标记
  16. /****************************************************/
  17. parameter ANGLE_P90 = 24'sd90_0000, //输入角度范围{-pi,pi},角度值放大了10000倍
  18. ANGLE_N90 = -24'sd90_0000,
  19. ANGLE_0 = 24'sd00_0000;
  20. /****************************************************/
  21. reg signed [23:0] phi_pre_r;
  22. reg [1:0] quadrant_flag_r;
  23. /****************************************************/
  24. always @(posedge clk or negedge rst_n)
  25. begin
  26. if(rst_n == 1'b0)
  27. begin
  28. phi_pre_r <= 24'sd0;
  29. quadrant_flag_r <= 2'b00;
  30. end
  31. else if(phi >= ANGLE_0 && phi <= ANGLE_P90) //第一象限
  32. begin
  33. phi_pre_r <= phi;
  34. quadrant_flag_r <= 2'b01;
  35. end
  36. else if(phi > ANGLE_P90 ) //第二象限
  37. begin
  38. phi_pre_r <= phi - ANGLE_P90;
  39. quadrant_flag_r <= 2'b10;
  40. end
  41. else if(phi < ANGLE_0 && phi >= ANGLE_N90) //第四象限
  42. begin
  43. phi_pre_r <= phi;
  44. quadrant_flag_r <= 2'b00;
  45. end
  46. else
  47. begin //第三象限
  48. phi_pre_r <= phi - ANGLE_N90;
  49. quadrant_flag_r <= 2'b11;
  50. end
  51. end
  52. /****************************************************/
  53. assign phi_pre = phi_pre_r;
  54. assign quadrant_flag = quadrant_flag_r;
  55. /****************************************************/
  56. endmodule

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


  
  1. /****************************************************/
  2. module Cordic_Rotate(
  3. clk,
  4. rst_n,
  5. phi_pre,
  6. quadrant_flag,
  7. ret_x,
  8. ret_y,
  9. quadrant
  10. );
  11. /****************************************************/
  12. input clk;
  13. input rst_n;
  14. input signed [23:0] phi_pre;
  15. input [1:0] quadrant_flag;
  16. output signed [16:0] ret_x;
  17. output signed [16:0] ret_y;
  18. output [1:0] quadrant;
  19. /****************************************************/
  20. parameter X_ORIGN = 17'sd32768; //旋转时x的起始大小,根据精度要求而定。
  21. //每次旋转的固定角度值
  22. parameter ANGLE_1 = 24'sd450000, ANGLE_2 = 24'sd265651,
  23. ANGLE_3 = 24'sd140362, ANGLE_4 = 24'sd71250,
  24. ANGLE_5 = 24'sd35763, ANGLE_6 = 24'sd17899,
  25. ANGLE_7 = 24'sd8952, ANGLE_8 = 24'sd4476,
  26. ANGLE_9 = 24'sd2238, ANGLE_10 = 24'sd1119,
  27. ANGLE_11 = 24'sd560, ANGLE_12 = 24'sd280,
  28. ANGLE_13 = 24'sd140, ANGLE_14 = 24'sd70,
  29. ANGLE_15 = 24'sd35, ANGLE_16 = 24'sd17,
  30. ANGLE_17 = 24'sd9, ANGLE_18 = 24'sd4,
  31. ANGLE_19 = 24'sd2, ANGLE_20 = 24'sd1;
  32. /****************************************************/
  33. reg signed [16:0] x_r [20:0];
  34. reg signed [16:0] y_r [20:0];
  35. reg signed [23:0] angle_remain [20:0];
  36. reg signed [1:0] quadrant_r [20:0];
  37. /****************************************************/
  38. //旋转的流水线过程
  39. always @(posedge clk or negedge rst_n)
  40. begin
  41. if(rst_n == 1'b0)
  42. begin
  43. x_r[0] <= 17'sd0;
  44. y_r[0] <= 17'sd0;
  45. angle_remain[0] <= 24'sd0;
  46. end
  47. else
  48. begin
  49. x_r[0] <= X_ORIGN;
  50. y_r[0] <= 17'sd0;
  51. angle_remain[0] <= phi_pre;
  52. end
  53. end
  54. //第1次旋转
  55. always @(posedge clk or negedge rst_n)
  56. begin
  57. if(rst_n == 1'b0)
  58. begin
  59. x_r[1] <= 17'sd0;
  60. y_r[1] <= 17'sd0;
  61. angle_remain[1] <= 24'sd0;
  62. end
  63. else if(angle_remain[0] > 24'sd0)
  64. begin
  65. x_r[1] <= x_r[0] - y_r[0];
  66. y_r[1] <= y_r[0] + x_r[0];
  67. angle_remain[1] <= angle_remain[0] - ANGLE_1;
  68. end
  69. else
  70. begin
  71. x_r[1] <= x_r[0] + y_r[0];
  72. y_r[1] <= y_r[0] - x_r[0];
  73. angle_remain[1] <= angle_remain[0] + ANGLE_1;
  74. end
  75. end
  76. //第2次旋转
  77. always @(posedge clk or negedge rst_n)
  78. begin
  79. if(rst_n == 1'b0)
  80. begin
  81. x_r[2] <= 17'sd0;
  82. y_r[2] <= 17'sd0;
  83. angle_remain[2] <= 24'sd0;
  84. end
  85. else if(angle_remain[1] > 24'sd0) //比较时,符号标记s必须带上,对结果有影响
  86. begin
  87. x_r[2] <= x_r[1] - (y_r[1] >>> 1);
  88. y_r[2] <= y_r[1] + (x_r[1] >>> 1); //二元加的优先级高于算术移位
  89. angle_remain[2] <= angle_remain[1] - ANGLE_2;
  90. end
  91. else
  92. begin
  93. x_r[2] <= x_r[1] + (y_r[1] >>> 1);
  94. y_r[2] <= y_r[1] - (x_r[1] >>> 1);
  95. angle_remain[2] <= angle_remain[1] + ANGLE_2;
  96. end
  97. end
  98. //第3次旋转
  99. always @(posedge clk or negedge rst_n)
  100. begin
  101. if(rst_n == 1'b0)
  102. begin
  103. x_r[3] <= 17'sd0;
  104. y_r[3] <= 17'sd0;
  105. angle_remain[3] <= 24'sd0;
  106. end
  107. else if(angle_remain[2] > 24'sd0)
  108. begin
  109. x_r[3] <= x_r[2] - (y_r[2] >>> 2);
  110. y_r[3] <= y_r[2] + (x_r[2] >>> 2);
  111. angle_remain[3] <= angle_remain[2] - ANGLE_3;
  112. end
  113. else
  114. begin
  115. x_r[3] <= x_r[2] + (y_r[2] >>> 2);
  116. y_r[3] <= y_r[2] - (x_r[2] >>> 2);
  117. angle_remain[3] <= angle_remain[2] + ANGLE_3;
  118. end
  119. end
  120. //第4次旋转
  121. always @(posedge clk or negedge rst_n)
  122. begin
  123. if(rst_n == 1'b0)
  124. begin
  125. x_r[4] <= 17'sd0;
  126. y_r[4] <= 17'sd0;
  127. angle_remain[4] <= 24'sd0;
  128. end
  129. else if(angle_remain[3] > 24'sd0)
  130. begin
  131. x_r[4] <= x_r[3] - (y_r[3] >>> 3);
  132. y_r[4] <= y_r[3] + (x_r[3] >>> 3);
  133. angle_remain[4] <= angle_remain[3] - ANGLE_4;
  134. end
  135. else
  136. begin
  137. x_r[4] <= x_r[3] + (y_r[3] >>> 3);
  138. y_r[4] <= y_r[3] - (x_r[3] >>> 3);
  139. angle_remain[4] <= angle_remain[3] + ANGLE_4;
  140. end
  141. end
  142. //第5次旋转
  143. always @(posedge clk or negedge rst_n)
  144. begin
  145. if(rst_n == 1'b0)
  146. begin
  147. x_r[5] <= 17'sd0;
  148. y_r[5] <= 17'sd0;
  149. angle_remain[5] <= 24'sd0;
  150. end
  151. else if(angle_remain[4] > 24'sd0)
  152. begin
  153. x_r[5] <= x_r[4] - (y_r[4] >>> 4);
  154. y_r[5] <= y_r[4] + (x_r[4] >>> 4);
  155. angle_remain[5] <= angle_remain[4] - ANGLE_5;
  156. end
  157. else
  158. begin
  159. x_r[5] <= x_r[4] + (y_r[4] >>> 4);
  160. y_r[5] <= y_r[4] - (x_r[4] >>> 4);
  161. angle_remain[5] <= angle_remain[4] + ANGLE_5;
  162. end
  163. end
  164. //第6次旋转
  165. always @(posedge clk or negedge rst_n)
  166. begin
  167. if(rst_n == 1'b0)
  168. begin
  169. x_r[6] <= 17'sd0;
  170. y_r[6] <= 17'sd0;
  171. angle_remain[6] <= 24'sd0;
  172. end
  173. else if(angle_remain[5] > 24'sd0)
  174. begin
  175. x_r[6] <= x_r[5] - (y_r[5] >>> 5);
  176. y_r[6] <= y_r[5] + (x_r[5] >>> 5);
  177. angle_remain[6] <= angle_remain[5] - ANGLE_6;
  178. end
  179. else
  180. begin
  181. x_r[6] <= x_r[5] + (y_r[5] >>> 5);
  182. y_r[6] <= y_r[5] - (x_r[5] >>> 5);
  183. angle_remain[6] <= angle_remain[5] + ANGLE_6;
  184. end
  185. end
  186. //第7次旋转
  187. always @(posedge clk or negedge rst_n)
  188. begin
  189. if(rst_n == 1'b0)
  190. begin
  191. x_r[7] <= 17'sd0;
  192. y_r[7] <= 17'sd0;
  193. angle_remain[7] <= 24'sd0;
  194. end
  195. else if(angle_remain[6] > 24'sd0)
  196. begin
  197. x_r[7] <= x_r[6] - (y_r[6] >>> 6);
  198. y_r[7] <= y_r[6] + (x_r[6] >>> 6);
  199. angle_remain[7] <= angle_remain[6] - ANGLE_7;
  200. end
  201. else
  202. begin
  203. x_r[7] <= x_r[6] + (y_r[6] >>> 6);
  204. y_r[7] <= y_r[6] - (x_r[6] >>> 6);
  205. angle_remain[7] <= angle_remain[6] + ANGLE_7;
  206. end
  207. end
  208. //第8次旋转
  209. always @(posedge clk or negedge rst_n)
  210. begin
  211. if(rst_n == 1'b0)
  212. begin
  213. x_r[8] <= 17'sd0;
  214. y_r[8] <= 17'sd0;
  215. angle_remain[8] <= 24'sd0;
  216. end
  217. else if(angle_remain[7] > 24'sd0)
  218. begin
  219. x_r[8] <= x_r[7] - (y_r[7] >>> 7);
  220. y_r[8] <= y_r[7] + (x_r[7] >>> 7);
  221. angle_remain[8] <= angle_remain[7] - ANGLE_8;
  222. end
  223. else
  224. begin
  225. x_r[8] <= x_r[7] + (y_r[7] >>> 7);
  226. y_r[8] <= y_r[7] - (x_r[7] >>> 7);
  227. angle_remain[8] <= angle_remain[7] + ANGLE_8;
  228. end
  229. end
  230. //第9次旋转
  231. always @(posedge clk or negedge rst_n)
  232. begin
  233. if(rst_n == 1'b0)
  234. begin
  235. x_r[9] <= 17'sd0;
  236. y_r[9] <= 17'sd0;
  237. angle_remain[9] <= 24'sd0;
  238. end
  239. else if(angle_remain[8] > 24'sd0)
  240. begin
  241. x_r[9] <= x_r[8] - (y_r[8] >>> 8);
  242. y_r[9] <= y_r[8] + (x_r[8] >>> 8);
  243. angle_remain[9] <= angle_remain[8] - ANGLE_9;
  244. end
  245. else
  246. begin
  247. x_r[9] <= x_r[8] + (y_r[8] >>> 8);
  248. y_r[9] <= y_r[8] - (x_r[8] >>> 8);
  249. angle_remain[9] <= angle_remain[8] + ANGLE_9;
  250. end
  251. end
  252. //第10次旋转
  253. always @(posedge clk or negedge rst_n)
  254. begin
  255. if(rst_n == 1'b0)
  256. begin
  257. x_r[10] <= 17'sd0;
  258. y_r[10] <= 17'sd0;
  259. angle_remain[10] <= 24'sd0;
  260. end
  261. else if(angle_remain[9] > 24'sd0)
  262. begin
  263. x_r[10] <= x_r[9] - (y_r[9] >>> 9);
  264. y_r[10] <= y_r[9] + (x_r[9] >>> 9);
  265. angle_remain[10] <= angle_remain[9] - ANGLE_10;
  266. end
  267. else
  268. begin
  269. x_r[10] <= x_r[9] + (y_r[9] >>> 9);
  270. y_r[10] <= y_r[9] - (x_r[9] >>> 9);
  271. angle_remain[10] <= angle_remain[9] + ANGLE_10;
  272. end
  273. end
  274. //第11次旋转
  275. always @(posedge clk or negedge rst_n)
  276. begin
  277. if(rst_n == 1'b0)
  278. begin
  279. x_r[11] <= 17'sd0;
  280. y_r[11] <= 17'sd0;
  281. angle_remain[11] <= 24'sd0;
  282. end
  283. else if(angle_remain[10] > 24'sd0)
  284. begin
  285. x_r[11] <= x_r[10] - (y_r[10] >>> 10);
  286. y_r[11] <= y_r[10] + (x_r[10] >>> 10);
  287. angle_remain[11] <= angle_remain[10] - ANGLE_11;
  288. end
  289. else
  290. begin
  291. x_r[11] <= x_r[10] + (y_r[10] >>> 10);
  292. y_r[11] <= y_r[10] - (x_r[10] >>> 10);
  293. angle_remain[11] <= angle_remain[10] + ANGLE_11;
  294. end
  295. end
  296. //第12次旋转
  297. always @(posedge clk or negedge rst_n)
  298. begin
  299. if(rst_n == 1'b0)
  300. begin
  301. x_r[12] <= 17'sd0;
  302. y_r[12] <= 17'sd0;
  303. angle_remain[12] <= 24'sd0;
  304. end
  305. else if(angle_remain[11] > 24'sd0)
  306. begin
  307. x_r[12] <= x_r[11] - (y_r[11] >>> 11);
  308. y_r[12] <= y_r[11] + (x_r[11] >>> 11);
  309. angle_remain[12] <= angle_remain[11] - ANGLE_12;
  310. end
  311. else
  312. begin
  313. x_r[12] <= x_r[11] + (y_r[11] >>> 11);
  314. y_r[12] <= y_r[11] - (x_r[11] >>> 11);
  315. angle_remain[12] <= angle_remain[11] + ANGLE_12;
  316. end
  317. end
  318. //第13次旋转
  319. always @(posedge clk or negedge rst_n)
  320. begin
  321. if(rst_n == 1'b0)
  322. begin
  323. x_r[13] <= 17'sd0;
  324. y_r[13] <= 17'sd0;
  325. angle_remain[13] <= 24'sd0;
  326. end
  327. else if(angle_remain[12] > 24'sd0)
  328. begin
  329. x_r[13] <= x_r[12] - (y_r[12] >>> 12);
  330. y_r[13] <= y_r[12] + (x_r[12] >>> 12);
  331. angle_remain[13] <= angle_remain[10] - ANGLE_13;
  332. end
  333. else
  334. begin
  335. x_r[13] <= x_r[12] + (y_r[12] >>> 12);
  336. y_r[13] <= y_r[12] - (x_r[12] >>> 12);
  337. angle_remain[13] <= angle_remain[12] + ANGLE_13;
  338. end
  339. end
  340. //第14次旋转
  341. always @(posedge clk or negedge rst_n)
  342. begin
  343. if(rst_n == 1'b0)
  344. begin
  345. x_r[14] <= 17'sd0;
  346. y_r[14] <= 17'sd0;
  347. angle_remain[14] <= 24'sd0;
  348. end
  349. else if(angle_remain[13] > 24'sd0)
  350. begin
  351. x_r[14] <= x_r[13] - (y_r[13] >>> 13);
  352. y_r[14] <= y_r[13] + (x_r[13] >>> 13);
  353. angle_remain[14] <= angle_remain[13] - ANGLE_14;
  354. end
  355. else
  356. begin
  357. x_r[14] <= x_r[13] + (y_r[13] >>> 13);
  358. y_r[14] <= y_r[13] - (x_r[13] >>> 13);
  359. angle_remain[14] <= angle_remain[13] + ANGLE_14;
  360. end
  361. end
  362. //第15次旋转
  363. always @(posedge clk or negedge rst_n)
  364. begin
  365. if(rst_n == 1'b0)
  366. begin
  367. x_r[15] <= 17'sd0;
  368. y_r[15] <= 17'sd0;
  369. angle_remain[15] <= 24'sd0;
  370. end
  371. else if(angle_remain[14] > 24'sd0)
  372. begin
  373. x_r[15] <= x_r[14] - (y_r[14] >>> 14);
  374. y_r[15] <= y_r[14] + (x_r[14] >>> 14);
  375. angle_remain[15] <= angle_remain[14] - ANGLE_15;
  376. end
  377. else
  378. begin
  379. x_r[15] <= x_r[14] + (y_r[14] >>> 14);
  380. y_r[15] <= y_r[14] - (x_r[14] >>> 14);
  381. angle_remain[15] <= angle_remain[14] + ANGLE_15;
  382. end
  383. end
  384. //第16次旋转
  385. always @(posedge clk or negedge rst_n)
  386. begin
  387. if(rst_n == 1'b0)
  388. begin
  389. x_r[16] <= 17'sd0;
  390. y_r[16] <= 17'sd0;
  391. angle_remain[16] <= 24'sd0;
  392. end
  393. else if(angle_remain[15] > 24'sd0)
  394. begin
  395. x_r[16] <= x_r[15] - (y_r[15] >>> 15);
  396. y_r[16] <= y_r[15] + (x_r[15] >>> 15);
  397. angle_remain[16] <= angle_remain[15] - ANGLE_16;
  398. end
  399. else
  400. begin
  401. x_r[16] <= x_r[15] + (y_r[15] >>> 15);
  402. y_r[16] <= y_r[15] - (x_r[15] >>> 15);
  403. angle_remain[16] <= angle_remain[15] + ANGLE_16;
  404. end
  405. end
  406. //第17次旋转
  407. always @(posedge clk or negedge rst_n)
  408. begin
  409. if(rst_n == 1'b0)
  410. begin
  411. x_r[17] <= 17'sd0;
  412. y_r[17] <= 17'sd0;
  413. angle_remain[17] <= 24'sd0;
  414. end
  415. else if(angle_remain[16] > 24'sd0)
  416. begin
  417. x_r[17] <= x_r[16] - (y_r[16] >>> 16);
  418. y_r[17] <= y_r[16] + (x_r[16] >>> 16);
  419. angle_remain[17] <= angle_remain[16] - ANGLE_17;
  420. end
  421. else
  422. begin
  423. x_r[17] <= x_r[16] + (y_r[16] >>> 16);
  424. y_r[17] <= y_r[16] - (x_r[16] >>> 16);
  425. angle_remain[17] <= angle_remain[16] + ANGLE_17;
  426. end
  427. end
  428. //第18次旋转
  429. always @(posedge clk or negedge rst_n)
  430. begin
  431. if(rst_n == 1'b0)
  432. begin
  433. x_r[18] <= 17'sd0;
  434. y_r[18] <= 17'sd0;
  435. angle_remain[18] <= 24'sd0;
  436. end
  437. else if(angle_remain[17] > 24'sd0)
  438. begin
  439. x_r[18] <= x_r[17] - (y_r[17] >>> 17);
  440. y_r[18] <= y_r[17] + (x_r[17] >>> 17);
  441. angle_remain[18] <= angle_remain[17] - ANGLE_18;
  442. end
  443. else
  444. begin
  445. x_r[18] <= x_r[17] + (y_r[17] >>> 17);
  446. y_r[18] <= y_r[17] - (x_r[17] >>> 17);
  447. angle_remain[18] <= angle_remain[17] + ANGLE_18;
  448. end
  449. end
  450. //第19次旋转
  451. always @(posedge clk or negedge rst_n)
  452. begin
  453. if(rst_n == 1'b0)
  454. begin
  455. x_r[19] <= 17'sd0;
  456. y_r[19] <= 17'sd0;
  457. angle_remain[19] <= 24'sd0;
  458. end
  459. else if(angle_remain[18] > 24'sd0)
  460. begin
  461. x_r[19] <= x_r[18] - (y_r[15] >>> 18);
  462. y_r[19] <= y_r[18] + (x_r[15] >>> 18);
  463. angle_remain[19] <= angle_remain[18] - ANGLE_19;
  464. end
  465. else
  466. begin
  467. x_r[19] <= x_r[18] + (y_r[18] >>> 18);
  468. y_r[19] <= y_r[18] - (x_r[18] >>> 18);
  469. angle_remain[19] <= angle_remain[18] + ANGLE_19;
  470. end
  471. end
  472. //第20次旋转
  473. always @(posedge clk or negedge rst_n)
  474. begin
  475. if(rst_n == 1'b0)
  476. begin
  477. x_r[20] <= 17'sd0;
  478. y_r[20] <= 17'sd0;
  479. angle_remain[20] <= 24'sd0;
  480. end
  481. else if(angle_remain[19] > 24'sd0)
  482. begin
  483. x_r[20] <= x_r[19] - (y_r[19] >>> 19);
  484. y_r[20] <= y_r[19] + (x_r[19] >>> 19);
  485. angle_remain[20] <= angle_remain[19] - ANGLE_20;
  486. end
  487. else
  488. begin
  489. x_r[20] <= x_r[19] + (y_r[19] >>> 19);
  490. y_r[20] <= y_r[19] - (x_r[19] >>> 19);
  491. angle_remain[20] <= angle_remain[19] + ANGLE_20;
  492. end
  493. end
  494. /****************************************************/
  495. //每个phi值的所在现象的流水线延迟
  496. always @(posedge clk or negedge rst_n)
  497. begin
  498. if(rst_n == 1'b0)
  499. begin
  500. quadrant_r[0] <= 2'b00; //不能合并着写
  501. quadrant_r[1] <= 2'b00;
  502. quadrant_r[2] <= 2'b00;
  503. quadrant_r[3] <= 2'b00;
  504. quadrant_r[4] <= 2'b00;
  505. quadrant_r[5] <= 2'b00;
  506. quadrant_r[6] <= 2'b00;
  507. quadrant_r[7] <= 2'b00;
  508. quadrant_r[8] <= 2'b00;
  509. quadrant_r[9] <= 2'b00;
  510. quadrant_r[10] <= 2'b00;
  511. quadrant_r[11] <= 2'b00;
  512. quadrant_r[12] <= 2'b00;
  513. quadrant_r[13] <= 2'b00;
  514. quadrant_r[14] <= 2'b00;
  515. quadrant_r[15] <= 2'b00;
  516. quadrant_r[16] <= 2'b00;
  517. quadrant_r[17] <= 2'b00;
  518. quadrant_r[18] <= 2'b00;
  519. quadrant_r[19] <= 2'b00;
  520. quadrant_r[20] <= 2'b00;
  521. end
  522. else
  523. begin
  524. quadrant_r[0] <= quadrant_flag;
  525. quadrant_r[1] <= quadrant_r[0];
  526. quadrant_r[2] <= quadrant_r[1];
  527. quadrant_r[3] <= quadrant_r[2];
  528. quadrant_r[4] <= quadrant_r[3];
  529. quadrant_r[5] <= quadrant_r[4];
  530. quadrant_r[6] <= quadrant_r[5];
  531. quadrant_r[7] <= quadrant_r[6];
  532. quadrant_r[8] <= quadrant_r[7];
  533. quadrant_r[9] <= quadrant_r[8];
  534. quadrant_r[10] <= quadrant_r[9];
  535. quadrant_r[11] <= quadrant_r[10];
  536. quadrant_r[12] <= quadrant_r[11];
  537. quadrant_r[13] <= quadrant_r[12];
  538. quadrant_r[14] <= quadrant_r[13];
  539. quadrant_r[15] <= quadrant_r[14];
  540. quadrant_r[16] <= quadrant_r[15];
  541. quadrant_r[17] <= quadrant_r[16];
  542. quadrant_r[18] <= quadrant_r[17];
  543. quadrant_r[19] <= quadrant_r[18];
  544. quadrant_r[20] <= quadrant_r[19];
  545. end
  546. end
  547. /****************************************************/
  548. assign ret_x = x_r[20];
  549. assign ret_y = y_r[20];
  550. assign quadrant = quadrant_r[20];
  551. /****************************************************/
  552. endmodule

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


  
  1. /****************************************************/
  2. module Cordic_Post(
  3. clk,
  4. rst_n,
  5. ret_x,
  6. ret_y,
  7. quadrant,
  8. sin_phi,
  9. cos_phi
  10. );
  11. /****************************************************/
  12. input clk;
  13. input rst_n;
  14. input signed [16:0] ret_x;
  15. input signed [16:0] ret_y;
  16. input [1:0] quadrant;
  17. output signed [16:0] sin_phi;
  18. output signed [16:0] cos_phi;
  19. /****************************************************/
  20. reg signed [16:0] sin_phi_r;
  21. reg signed [16:0] cos_phi_r;
  22. /****************************************************/
  23. always @(posedge clk or negedge rst_n)
  24. begin
  25. if(rst_n == 1'b0)
  26. begin
  27. sin_phi_r <= 17'sd0;
  28. cos_phi_r <= 17'sd0;
  29. end
  30. else
  31. case(quadrant) //根据原始角度所在象限,还原其三角函数值sin_phi和cos_phi
  32. 2'd01: //若再乘上极径和模长补偿因子,则实现直角坐标系变换
  33. begin
  34. cos_phi_r <= ret_x;
  35. sin_phi_r <= ret_y;
  36. end
  37. 2'd10:
  38. begin
  39. cos_phi_r <= ~ret_y + 1'b1;
  40. sin_phi_r <= ret_x;
  41. end
  42. 2'd11:
  43. begin
  44. cos_phi_r <= ret_y;
  45. sin_phi_r <= ~ret_x + 1'b1;
  46. end
  47. 2'd00:
  48. begin
  49. cos_phi_r <= ret_x;
  50. sin_phi_r <= ret_y;
  51. end
  52. default:
  53. begin
  54. sin_phi_r <= 17'sd0;
  55. cos_phi_r <= 17'sd0;
  56. end
  57. endcase
  58. end
  59. /****************************************************/
  60. assign sin_phi = sin_phi_r;
  61. assign cos_phi = cos_phi_r;
  62. /****************************************************/
  63. endmodule

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

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

2. 向量模式

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


  
  1. 3'd2:
  2. if(times < 5'd16)
  3. begin
  4. if( yn_r !==22'd0) //当旋转到y=0时,提前结束,否则继续旋转反而影响精度
  5. begin
  6. if((yn_r[21])) //yn最高位为1时,即坐标在第四象限,则逆时针旋转
  7. begin
  8. xn_r <= xn_r - (yn_r >>> times);
  9. yn_r <= yn_r + (xn_r >>> times);
  10. addr_r <= addr_r + 1'd1;
  11. times <= addr_r;
  12. zn_r <= zn_r-angle;
  13. i <= 3'd2;
  14. end
  15. else
  16. begin //反之,坐标在第一象限,则顺时针旋转
  17. xn_r <= xn_r + (yn_r >>> times);
  18. yn_r <= yn_r - (xn_r >>> times);
  19. addr_r <= addr_r + 1'd1;
  20. times <= addr_r;
  21. zn_r <= zn_r+angle;
  22. i <= 3'd2;
  23. end
  24. end
  25. else
  26. begin
  27. i <= i +1'b1;
  28. end
  29. end
  30. else
  31. begin
  32. i <= i +1'b1;
  33. end

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

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/87436090

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。