module Vec2Angle
(
clk,
nreset,
i_x,
i_y,
o_angle
);
parameter nd = 16; // number of data bits
parameter na = 14; // number of angle bits ( <= 32)
parameter nt = 34; // number of bits for arc tangent table ( <= 34, >= na + 1 )
parameter ni = 16; // number of iteration ( <= 32)
parameter np = nd + ni; // number of processing bits ( >= nd)
input clk;
input nreset;
input [nd-1:0] i_x, i_y;
output [na-1:0] o_angle;
wire signed [np:0] x[ni:0];
wire signed [np:0] y[ni:0];
wire [nt-1:0] z[ni:0];
wire d[ni:0];
reg signed [np:0] r_x[ni/2:0];
reg signed [np:0] r_y[ni/2:0];
reg [nt-1:0] r_z[ni/2:0];
reg r_d[ni/2:0];
reg s[ni/2:0];
// data formating and initialization
always @(posedge clk or negedge nreset)
begin : Initialization
if(~nreset) begin
s[0] <= 0;
r_x[0] <= 0;
r_y[0] <= 0;
r_z[0] <= 0;
r_d[0] <= 0;
end
else begin
s[0] <= i_x[nd-1];
r_x[0] <= i_x[nd-1] ? ( ~{{i_x[nd-1]}, i_x, {(np-nd){1'b0}}} + 1 ): { {i_x[nd-1]}, i_x, {(np-nd){1'b0}} };
r_y[0] <= i_x[nd-1] ? ( ~{{i_y[nd-1]}, i_y, {(np-nd){1'b0}}} + 1 ): { {i_y[nd-1]}, i_y, {(np-nd){1'b0}} };
r_z[0] <= 0;
r_d[0] <= i_x[nd-1] ? ~i_y[nd-1] : i_y[nd-1];
end
end
// CORDIC iteration
wire [33:0] atan2_[31:0];
genvar i;
generate for (i = 0; i < ni/2 ; i = i + 1)
begin : Iteration
if(i == 0) begin
assign x[i*2+1] = r_d[i] ? (r_x[i] - r_y[i][np:i*2]) : (r_x[i] + r_y[i][np:i*2]);
assign y[i*2+1] = r_d[i] ? (r_y[i] + r_x[i][np:i*2]) : (r_y[i] - r_x[i][np:i*2]);
assign z[i*2+1] = r_d[i] ? (r_z[i] - atan2_[i*2][33:33-nt+1] ) : (r_z[i] + atan2_[i*2][33:33-nt+1] );
assign d[i*2+1] = y[i*2+1][np];
assign x[i*2+2] = d[i*2+1] ? (x[i*2+1] - {{(i*2+1){y[i*2+1][np]}}, y[i*2+1][np:i*2+1]} ) : (x[i*2+1] + {{(i*2+1){y[i*2+1][np]}}, y[i*2+1][np:i*2+1]});
assign y[i*2+2] = d[i*2+1] ? (y[i*2+1] + {{(i*2+1){x[i*2+1][np]}}, x[i*2+1][np:i*2+1]} ) : (y[i*2+1] - {{(i*2+1){x[i*2+1][np]}}, x[i*2+1][np:i*2+1]});
assign z[i*2+2] = d[i*2+1] ? (z[i*2+1] - atan2_[i*2+1][33:33-nt+1] ) : (z[i*2+1] + atan2_[i*2+1][33:33-nt+1] );
assign d[i*2+2] = y[i*2+2][np];
end
else begin
assign x[i*2+1] = r_d[i] ? (r_x[i] - {{(i*2){r_y[i][np]}},r_y[i][np:i*2]}) : (r_x[i] + {{(i*2){r_y[i][np]}},r_y[i][np:i*2]});
assign y[i*2+1] = r_d[i] ? (r_y[i] + {{(i*2){r_x[i][np]}},r_x[i][np:i*2]}) : (r_y[i] - {{(i*2){r_x[i][np]}},r_x[i][np:i*2]});
assign z[i*2+1] = r_d[i] ? (r_z[i] - atan2_[i*2][33:33-nt+1] ) : (r_z[i] + atan2_[i*2][33:33-nt+1] );
assign d[i*2+1] = y[i*2+1][np];
assign x[i*2+2] = d[i*2+1] ? (x[i*2+1] - {{(i*2+1){y[i*2+1][np]}}, y[i*2+1][np:i*2+1]} ) : (x[i*2+1] + {{(i*2+1){y[i*2+1][np]}}, y[i*2+1][np:i*2+1]});
assign y[i*2+2] = d[i*2+1] ? (y[i*2+1] + {{(i*2+1){x[i*2+1][np]}}, x[i*2+1][np:i*2+1]} ) : (y[i*2+1] - {{(i*2+1){x[i*2+1][np]}}, x[i*2+1][np:i*2+1]});
assign z[i*2+2] = d[i*2+1] ? (z[i*2+1] - atan2_[i*2+1][33:33-nt+1] ) : (z[i*2+1] + atan2_[i*2+1][33:33-nt+1] );
assign d[i*2+2] = y[i*2+2][np];
end
always @(posedge clk or negedge nreset)
begin
if(~nreset) begin
r_x[i+1] <= 0;
r_y[i+1] <= 0;
r_z[i+1] <= 0;
r_d[i+1] <= 0;
s[i+1] <= 0;
end
else begin
r_x[i+1] <= x[i*2+2];
r_y[i+1] <= y[i*2+2];
r_z[i+1] <= z[i*2+2];
r_d[i+1] <= d[i*2+2];
s[i+1] <= s[i];
end
end
end
endgenerate
assign x[0] = 0;
assign y[0] = 0;
assign z[0] = 0;
assign d[0] = 0;
wire [na-1:0] z_t = r_z[ni/2][nt-1:nt-na];
wire s_d = s[ni/2];
wire [na-1:0] z_r; // round
generate
if(nt < na + 1) begin
assign z_r = z_t; // no round
end
else begin
assign z_r = z_t + {{(na-1){1'b0}},r_z[ni/2][nt-na-1]}; // round
end
endgenerate
reg [na-1:0] o_angle;
always @(posedge clk or negedge nreset)
begin
if(~nreset) begin
o_angle <= 0;
end
else begin
o_angle <= s_d ? (z_r + {1'b1,{(na-1){1'b0}}}): z_r;
end
end
assign atan2_[ 0] = 34'h080000000; // pi/4
assign atan2_[ 1] = 34'h04B901476;
assign atan2_[ 2] = 34'h027ECE16D;
assign atan2_[ 3] = 34'h014444750;
assign atan2_[ 4] = 34'h00A2C350C;
assign atan2_[ 5] = 34'h005175F85;
assign atan2_[ 6] = 34'h0028BD879;
assign atan2_[ 7] = 34'h00145F154;
assign atan2_[ 8] = 34'h000A2F94D;
assign atan2_[ 9] = 34'h000517CBB;
assign atan2_[10] = 34'h00028BE60;
assign atan2_[11] = 34'h000145F30;
assign atan2_[12] = 34'h0000A2F98;
assign atan2_[13] = 34'h0000517CC;
assign atan2_[14] = 34'h000028BE6;
assign atan2_[15] = 34'h0000145F3;
assign atan2_[16] = 34'h00000A2FA;
assign atan2_[17] = 34'h00000517D;
assign atan2_[18] = 34'h0000028BE;
assign atan2_[19] = 34'h00000145F;
assign atan2_[20] = 34'h000000A30;
assign atan2_[21] = 34'h000000518;
assign atan2_[22] = 34'h00000028C;
assign atan2_[23] = 34'h000000146;
assign atan2_[24] = 34'h0000000A3;
assign atan2_[25] = 34'h000000051;
assign atan2_[26] = 34'h000000029;
assign atan2_[27] = 34'h000000014;
assign atan2_[28] = 34'h00000000A;
assign atan2_[29] = 34'h000000005;
assign atan2_[30] = 34'h000000003;
assign atan2_[31] = 34'h000000001;
endmodule // AtanTbl