//
//		r2p5.v - Convert 5x5 bit Rectangular Input to 5x5 bit Polar Output
//
//						(C) Copyright 2009 John B. Stephensen
//
// This Verilog source file and all its derivatives are licensed only for
// personal non-profit educational use in the Amateur Radio Service and
// the license is not transferrable. The information is provided as-is for
// experimental purposes and the author does not warranty its freedom
// from defects or its suitability for any specific application.
//
// The module first rotates the X and Y coordinates into the first quadrant and then looks
// up the arctangent and the magnitude in ROM. This module truncates inputs so the values
// stored in the arctangent ROM assume a positive bias of 1/2 bit. The LSBs are dropped for
// magnitude calculation so that ROM has a postivie bias of 1 bit. The rotation converts
// the ranges -2 =< x < 0 (1111x) and 0 =< to < +2 (0000x) to 000. This logic assumes that
// the actual X and Y axis input values are truncated to 5 bits rather than rounded.
//
// 42 slices are used with a 174 MHz maximum clock rate and there is a 2 clock period delay. 
// 
module r2p5(
    input [4:0] x,		// rectangular inputs
    input [4:0] y,
    input iv,
    output [4:0] phs,	// polar outputs
    output [2:0] mag,
    output ov,
    input clk,				// master clock and reset
    input rst
    );
// internal signals
reg [1:0] q;		// quadrant
wire [3:0] x0,y0;	// positive value of inputs
reg [3:0] x1,y1;	// first quadrant version of inputs
wire [3:0] p1;		// first quadrant phase from ROM
reg [4:0] p2;		// phase adjusted to actual quadrant
reg [2:1] v;		// data valid delay
// rotate into first quadrant (0-90 degrees)
// by taking absolute value of inputs
assign x0 = {x[4]^x[3],x[4]^x[2],x[4]^x[1],x[4]^x[0]};
assign y0 = {y[4]^y[3],y[4]^y[2],y[4]^y[1],y[4]^y[0]};
// and swapping when signs don't match
// also calculate quadrant (X+ Y+ = 0, X- Y+ = 1, X- Y- = 2, X+ Y- = 3)
always @ (posedge clk)
begin
	x1 <= (x[4]^y[4]) ? y0 : x0;
	y1 <= (x[4]^y[4]) ? x0 : y0;
	q <= {y[4],x[4]^y[4]};
end
// look up arctangent (LS address is X and MS address is Y)
rom256x4atan rom1 (
	.a({y1,x1}),
	.spo(p1)
	);
// look up magnitude
rom64x3mag rom2 (
	.a({x1[3:1],y1[3:1]}),	// upper 3 bits of absolute value of X and Y
	.qspo(mag),					// top bit is -6 dB, lower 2 are -3 and -1.5 dB
	.clk(clk)
	);
// form phase output by adding 1st quadrant phase to quadrant number
always @ (posedge clk)
begin
	p2 <= {q,3'b000} + {1'b0,p1};
	v <= {v[1],iv & ~rst};
end
// connect outputs
assign phs = p2;
assign ov = v[2];
endmodule
