CORDIC算法原理详解及其Verilog实现
CORDIC算法原理詳解及其Verilog實現
本文的verilog代碼
鏈接:https://pan.baidu.com/s/1GGbRjxO5CxoIODQAg1l6Lw
提取碼:jo0h
*本文的Verilog代碼均沒有考慮象限問題,MATLAB代碼有考慮。
*本文參考博客
[1]https://blog.csdn.net/qq_39210023/article/details/77456031
[2]https://blog.csdn.net/longxuekun1992/article/details/52435024
文章目錄
- CORDIC 簡介
- 算法實現
- 1.已知坐標(x,y),求其向量對應的相角θ(反正切)和模值
- 1.1 MATLAB代碼
- 1.2 Verilog代碼
- 1.3 testbench A
- 2.已知角度θ,求正弦sinθ和余弦cosθ
- 2.1 MATLAB代碼
- 2.2 Verilog代碼
- 2.3 Testbench B
CORDIC 簡介
CORDIC(Coordinate Rotation Digital Computer)坐標旋轉數字計算機,是數學與計算機技術交叉產生的一種機器算法,用于解決計算機的數學計算問題。發展到現在,CORDIC算法及其擴展算法大致有三種計算模式:圓周旋轉模式、線性旋轉模式和雙曲線旋轉模式,分別用來實現不同的數學運算。本文介紹圓周旋轉模式下的CORDIC算法原理及實現過程,另兩種模式將分期介紹。
簡單來講,CORDIC利用近似逼近的思想,將計算機中三角函數、開根號、求對數等復雜運算,轉化為簡單的加減和移位操作。
1)算法描述
如圖,XY平面中一點( x 1 , y 1 ) 經圓周旋轉θ角度,得到點( x 2 , y 2 ) 。經簡單的三角函數關系,可得到:
通過提出因數cosθ,可得:
如果不考慮cosθ,得到“偽旋轉”方程:
偽旋轉僅實現了正確的角度旋轉,但向量模值變為原來的1/cosθ。
2)CORDIC方法
注意!上式已經僅剩加減和移位運算。
可以確定的是,任意旋轉角度θ,都可以由上表中的大小不同θi進行多次旋轉得到。CORDIC正是利用這一點,將θ角度的旋轉分解為從大到小、逐次逼近真實旋轉角度的一組旋轉,而這些旋轉的實現又都可以由加減和移位運算來完成。θi可以預先制成表格,供計算機查找使用。
算法實現
1.已知坐標(x,y),求其向量對應的相角θ(反正切)和模值
思想:把原向量逐次向X正軸進行偽旋轉逼近,整個過程的累計旋轉角度即為θ,而旋轉后的x坐標補償模值增益K后即為原向量模值。
每次迭代的方程為:
模值總增益K為:
其中d決定旋轉方向為逆時針還是順時針,z為角度累加值。
注意!查找表中所有θi的總和約為99度,因此能實現計算的角度在-99~99度之間。實際算法實現時,我們可預先判斷坐標象限,人為將其轉化為第一象限內的計算,并在事后補償為真實值。
1.1 MATLAB代碼
%% *********************************************************************************** % 已知坐標,用cordic算法計算相角和幅值。基本公式如下: % x(k+1) = x(k) - d(k)*y(k)*2^(-k) % y(k+1) = y(k) + d(k)*x(k)*2^(-k) % z(k) = z(k) - d(k)*actan(2^(-k)) %% ***********************************************************************************clear;close all;clc; % 初始化---------------------------------------- N = 16; %迭代次數 tan_table = 2.^-(0 : N-1); angle_LUT = atan(tan_table);K = 1; for k = 0 : N-1K = K*(1/sqrt(1 + 2^(-2*k))); endx = 3; y = sqrt(3); angle_accumulate = 0;% cordic算法計算------------------------------- if (x==0 && y==0) radian_out = 0;amplitude_out = 0; else % 先做象限判斷,得到相位補償值if (x > 0)phase_shift = 0;elseif (y < 0)phase_shift = -pi;elsephase_shift = pi;endfor k = 0 : N-1 % 迭代開始x_temp = x;if (y < 0) % d(k)=1,逆時針旋轉x = x_temp - y*2^(-k);y = y + x_temp*2^(-k);angle_accumulate = angle_accumulate - angle_LUT(k+1);else % d(k)=-1,順時針旋轉x = x_temp + y*2^(-k);y = y - x_temp*2^(-k);angle_accumulate = angle_accumulate + angle_LUT(k+1);end radian_out = angle_accumulate + phase_shift; %弧度輸出endamplitude_out = x*K; %幅值輸出 endangle_out = radian_out*180/pi; %相角輸出</span>1.2 Verilog代碼
采用16級流水的Verilog (未考慮象限問題)
//********************************************************* //功能1:已知角度θ,求正弦sinθ和余弦cosθ//思想:若向量模值為1,則其x坐標就是余弦值,y坐標就是正弦值。 //利用這一點,從(K,0)處迭代旋轉至θ處的單位矢量即可。 //*********************************************************module cordic_A( input clk, input rst_n, input [8:0] angle, input start,output reg signed[31:0] Sin, output reg signed[31:0] Cos, output finished);parameter angle_0 = 32'd2949120; //45度*2^16 parameter angle_1 = 32'd1740992; //26.5651度*2^16 parameter angle_2 = 32'd919872; //14.0362度*2^16 parameter angle_3 = 32'd466944; //7.1250度*2^16 parameter angle_4 = 32'd234368; //3.5763度*2^16 parameter angle_5 = 32'd117312; //1.7899度*2^16 parameter angle_6 = 32'd58688; //0.8952度*2^16 parameter angle_7 = 32'd29312; //0.4476度*2^16 parameter angle_8 = 32'd14656; //0.2238度*2^16 parameter angle_9 = 32'd7360; //0.1119度*2^16 parameter angle_10 = 32'd3648; //0.0560度*2^16 parameter angle_11 = 32'd1856; //0.0280度*2^16 parameter angle_12 = 32'd896; //0.0140度*2^16 parameter angle_13 = 32'd448; //0.0070度*2^16 parameter angle_14 = 32'd256; //0.0035度*2^16 parameter angle_15 = 32'd128; //0.0018度*2^16parameter pipeline = 16; parameter K = 32'h09b74; //0.607253*2^16,// reg signed [31:0] Sin; // reg signed [31:0] Cos;reg signed [31:0] x0 =0,y0 =0,z0 =0; reg signed [31:0] x1 =0,y1 =0,z1 =0; reg signed [31:0] x2 =0,y2 =0,z2 =0; reg signed [31:0] x3 =0,y3 =0,z3 =0; reg signed [31:0] x4 =0,y4 =0,z4 =0; reg signed [31:0] x5 =0,y5 =0,z5 =0; reg signed [31:0] x6 =0,y6 =0,z6 =0; reg signed [31:0] x7 =0,y7 =0,z7 =0; reg signed [31:0] x8 =0,y8 =0,z8 =0; reg signed [31:0] x9 =0,y9 =0,z9 =0; reg signed [31:0] x10=0,y10=0,z10=0; reg signed [31:0] x11=0,y11=0,z11=0; reg signed [31:0] x12=0,y12=0,z12=0; reg signed [31:0] x13=0,y13=0,z13=0; reg signed [31:0] x14=0,y14=0,z14=0; reg signed [31:0] x15=0,y15=0,z15=0; reg signed [31:0] x16=0,y16=0,z16=0;reg [4:0] count;always@(posedge clk or negedge rst_n)beginif(!rst_n)count <= 'b0;else if(start)beginif(count != 5'd18)count <= count + 1'b1;else count <= count;end endassign finished = (count == 5'd18)?1'b1:1'b0;always@(posedge clk or negedge rst_n)beginif(!rst_n)beginx0 <= 'b0;y0 <= 'b0;z0 <= 'b0;endelse beginx0 <= K;y0 <= 32'd0;z0 <= angle << 16;end end always@(posedge clk or negedge rst_n)begin//第一次迭代if(!rst_n)beginx1 <= 'b0;y1 <= 'b0;z1 <= 'b0;endelse if(z0[31]) beginx1 <= x0 + y0;y1 <= y0 - x0;z1 <= z0 + angle_0;endelse beginx1 <= x0 - y0;y1 <= y0 + x0;z1 <= z0 - angle_0; end end always@(posedge clk or negedge rst_n)begin//第二次迭代if(!rst_n)beginx2 <= 'b0;y2 <= 'b0;z2 <= 'b0;endelse if(z1[31]) beginx2 <= x1 + (y1>>>1);y2 <= y1 - (x1>>>1);z2 <= z1 + angle_1;endelse beginx2 <= x1 - (y1>>>1);y2 <= y1 + (x1>>>1);z2 <= z1 - angle_1; end end always@(posedge clk or negedge rst_n)begin//第3次迭代if(!rst_n)beginx3 <= 'b0;y3 <= 'b0;z3 <= 'b0;endelse if(z2[31]) beginx3 <= x2 + (y2>>>2);y3 <= y2 - (x2>>>2);z3 <= z2 + angle_2;endelse beginx3 <= x2 - (y2>>>2);y3 <= y2 + (x2>>>2);z3 <= z2 - angle_2; end end always@(posedge clk or negedge rst_n)begin//第4次迭代if(!rst_n)beginx4 <= 'b0;y4 <= 'b0;z4 <= 'b0;endelse if(z3[31]) beginx4 <= x3 + (y3>>>3);y4 <= y3 - (x3>>>3);z4 <= z3 + angle_3;endelse beginx4 <= x3 - (y3>>>3);y4 <= y3 + (x3>>>3);z4 <= z3 - angle_3; end end always@(posedge clk or negedge rst_n)begin//第5次迭代if(!rst_n)beginx5 <= 'b0;y5 <= 'b0;z5 <= 'b0;endelse if(z4[31]) beginx5 <= x4 + (y4>>>4);y5 <= y4 - (x4>>>4);z5 <= z4 + angle_4;endelse beginx5 <= x4 - (y4>>>4);y5 <= y4 + (x4>>>4);z5 <= z4 - angle_4; end end always@(posedge clk or negedge rst_n)begin//第6次迭代if(!rst_n)beginx6 <= 'b0;y6 <= 'b0;z6 <= 'b0;endelse if(z5[31]) beginx6 <= x5 + (y5>>>5);y6 <= y5 - (x5>>>5);z6 <= z5 + angle_5;endelse beginx6 <= x5 - (y5>>>5);y6 <= y5 + (x5>>>5);z6 <= z5 - angle_5; end end always@(posedge clk or negedge rst_n)begin//第7次迭代if(!rst_n)beginx7 <= 'b0;y7 <= 'b0;z7 <= 'b0;endelse if(z6[31]) beginx7 <= x6 + (y6>>>6);y7 <= y6 - (x6>>>6);z7 <= z6 + angle_6;endelse beginx7 <= x6 - (y6>>>6);y7 <= y6 + (x6>>>6);z7 <= z6 - angle_6; end end always@(posedge clk or negedge rst_n)begin//第8次迭代if(!rst_n)beginx8 <= 'b0;y8 <= 'b0;z8 <= 'b0;endelse if(z7[31]) beginx8 <= x7 + (y7>>>7);y8 <= y7 - (x7>>>7);z8 <= z7 + angle_7;endelse beginx8 <= x7 - (y7>>>7);y8 <= y7 + (x7>>>7);z8 <= z7 - angle_7; end end always@(posedge clk or negedge rst_n)begin//第9次迭代if(!rst_n)beginx9 <= 'b0;y9 <= 'b0;z9 <= 'b0;endelse if(z8[31]) beginx9 <= x8 + (y8>>>8);y9 <= y8 - (x8>>>8);z9 <= z8 + angle_8;endelse beginx9 <= x8 - (y8>>>8);y9 <= y8 + (x8>>>8);z9 <= z8 - angle_8; end end always@(posedge clk or negedge rst_n)begin//第10次迭代if(!rst_n)beginx10 <= 'b0;y10 <= 'b0;z10 <= 'b0;endelse if(z9[31]) beginx10 <= x9 + (y9>>>9);y10 <= y9 - (x9>>>9);z10 <= z9 + angle_9;endelse beginx10 <= x9 - (y9>>>9);y10 <= y9 + (x9>>>9);z10 <= z9 - angle_9; end end always@(posedge clk or negedge rst_n)begin//第11次迭代if(!rst_n)beginx11 <= 'b0;y11 <= 'b0;z11 <= 'b0;endelse if(z10[31]) beginx11 <= x10 + (y10>>>10);y11 <= y10 - (x10>>>10);z11 <= z10 + angle_10;endelse beginx11 <= x10 - (y10>>>10);y11 <= y10 + (x10>>>10);z11 <= z10 - angle_10; end end always@(posedge clk or negedge rst_n)begin//第12次迭代if(!rst_n)beginx12 <= 'b0;y12 <= 'b0;z12 <= 'b0;endelse if(z11[31]) beginx12 <= x11 + (y11>>>11);y12 <= y11 - (x11>>>11);z12 <= z11 + angle_11;endelse beginx12 <= x11 - (y11>>>11);y12 <= y11 + (x11>>>11);z12 <= z11 - angle_11; end end always@(posedge clk or negedge rst_n)begin//第13次迭代if(!rst_n)beginx13 <= 'b0;y13 <= 'b0;z13 <= 'b0;endelse if(z12[31]) beginx13 <= x12 + (y12>>>12);y13 <= y12 - (x12>>>12);z13 <= z12 + angle_12;endelse beginx13 <= x12 - (y12>>>12);y13 <= y12 + (x12>>>12);z13 <= z12 - angle_12; end end always@(posedge clk or negedge rst_n)begin//第14次迭代if(!rst_n)beginx14 <= 'b0;y14 <= 'b0;z14 <= 'b0;endelse if(z13[31]) beginx14 <= x13 + (y13>>>13);y14 <= y13 - (x13>>>13);z14 <= z13 + angle_13;endelse beginx14 <= x13 - (y13>>>13);y14 <= y13 + (x13>>>13);z14 <= z13 - angle_13; end end always@(posedge clk or negedge rst_n)begin//第15次迭代if(!rst_n)beginx15 <= 'b0;y15 <= 'b0;z15 <= 'b0;endelse if(z14[31]) beginx15 <= x14 + (y14>>>14);y15 <= y14 - (x14>>>14);z15 <= z14 + angle_14;endelse beginx15 <= x14 - (y14>>>14);y15 <= y14 + (x14>>>14);z15 <= z14 - angle_14; end end always@(posedge clk or negedge rst_n)begin//第16次迭代if(!rst_n)beginx16 <= 'b0;y16 <= 'b0;z16 <= 'b0;endelse if(z15[31]) beginx16 <= x15 + (y15>>>15);y16 <= y15 - (x15>>>15);z16 <= z15 + angle_15;endelse beginx16 <= x15 - (y15>>>15);y16 <= y15 + (x15>>>15);z16 <= z15 - angle_15; end end always@(posedge clk or negedge rst_n)beginif(!rst_n)beginCos <= 'b0;Sin <= 'b0;endelse beginSin = y16;Cos = x16;end end endmodule1.3 testbench A
輸入連續5個時鐘上升沿輸入60°,30°,45°,90°,30°,看是否能夠連續輸出相應結果。
`timescale 1ns/1psmodule cordic_Atb();parameter PERIOD = 10; reg clk; reg rst_n; reg [8:0]angle; reg start;wire [31:0] Sin; wire [31:0] Cos; wire finished;initial beginclk = 0;rst_n = 0;start = 0;angle = 'b0;#100 rst_n =1;#10 @(posedge clk) start = 1'b1;angle = 9'd60;#10 @(posedge clk) angle = 9'd30;#10 @(posedge clk) angle = 9'd45;#10 @(posedge clk) angle = 9'd90;#10 @(posedge clk) angle = 9'd30;#100000 $stop; endalways #(PERIOD/2) clk = ~clk;cordic_A inst1(.clk(clk),.rst_n(rst_n),.angle(angle),.start(start),.Sin(Sin),.Cos(Cos),.finished(finished));endmodule由于硬件實現將數據整體左移16位,從而換區更高精度,因此得到的結果需要向右移16位,進行還原。還原后我們發現跟預期的值相等。
2.已知角度θ,求正弦sinθ和余弦cosθ
思想:若向量模值為1,則其x坐標就是余弦值,y坐標就是正弦值。利用這一點,從(K,0)處迭代旋轉至θ處的單位矢量即可。
迭代方程及K的計算同第一小節。同時也要注意預先對象限的判斷和補償。
2.1 MATLAB代碼
%% *********************************************************************************** % 已知相角theta,計算其正弦和余弦值。基本公式如下: % x(k+1) = x(k) - d(k)*y(k)*2^(-k) % y(k+1) = y(k) + d(k)*x(k)*2^(-k) % z(k) = z(k) - d(k)*actan(2^(-k)) %% *********************************************************************************** clear;close all;clc;% 初始化---------------------------------------- N = 16; %迭代次數 tan_table = 2.^-(0 : N-1); angle_LUT = atan(tan_table);K = 1; for k = 0 : N-1K = K*(1/sqrt(1 + 2^(-2*k))); endtheta = -90; x = 1; y = 0; phase_accumulate = theta/180*pi; %轉化為弧度% cordic算法計算------------------------------- if (phase_accumulate > pi/2) % 先做象限判斷,得到相位補償值phase_accumulate = phase_accumulate - pi;sign_x = -1;sign_y = -1; elseif (phase_accumulate < -pi/2)phase_accumulate = phase_accumulate + pi;sign_x = -1;sign_y = -1; elsesign_x = 1;sign_y = 1; endfor k = 0 : N-1 % 迭代開始x_temp = x;if (phase_accumulate > 0) % d(k)=1,逆時針旋轉x = x_temp - y*2^(-k);y = y + x_temp*2^(-k);phase_accumulate = phase_accumulate - angle_LUT(k+1);else % d(k)=-1,順時針旋轉x = x_temp + y*2^(-k);y = y - x_temp*2^(-k);phase_accumulate = phase_accumulate + angle_LUT(k+1);end endcos_out = sign_x*x*K; %余弦輸出 sin_out = sign_y*y*K; %正弦輸出</span>2.2 Verilog代碼
16級流水的Verilog代碼如下:
//********************************************************* //已知坐標(x,y),求其向量對應的相角θ(反正切)和模值//思想:把原向量逐次向X正軸進行偽旋轉逼近. //整個過程的累計旋轉角度即為θ, //而旋轉后的x坐標補償模值增益K后即為原向量模值。 //*********************************************************module cordic_B( input clk, input rst_n, input signed [31:0] x, input signed [31:0] y, input start, output reg signed[31:0] angle, output reg signed[31:0] mozhi, output finished );parameter angle_0 = 32'd2949120; //45度*2^16 parameter angle_1 = 32'd1740992; //26.5651度*2^16 parameter angle_2 = 32'd919872; //14.0362度*2^16 parameter angle_3 = 32'd466944; //7.1250度*2^16 parameter angle_4 = 32'd234368; //3.5763度*2^16 parameter angle_5 = 32'd117312; //1.7899度*2^16 parameter angle_6 = 32'd58688; //0.8952度*2^16 parameter angle_7 = 32'd29312; //0.4476度*2^16 parameter angle_8 = 32'd14656; //0.2238度*2^16 parameter angle_9 = 32'd7360; //0.1119度*2^16 parameter angle_10 = 32'd3648; //0.0560度*2^16 parameter angle_11 = 32'd1856; //0.0280度*2^16 parameter angle_12 = 32'd896; //0.0140度*2^16 parameter angle_13 = 32'd448; //0.0070度*2^16 parameter angle_14 = 32'd256; //0.0035度*2^16 parameter angle_15 = 32'd128; //0.0018度*2^16parameter pipeline = 16; parameter K = 32'h09b74; //0.607253*2^16,// reg signed [31:0] Sin; // reg signed [31:0] Cos;reg signed [31:0] x0 =0,y0 =0,z0 =0; reg signed [31:0] x1 =0,y1 =0,z1 =0; reg signed [31:0] x2 =0,y2 =0,z2 =0; reg signed [31:0] x3 =0,y3 =0,z3 =0; reg signed [31:0] x4 =0,y4 =0,z4 =0; reg signed [31:0] x5 =0,y5 =0,z5 =0; reg signed [31:0] x6 =0,y6 =0,z6 =0; reg signed [31:0] x7 =0,y7 =0,z7 =0; reg signed [31:0] x8 =0,y8 =0,z8 =0; reg signed [31:0] x9 =0,y9 =0,z9 =0; reg signed [31:0] x10=0,y10=0,z10=0; reg signed [31:0] x11=0,y11=0,z11=0; reg signed [31:0] x12=0,y12=0,z12=0; reg signed [31:0] x13=0,y13=0,z13=0; reg signed [31:0] x14=0,y14=0,z14=0; reg signed [31:0] x15=0,y15=0,z15=0; reg signed [31:0] x16=0,y16=0,z16=0;reg [4:0] count;always@(posedge clk or negedge rst_n)beginif(!rst_n)count <= 'b0;else if(start)beginif(count != 5'd18)count <= count + 1'b1;else count <= count;end endassign finished = (count == 5'd18)?1'b1:1'b0;always@(posedge clk or negedge rst_n)beginif(!rst_n)beginx0 <= 'b0;y0 <= 'b0;z0 <= 'b0;endelse beginx0 <= x<<<16;y0 <= y<<<16;z0 <= 'b0;end end always@(posedge clk or negedge rst_n)begin//第一次迭代if(!rst_n)beginx1 <= 'b0;y1 <= 'b0;z1 <= 'b0;endelse if(!y0[31]) begin //和A不同的是,每次判斷y坐標的正負,從而決定是順時針還是逆時針旋轉。x1 <= x0 + y0;y1 <= y0 - x0;z1 <= z0 + angle_0;endelse beginx1 <= x0 - y0;y1 <= y0 + x0;z1 <= z0 - angle_0; end end always@(posedge clk or negedge rst_n)begin//第二次迭代if(!rst_n)beginx2 <= 'b0;y2 <= 'b0;z2 <= 'b0;endelse if(!y1[31]) beginx2 <= x1 + (y1>>>1);y2 <= y1 - (x1>>>1);z2 <= z1 + angle_1;endelse beginx2 <= x1 - (y1>>>1);y2 <= y1 + (x1>>>1);z2 <= z1 - angle_1; end end always@(posedge clk or negedge rst_n)begin//第3次迭代if(!rst_n)beginx3 <= 'b0;y3 <= 'b0;z3 <= 'b0;endelse if(!y2[31]) beginx3 <= x2 + (y2>>>2);y3 <= y2 - (x2>>>2);z3 <= z2 + angle_2;endelse beginx3 <= x2 - (y2>>>2);y3 <= y2 + (x2>>>2);z3 <= z2 - angle_2; end end always@(posedge clk or negedge rst_n)begin//第4次迭代if(!rst_n)beginx4 <= 'b0;y4 <= 'b0;z4 <= 'b0;endelse if(!y3[31]) beginx4 <= x3 + (y3>>>3);y4 <= y3 - (x3>>>3);z4 <= z3 + angle_3;endelse beginx4 <= x3 - (y3>>>3);y4 <= y3 + (x3>>>3);z4 <= z3 - angle_3; end end always@(posedge clk or negedge rst_n)begin//第5次迭代if(!rst_n)beginx5 <= 'b0;y5 <= 'b0;z5 <= 'b0;endelse if(!y4[31]) beginx5 <= x4 + (y4>>>4);y5 <= y4 - (x4>>>4);z5 <= z4 + angle_4;endelse beginx5 <= x4 - (y4>>>4);y5 <= y4 + (x4>>>4);z5 <= z4 - angle_4; end end always@(posedge clk or negedge rst_n)begin//第6次迭代if(!rst_n)beginx6 <= 'b0;y6 <= 'b0;z6 <= 'b0;endelse if(!y5[31]) beginx6 <= x5 + (y5>>>5);y6 <= y5 - (x5>>>5);z6 <= z5 + angle_5;endelse beginx6 <= x5 - (y5>>>5);y6 <= y5 + (x5>>>5);z6 <= z5 - angle_5; end end always@(posedge clk or negedge rst_n)begin//第7次迭代if(!rst_n)beginx7 <= 'b0;y7 <= 'b0;z7 <= 'b0;endelse if(!y6[31]) beginx7 <= x6 + (y6>>>6);y7 <= y6 - (x6>>>6);z7 <= z6 + angle_6;endelse beginx7 <= x6 - (y6>>>6);y7 <= y6 + (x6>>>6);z7 <= z6 - angle_6; end end always@(posedge clk or negedge rst_n)begin//第8次迭代if(!rst_n)beginx8 <= 'b0;y8 <= 'b0;z8 <= 'b0;endelse if(!y7[31]) beginx8 <= x7 + (y7>>>7);y8 <= y7 - (x7>>>7);z8 <= z7 + angle_7;endelse beginx8 <= x7 - (y7>>>7);y8 <= y7 + (x7>>>7);z8 <= z7 - angle_7; end end always@(posedge clk or negedge rst_n)begin//第9次迭代if(!rst_n)beginx9 <= 'b0;y9 <= 'b0;z9 <= 'b0;endelse if(!y8[31]) beginx9 <= x8 + (y8>>>8);y9 <= y8 - (x8>>>8);z9 <= z8 + angle_8;endelse beginx9 <= x8 - (y8>>>8);y9 <= y8 + (x8>>>8);z9 <= z8 - angle_8; end end always@(posedge clk or negedge rst_n)begin//第10次迭代if(!rst_n)beginx10 <= 'b0;y10 <= 'b0;z10 <= 'b0;endelse if(!y9[31]) beginx10 <= x9 + (y9>>>9);y10 <= y9 - (x9>>>9);z10 <= z9 + angle_9;endelse beginx10 <= x9 - (y9>>>9);y10 <= y9 + (x9>>>9);z10 <= z9 - angle_9; end end always@(posedge clk or negedge rst_n)begin//第11次迭代if(!rst_n)beginx11 <= 'b0;y11 <= 'b0;z11 <= 'b0;endelse if(!y10[31]) beginx11 <= x10 + (y10>>>10);y11 <= y10 - (x10>>>10);z11 <= z10 + angle_10;endelse beginx11 <= x10 - (y10>>>10);y11 <= y10 + (x10>>>10);z11 <= z10 - angle_10; end end always@(posedge clk or negedge rst_n)begin//第12次迭代if(!rst_n)beginx12 <= 'b0;y12 <= 'b0;z12 <= 'b0;endelse if(!y11[31]) beginx12 <= x11 + (y11>>>11);y12 <= y11 - (x11>>>11);z12 <= z11 + angle_11;endelse beginx12 <= x11 - (y11>>>11);y12 <= y11 + (x11>>>11);z12 <= z11 - angle_11; end end always@(posedge clk or negedge rst_n)begin//第13次迭代if(!rst_n)beginx13 <= 'b0;y13 <= 'b0;z13 <= 'b0;endelse if(!y12[31]) beginx13 <= x12 + (y12>>>12);y13 <= y12 - (x12>>>12);z13 <= z12 + angle_12;endelse beginx13 <= x12 - (y12>>>12);y13 <= y12 + (x12>>>12);z13 <= z12 - angle_12; end end always@(posedge clk or negedge rst_n)begin//第14次迭代if(!rst_n)beginx14 <= 'b0;y14 <= 'b0;z14 <= 'b0;endelse if(!y13[31]) beginx14 <= x13 + (y13>>>13);y14 <= y13 - (x13>>>13);z14 <= z13 + angle_13;endelse beginx14 <= x13 - (y13>>>13);y14 <= y13 + (x13>>>13);z14 <= z13 - angle_13; end end always@(posedge clk or negedge rst_n)begin//第15次迭代if(!rst_n)beginx15 <= 'b0;y15 <= 'b0;z15 <= 'b0;endelse if(!y14[31]) beginx15 <= x14 + (y14>>>14);y15 <= y14 - (x14>>>14);z15 <= z14 + angle_14;endelse beginx15 <= x14 - (y14>>>14);y15 <= y14 + (x14>>>14);z15 <= z14 - angle_14; end end always@(posedge clk or negedge rst_n)begin//第16次迭代if(!rst_n)beginx16 <= 'b0;y16 <= 'b0;z16 <= 'b0;endelse if(!y15[31]) beginx16 <= x15 + (y15>>>15);y16 <= y15 - (x15>>>15);z16 <= z15 + angle_15;endelse beginx16 <= x15 - (y15>>>15);y16 <= y15 + (x15>>>15);z16 <= z15 - angle_15; end end wire[31:0] mozhi_tmp; wire[31:0] mozhi_tmp1; wire[31:0] mozhi_tmp2;assign mozhi_tmp = x16>>>6; assign mozhi_tmp1 = mozhi_tmp+mozhi_tmp+mozhi_tmp+mozhi_tmp+mozhi_tmp+mozhi_tmp+mozhi_tmp; assign mozhi_tmp2 = x16>>>1;always@(posedge clk or negedge rst_n)beginif(!rst_n)beginmozhi <= 'b0;angle <= 'b0;endelse beginmozhi = (mozhi_tmp1 + mozhi_tmp2)>>>16;angle = z16>>>16;end end endmodule2.3 Testbench B
Testbench代碼如下:
`timescale 1ns/1psmodule cordic_Btb();parameter PERIOD = 10; reg clk; reg rst_n; reg signed [31:0] x; reg signed [31:0] y; reg start; wire signed [31:0] angle; wire signed [31:0] mozhi; wire finished; initial beginclk = 0;rst_n = 0;x = 'b0;y = 'b0;start = 0;#100 rst_n = 1;#10 @(posedge clk) start = 1; x = 9'd100 ; y = 9'd100 ;#10 @(posedge clk) x = 9'd10; y = 9'd10;#10 @(posedge clk) x = 9'd3 ; y = 9'd4 ;#10 @(posedge clk) x = 9'd6 ; y = 9'd8 ;#100000 $stop; endalways #(PERIOD/2) clk = ~clk;cordic_B inst1(.clk(clk),.rst_n(rst_n),.x(x),.y(y),.start(start),.angle(angle),.mozhi(mozhi),.finished(finished)); endmodule相應仿真波形如下圖所示:
可以看到,輸入的(x,y)為(100,100)時,其夾角θ \thetaθ=45°,模值近似為141。其他情況同理。
總結
以上是生活随笔為你收集整理的CORDIC算法原理详解及其Verilog实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 启动hdfs报错:hadoop100 P
- 下一篇: ssh localhost失败:Perm