X

FPGA SDR(19)自作ATAN2

2018/07/29 追記:360°を8等分して45°~90°に変換してから計算するようにすると音質が改善しました。
2018/07/22 追記:ATAN2の出力を16ビットまでパラメータで指定できるようにしました。

 

Cyclone II EP2C5T144で使えるQuartus II Web Edition 13.0sp1のMegaWizardにALTERA CORDICが見つかりません。EP2C5T144でもFMラジオを作りたいのでCORDICを勉強してATAN2を作ってみました。加減算とビットシフトだけで済んでしまうんですね。ATAN2の出力を16ビットとして、計算に必要なテーブルはたった13行です。

360°を8等分して45°~90°に変換してから計算しています。

`timescale 1ns/1ns


module MyATAN2
#(
	parameter XY_WIDTH = 10,
	parameter Q_WIDTH = 10
)
(
	input  wire       areset,
	input  wire       clk,
	input  wire       en,
	input  wire signed [XY_WIDTH-1:0] x,
	input  wire signed [XY_WIDTH-1:0] y,
	output reg signed [Q_WIDTH-1:0] q
);


	localparam TABLE_WIDTH = 16;
	localparam TABLE_SIZE = 13;
	localparam DATA_WIDTH = 1 + XY_WIDTH + TABLE_SIZE;
	localparam PI = 16'sb011_0010_0100_0011_1; // pi = 0011 . 0010 0100 0011 1111 0110 1010
	
	reg [3:0] n; // 0 ~ TABLE_SIZE+1
	reg [2:0] quad; // 0 ~ 7
	wire signed [DATA_WIDTH-1:0] pi;
	wire signed [DATA_WIDTH-1:0] pidiv2;
	reg signed [DATA_WIDTH-1:0] xn;
	reg signed [DATA_WIDTH-1:0] yn;
	reg signed [TABLE_WIDTH-1:0] atan;
	reg signed [TABLE_WIDTH-1:0] atan_table [0:TABLE_SIZE-1];


	initial begin
		atan_table[0]  = 16'sb000_1100_1001_0000_1; // atan(1/1):    000 . 1100 1001 0000 1111 1101 1010
		atan_table[1]  = 16'sb000_0111_0110_1011_0; // atan(1/2):    000 . 0111 0110 1011 0001 1001 1100
		atan_table[2]  = 16'sb000_0011_1110_1011_0; // atan(1/4):    000 . 0011 1110 1011 0110 1110 1011
		atan_table[3]  = 16'sb000_0001_1111_1101_0; // atan(1/8):    000 . 0001 1111 1101 0101 1011 1010
		atan_table[4]  = 16'sb000_0000_1111_1111_1; // atan(1/16):   000 . 0000 1111 1111 1010 1010 1101
		atan_table[5]  = 16'sb000_0000_0111_1111_1; // atan(1/32):   000 . 0000 0111 1111 1111 0101 0101
		atan_table[6]  = 16'sb000_0000_0011_1111_1; // atan(1/64):   000 . 0000 0011 1111 1111 1110 1010
		atan_table[7]  = 16'sb000_0000_0001_1111_1; // atan(1/128):  000 . 0000 0001 1111 1111 1111 1101
		atan_table[8]  = 16'sb000_0000_0000_1111_1; // atan(1/256):  000 . 0000 0000 1111 1111 1111 1111
		atan_table[9]  = 16'sb000_0000_0000_0111_1; // atan(1/512):  000 . 0000 0000 0111 1111 1111 1111
		atan_table[10] = 16'sb000_0000_0000_0011_1; // atan(1/1024): 000 . 0000 0000 0011 1111 1111 1111
		atan_table[11] = 16'sb000_0000_0000_0001_1; // atan(1/2048): 000 . 0000 0000 0001 1111 1111 1111
		atan_table[12] = 16'sb000_0000_0000_0000_1; // atan(1/4096): 000 . 0000 0000 0000 1111 1111 1111
	end
	
	
	assign pi = PI >>> (TABLE_WIDTH - Q_WIDTH);
	assign pidiv2 = pi >>> 1;

	always @(posedge clk)
	begin
		if (areset) begin
				n = y) begin
						quad = -y) begin
						quad  y
				else if (quad == 1) q  y
				else if (quad == 4) q  y
				else if (quad == 5) q  y
			end
			else begin
				if (n >> (n-1));
						yn >> (n-1));
						atan >> (TABLE_WIDTH - Q_WIDTH));
					end
					else begin
						xn >> (n-1));
						yn >> (n-1));
						atan >> (TABLE_WIDTH - Q_WIDTH));
					end
				end
			end
		end
	end


endmodule

 

snoopy: