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