2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

趣味で非パイプラインのCORDICの実装

Posted at

個人的にCORDICによる三角関数の実装に興味があったので実装しました。
次の記事 https://qiita.com/cyebu1103/items/2d51212f27788f8b3c8f がとても親切に解説してくれています。

演算子を極力使わないように実装を試みました。非パイプラインです。
数値はQ29表記の32ビット符号付き固定小数点、入力レンジは[-6.28,6.28]です。
Xilinx LogiCoreIPの三角関数IPの入力範囲は確か[-3.28,3.28]。
ALTERA Megafunctionのalt_sincosのように入力制限がないものを作りたい。

上手なバレルシフタの記述方法を検討中。

COREDIC_sincos.vhd

module CORDIC_sincos(input wire clk, input wire st, input wire [31:0] theta, output wire [31:0] sin, output wire [31:0] cos);

//Format: S2Q29, 32 bit fixed point.

reg on;		initial on=1'b0;
reg [4:0] cnt;
always@(clk) on <= (on==1'b0)? ((st==1'b1)? 1'b1:1'b0) : ((cnt==5'd24)? 1'b0:1'b1);

localparam signed [31:0] PI			= 32'h6487ed51; //3.141593e+00 (Tranceted error: 1.215419e-10)
localparam signed [31:0] PI_2		= 32'h3243f6a8; //1.570796e+00 (Tranceted error: 9.920935e-10)
localparam signed [31:0] inv_PI		= 32'h0a2f9836; //3.183099e-01 (Tranceted error: 1.665406e-09)
localparam signed [31:0] inv_2PI	= 32'h0517cc1b; //1.591549e-01 (Tranceted error: 8.327029e-10)
localparam signed [31:0] inv_sqrt2	= 32'h16a09e66; //7.071068e-01 (Tranceted error: 9.257461e-10)
localparam signed [31:0] PI_4		= 32'h1921fb54; //7.853982e-01 (Tranceted error: 4.960468e-10)
localparam signed [31:0] PI3_4		= 32'h4b65f1fc; //2.356194e+00 (Tranceted error: 1.488140e-09)
localparam signed [31:0] inv_k		= 32'h136e9db5; //6.072529e-01 (Tranceted error: 6.127276e-11)

localparam signed [31:0] atan_no0_P	 = 32'h1921fb54; //7.853982e-01 (Tranceted error: 4.960468e-10)
localparam signed [31:0] atan_no1_P	 = 32'h0ed63382; //4.636476e-01 (Tranceted error: 1.286868e-09)
localparam signed [31:0] atan_no2_P	 = 32'h07d6dd7e; //2.449787e-01 (Tranceted error: 5.466124e-10)
localparam signed [31:0] atan_no3_P	 = 32'h03fab753; //1.243550e-01 (Tranceted error: 6.222629e-10)
localparam signed [31:0] atan_no4_P	 = 32'h01ff55bb; //6.241881e-02 (Tranceted error: 8.353672e-10)
localparam signed [31:0] atan_no5_P	 = 32'h00ffeaad; //3.123983e-02 (Tranceted error: 1.610138e-09)
localparam signed [31:0] atan_no6_P	 = 32'h007ffd55; //1.562373e-02 (Tranceted error: 8.071138e-10)
localparam signed [31:0] atan_no7_P	 = 32'h003fffaa; //7.812341e-03 (Tranceted error: 1.247584e-09)
localparam signed [31:0] atan_no8_P	 = 32'h001ffff5; //3.906230e-03 (Tranceted error: 6.210636e-10)
localparam signed [31:0] atan_no9_P	 = 32'h000ffffe; //1.953123e-03 (Tranceted error: 1.241769e-09)
localparam signed [31:0] atan_no10_P = 32'h0007ffff; //9.765622e-04 (Tranceted error: 1.552204e-09)
localparam signed [31:0] atan_no11_P = 32'h0003ffff; //4.882812e-04 (Tranceted error: 1.823840e-09)
localparam signed [31:0] atan_no12_P = 32'h0001ffff; //2.441406e-04 (Tranceted error: 1.857795e-09)
localparam signed [31:0] atan_no13_P = 32'h0000ffff; //1.220703e-04 (Tranceted error: 1.862039e-09)
localparam signed [31:0] atan_no14_P = 32'h00007fff; //6.103516e-05 (Tranceted error: 1.862569e-09)
localparam signed [31:0] atan_no15_P = 32'h00003fff; //3.051758e-05 (Tranceted error: 1.862636e-09)
localparam signed [31:0] atan_no16_P = 32'h00001fff; //1.525879e-05 (Tranceted error: 1.862644e-09)
localparam signed [31:0] atan_no17_P = 32'h00000fff; //7.629395e-06 (Tranceted error: 1.862645e-09)
localparam signed [31:0] atan_no18_P = 32'h000007ff; //3.814697e-06 (Tranceted error: 1.862645e-09)

localparam signed [31:0] atan_no0_N	 = 32'he6de04ab; //-7.853982e-01 (Tranceted error: 1.366598e-09)
localparam signed [31:0] atan_no1_N	 = 32'hf129cc7d; //-4.636476e-01 (Tranceted error: 5.757768e-10)
localparam signed [31:0] atan_no2_N	 = 32'hf8292281; //-2.449787e-01 (Tranceted error: 1.316033e-09)
localparam signed [31:0] atan_no3_N	 = 32'hfc0548ac; //-1.243550e-01 (Tranceted error: 1.240382e-09)
localparam signed [31:0] atan_no4_N	 = 32'hfe00aa44; //-6.241881e-02 (Tranceted error: 1.027278e-09)
localparam signed [31:0] atan_no5_N	 = 32'hff001552; //-3.123983e-02 (Tranceted error: 2.525072e-10)
localparam signed [31:0] atan_no6_N	 = 32'hff8002aa; //-1.562373e-02 (Tranceted error: 1.055531e-09)
localparam signed [31:0] atan_no7_N	 = 32'hffc00055; //-7.812341e-03 (Tranceted error: 6.150612e-10)
localparam signed [31:0] atan_no8_N	 = 32'hffe0000a; //-3.906230e-03 (Tranceted error: 1.241582e-09)
localparam signed [31:0] atan_no9_N	 = 32'hfff00001; //-1.953123e-03 (Tranceted error: 6.208760e-10)
localparam signed [31:0] atan_no10_N = 32'hfff80000; //-9.765622e-04 (Tranceted error: 3.104407e-10)
localparam signed [31:0] atan_no11_N = 32'hfffc0000; //-4.882812e-04 (Tranceted error: 3.880510e-11)
localparam signed [31:0] atan_no12_N = 32'hfffe0000; //-2.441406e-04 (Tranceted error: 4.850638e-12)
localparam signed [31:0] atan_no13_N = 32'hffff0000; //-1.220703e-04 (Tranceted error: 6.063298e-13)
localparam signed [31:0] atan_no14_N = 32'hffff8000; //-6.103516e-05 (Tranceted error: 7.579123e-14)
localparam signed [31:0] atan_no15_N = 32'hffffc000; //-3.051758e-05 (Tranceted error: 9.473904e-15)
localparam signed [31:0] atan_no16_N = 32'hffffe000; //-1.525879e-05 (Tranceted error: 1.184238e-15)
localparam signed [31:0] atan_no17_N = 32'hfffff000; //-7.629395e-06 (Tranceted error: 1.480300e-16)
localparam signed [31:0] atan_no18_N = 32'hfffff800; //-3.814697e-06 (Tranceted error: 1.850386e-17)

reg sign;
reg zero;
reg reverse;
reg angle_zero;

reg signed [31:0] x;
reg signed [31:0] y;
reg signed [31:0] x_sh;
reg signed [31:0] y_sh;

reg quadrant;

reg [31:0] theta_sh;
reg [31:0] theta_sh_buf;
reg [31:0] angle_tb;

reg [31:0] sin_in;
reg [31:0] cos_in;

reg div;

assign sin=sin_in;
assign cos=cos_in;

always@(posedge clk)
begin

	div=(on==1'b1)? ~div:1'b0;

	if(div==1'b0)
	begin
		cnt <= (on==1'b1)? cnt+1'b1: 1'b0;

		if(cnt==5'd1) angle_zero <= (theta==1'b0)? 1'b1:1'b0;

		if(cnt==5'd1) theta_sh <= (theta[31]==1'b0)? theta-PI:theta+PI;	// Range convert [-2pi,2pi]->[-pi,pi]
		else theta_sh <= (theta_sh_buf!=1'b0)? theta_sh_buf+angle_tb:1'b0;

		if(cnt==5'd2) reverse <= (theta_sh[31]==1'b1)? 1'b1:1'b0; else reverse<=reverse;
		sign <= theta_sh[31];

		if(cnt==5'd6)
		begin
			x<=(angle_zero!=1'b1)? inv_k:32'h20000000;
			y<=(angle_zero!=1'b1)? inv_k:1'b0;
		end
		else
		begin
			x <= (zero!=1'b1)? ((sign==1'b0)? x-y_sh: x+y_sh):x;
			y <= (zero!=1'b1)? ((sign==1'b0)? y+x_sh: y-x_sh):y;
		end

		if(cnt==5'd23)
		begin
			case ({reverse,quadrant})
				2'b00: begin cos_in<=~x+1'b1; sin_in<=~y+1'b1; end
				2'b01: begin cos_in<=y; sin_in<=~x+1'b1; end
				2'b10: begin cos_in<=x; sin_in<=y; end
				2'b11: begin cos_in<=~y+1'b1; sin_in<=x; end
				default: begin cos_in<=1'b0; sin_in<=1'b0; end
			endcase
		end
		else
		begin
			cos_in<=cos_in;
			sin_in<=sin_in;
		end

	end
	else
	begin

		case(cnt)
			5'd2:	angle_tb <= (theta_sh[31]==1'b1)? PI:1'b0;	//Range convert [-pi,pi] to [0,pi];
			5'd4:	angle_tb <= (quadrant==1'b1)? -PI_2:1'b0;	//Range convert [0,pi] to [0,pi/2];
			5'd5:	angle_tb <= (theta_sh[31]==1'b0)? atan_no0_N:atan_no0_P;
			5'd6:	angle_tb <= (theta_sh[31]==1'b0)? atan_no1_N:atan_no1_P;
			5'd7:	angle_tb <= (theta_sh[31]==1'b0)? atan_no2_N:atan_no2_P;
			5'd8:	angle_tb <= (theta_sh[31]==1'b0)? atan_no3_N:atan_no3_P;
			5'd9:	angle_tb <= (theta_sh[31]==1'b0)? atan_no4_N:atan_no4_P;
			5'd10:	angle_tb <= (theta_sh[31]==1'b0)? atan_no5_N:atan_no5_P;
			5'd11:	angle_tb <= (theta_sh[31]==1'b0)? atan_no6_N:atan_no6_P;
			5'd12:	angle_tb <= (theta_sh[31]==1'b0)? atan_no7_N:atan_no7_P;
			5'd13:	angle_tb <= (theta_sh[31]==1'b0)? atan_no8_N:atan_no8_P;
			5'd14:	angle_tb <= (theta_sh[31]==1'b0)? atan_no9_N:atan_no9_P;
			5'd15:	angle_tb <= (theta_sh[31]==1'b0)? atan_no10_N:atan_no10_P;
			5'd16:	angle_tb <= (theta_sh[31]==1'b0)? atan_no11_N:atan_no11_P;
			5'd17:	angle_tb <= (theta_sh[31]==1'b0)? atan_no12_N:atan_no12_P;
			5'd18:	angle_tb <= (theta_sh[31]==1'b0)? atan_no13_N:atan_no13_P;
			5'd19:	angle_tb <= (theta_sh[31]==1'b0)? atan_no14_N:atan_no14_P;
			5'd20:	angle_tb <= (theta_sh[31]==1'b0)? atan_no15_N:atan_no15_P;
			5'd21:	angle_tb <= (theta_sh[31]==1'b0)? atan_no16_N:atan_no16_P;
			5'd22:	angle_tb <= (theta_sh[31]==1'b0)? atan_no17_N:atan_no17_P;
			5'd23:	angle_tb <= (theta_sh[31]==1'b0)? atan_no18_N:atan_no18_P;
			default:angle_tb <= 32'b0;
		endcase

		theta_sh_buf<=theta_sh;
		zero <= (theta_sh==1'b0)? 1'b1:1'b0;
		quadrant <= (cnt==5'd3)? ((theta_sh>PI_2)? 1'b1:1'b0):quadrant;

		if(x[31]==1'b1)
		begin
			x_sh<=1'b0;
		end
		else
		begin
			case(cnt)
				5'd7:		x_sh <= {1'b0,x[31:1]};
				5'd8:		x_sh <= {2'b0,x[31:2]};
				5'd9:		x_sh <= {3'b0,x[31:3]};
				5'd10:		x_sh <= {4'b0,x[31:4]};
				5'd11:		x_sh <= {5'b0,x[31:5]};
				5'd12:		x_sh <= {6'b0,x[31:6]};
				5'd13:		x_sh <= {7'b0,x[31:7]};
				5'd14:		x_sh <= {8'b0,x[31:8]};
				5'd15:		x_sh <= {9'b0,x[31:9]};
				5'd16:		x_sh <= {10'b0,x[31:10]};
				5'd17:		x_sh <= {11'b0,x[31:11]};
				5'd18:		x_sh <= {12'b0,x[31:12]};
				5'd19:		x_sh <= {13'b0,x[31:13]};
				5'd20:		x_sh <= {14'b0,x[31:14]};
				5'd21:		x_sh <= {15'b0,x[31:15]};
				5'd22:		x_sh <= {16'b0,x[31:16]};
				default:	x_sh <= 32'b0;
			endcase
		end

		if(y[31]==1'b1)
		begin
			y_sh<=1'b0;
		end
		else
		begin
			case(cnt)
				5'd7:		y_sh <= {1'b0,y[31:1]};
				5'd8:		y_sh <= {2'b0,y[31:2]};
				5'd9:		y_sh <= {3'b0,y[31:3]};
				5'd10:		y_sh <= {4'b0,y[31:4]};
				5'd11:		y_sh <= {5'b0,y[31:5]};
				5'd12:		y_sh <= {6'b0,y[31:6]};
				5'd13:		y_sh <= {7'b0,y[31:7]};
				5'd14:		y_sh <= {8'b0,y[31:8]};
				5'd15:		y_sh <= {9'b0,y[31:9]};
				5'd16:		y_sh <= {10'b0,y[31:10]};
				5'd17:		y_sh <= {11'b0,y[31:11]};
				5'd18:		y_sh <= {12'b0,y[31:12]};
				5'd19:		y_sh <= {13'b0,y[31:13]};
				5'd20:		y_sh <= {14'b0,y[31:14]};
				5'd21:		y_sh <= {15'b0,y[31:15]};
				5'd22:		y_sh <= {16'b0,y[31:16]};
				default:	y_sh <= 32'b0;
			endcase
		end

	end
end

endmodule


2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?