//
//				p2r14.v - 4x4 Polar to 14x14 Rectangular Conversion 		
//
//					(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 input is a 4-bit magnitude and a 4-bit phase. The magnitude may be
// zero or -42 to -3 dBFS in 3 dB steps. The phase is 0 to 337.5 degrees in
// 22.5-degree incremnts. The X-axis and Y-axis outputs are 12 bits each
// with a value between -1984 and +1984. There is a 1 clock period delay.
//
// 48 slices are used. (34 without 3 dB step)
//
module p2r14 (
    input [3:0] mag,
    input [3:0] phs,
    output [13:0] dox,
    output [13:0] doy,
    input clk
    );
// internal signals
wire [5:0] cos0,sin0;
wire [7:0] cos,sin;
reg [13:0] x,y;
// Look up cosine and sine
// Outputs for 0-90 degrees are 0, 12, 22, 29, and 31.
rom16x6cos cosrom (
	.a(phs),
	.spo(cos0)
	);
rom16x6sin sinrom (
	.a(phs),
	.spo(sin0)
	);
// add shifted output to get 3 dB increment
assign cos = {cos0[5],cos0,1'b0} + (mag[0] ? {cos0[5],cos0[5],cos0} : 8'h00);
assign sin = {sin0[5],sin0,1'b0} + (mag[0] ? {sin0[5],sin0[5],sin0} : 8'h00);
// shift to get correct magnitude
always @ (posedge clk)
begin
	case (mag[3:1])
	0: x <= 0;
	1: x <= {cos[7],cos[7],cos[7],cos[7],cos[7],cos[7],cos};
	2: x <= {cos[7],cos[7],cos[7],cos[7],cos[7],cos,1'b0};
	3: x <= {cos[7],cos[7],cos[7],cos[7],cos,2'b00};
	4: x <= {cos[7],cos[7],cos[7],cos,3'b000};
	5: x <= {cos[7],cos[7],cos,4'b0000};
	6: x <= {cos[7],cos,5'b00000};
	7: x <= {cos,6'b000000};
	default: x <= 12'hxxx;
	endcase
	case (mag[3:1])
	0: y <= 0;
	1: y <= {sin[7],sin[7],sin[7],sin[7],sin[7],sin[7],sin};
	2: y <= {sin[7],sin[7],sin[7],sin[7],sin[7],sin,1'b0};
	3: y <= {sin[7],sin[7],sin[7],sin[7],sin,2'b00};
	4: y <= {sin[7],sin[7],sin[7],sin,3'b000};
	5: y <= {sin[7],sin[7],sin,4'b0000};
	6: y <= {sin[7],sin,5'b00000};
	7: y <= {sin,6'b000000};
	default: y <= 12'hxxx;
	endcase
end
// connect outputs
assign dox = x;
assign doy = y;
endmodule
