//
//		fix2flt16.v - convert complex fixed point to complex floating point
//
//					(C) Copyright 2005-2010 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.
//
// This circuit uses a sequence of multiplexers to shift an integer left
// by 0-15 bits until the value of either the X or Y component is between
// +/-0.5 and +/-1. The number of shifts becomes the exponent. The output
// consists of two 5 bit numbers in two's complement form.
//
// The delay is 4 clocks at 249 MHz maximum and 55 slices are used.
// (max. frequency measured with input register)
//
// History:
//		2-12-10	modified for 16 bit inputs (saves 4 slices)
// 
module fix2flt16(doe,dox,doy,ov,dix,diy,iv,clk);
    output [3:0] doe;		// data output exponent
    output [4:0] dox,doy;	// data output magnitude
	 output ov;					// output valid
    input [15:0] dix,diy;	// fixed point data input
	 input iv;					// input valid
    input clk;					// master clock
// internal busses
wire sx0,sy0;			// sign bits
reg sx1,sy1,sx2,sy2,sx3,sy3,sx4,sy4;	// sign bit delay
wire [14:0] x0,y0;	// 15 bit input
reg [14:4] x1,y1;		// 11 bit shifter stage
reg [14:8] x2,y2;		// 7 bit
reg [14:10] x3,y3;	// 5 bit
reg [14:11] x4,y4;	// 4 bit
wire [3:0] e;			// exponent bits and shift amounts
reg [3:3] e1;			// exponent bit 3
reg [3:2] e2;			// register exponent
reg [3:1] e3;
reg [3:0] e4;
reg [4:1] v;				// data valid bits
// separate sign bits
assign sx0 = dix[15];
assign sy0 = diy[15];
assign x0 = dix[14:0];
assign y0 = diy[14:0];
// shift input to get magnitude field
always @ (posedge clk)
begin
	x1 <= (e[3]) ? {x0[6:0],4'h0} : x0[14:4];
	y1 <= (e[3]) ? {y0[6:0],4'h0} : y0[14:4];
	sx1 <= sx0;
	sy1 <= sy0;
	x2 <= (e[2]) ? x1[10:4] : x1[14:8];
	y2 <= (e[2]) ? y1[10:4] : y1[14:8];
	sx2 <= sx1;
	sy2 <= sy1;
	x3 <= (e[1]) ? x2[12:8] : x2[14:10];
	y3 <= (e[1]) ? y2[12:8] : y2[14:10];
	sx3 <= sx2;
	sy3 <= sy2;
	x4 <= (e[0]) ? x3[13:10] : x3[14:11];
	y4 <= (e[0]) ? y3[13:10] : y3[14:11];
	sx4 <= sx3;
	sy4 <= sy3;
end
// exponent calculation
assign e[3] = (sx0 ~^ x0[14]) & (sy0 ~^ y0[14]) & (sx0 ~^ x0[13]) & (sy0 ~^ y0[13])
					& (sx0 ~^ x0[12]) & (sy0 ~^ y0[12]) & (sx0 ~^ x0[11]) & (sy0 ~^ y0[11])
					& (sx0 ~^ x0[10]) & (sy0 ~^ y0[10]) & (sx0 ~^ x0[9]) & (sy0 ~^ y0[9])
					& (sx0 ~^ x0[8]) & (sy0 ~^ y0[8]) & (sx0 ~^ x0[7]) & (sy0 ~^ y0[7]);
assign e[2] = (sx1 ~^ x1[14]) & (sy1 ~^ y1[14]) & (sx1 ~^ x1[13]) & (sy1 ~^ y1[13])
					& (sx1 ~^ x1[12]) & (sy1 ~^ y1[12]) & (sx1 ~^ x1[11]) & (sy1 ~^ y1[11]);
assign e[1] = (sx2 ~^ x2[14]) & (sy2 ~^ y2[14]) & (sx2 ~^ x2[13]) & (sy2 ~^ y2[13]);
assign e[0] = (sx3 ~^ x3[14]) & (sy3 ~^ y3[14]);
// latch output
always @ (posedge clk)
begin
	e1 <= e[3];
	e2 <= {e1,e[2]};
	e3 <= {e2,e[1]};
	e4 <= {e3,e[0]};
	v <= {v[3:1],iv};
end
// connect output port
assign doe = e4;
assign dox = {sx4,x4};
assign doy = {sy4,y4};
assign ov = v[4];
endmodule
