//
//				comp16.v - Compressor with 16-bit X and Y inputs	
//
//					(C) Copyright 2008-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 module implements a compressor for rectangular signals. The input
// magnitude is estimated and the required gain is obtained from a ROM and
// applied to multipliers for the X and Y paths. The ROM is loaded via the
// CIN input and consists of 64 8-bit entries formatted as follows:
//
//     7   6   5   4   3   2   1   0
//   +---+---+---+---+---+---+---+---+
//   |    Integer    |   Fraction    | Gain control entry
//   +---+---+---+---+---+---+---+---+
//
// Entries are loaded serially with the entry for the larget magnitude first.
// The absence of compression is selected by loading all entries with 10 hex
// or 16 decimal. Note that the magnitude estimate has a range of 0.87-0.98
// of the actual value.
//
// 76 slices and 2 multipliers are used. 95 MHz maximum clock rate. There
// is a 3 clock delay.
//
// Normal Warnings:
//		<x<35:22>>, <x<5:0>>, <y<35:22>> and <x<5:0>> are assigned but never used.
//		<mag<0>> is assigned but never used.
//
// History:
//		6-8-09	created
//		5-3-10	8-bit magnitude (was 72 slices 105 MHz)
//
module comp16 (
    input [15:0] dix,diy,	// data in
    input iv,					// input valid
    output [15:0] dox,doy,	// data out
    output ov,					// output valid
    input clk,
	 input [7:0] cin,			// configuration input
	 input cwe
    );
// internal signals
wire [35:0] x,y;	// multiplied input signal
wire [7:0] gain;	// gain control
wire [7:0] mag;	// magnitude of input (0-1.4)
wire [5:0] mag1;	// magnitude limited to 0-1
wire mv;				// magnitude valid
reg [2:1] v;		// data valid delay
// generate data valid
always @ (posedge clk) v <= {v[1],mv};
// multiply input signal by AGC value
MULT18X18SIO #(
	.AREG(1),
	.BREG(0),
	.PREG(1)
	) mulx (
	.A({dix,2'b00}),
	.B({10'b0000000000,gain}),
	.P(x),
	.CEA(iv),
	.CEB(1'b1),
	.CEP(mv),
	.CLK(clk),
	.RSTA(1'b0),
	.RSTB(1'b0),
	.RSTP(1'b0)
	);
MULT18X18SIO #(
	.AREG(1),
	.BREG(0),
	.PREG(1)
	) muly (
	.A({diy,2'b00}),
	.B({10'b0000000000,gain}),
	.P(y),
	.CEA(iv),
	.CEB(1'b1),
	.CEP(mv),
	.CLK(clk),
	.RSTA(1'b0),
	.RSTB(1'b0),
	.RSTP(1'b0)
	);
// calculate magnitude of input - limit max. value to 127
mag8 magdet (
	.x(dix[15:8]),
	.y(diy[15:8]),
	.iv(iv),
	.mag(mag),
	.ov(mv),
	.clk(clk)
	);
assign mag1 = mag[7] ? 63 : mag[6:1];
// look up gain
srl64x8e gm (
	.d(cin[7:0]),
	.ce(cwe),
	.clk(clk),
	.a(mag1),
	.y(gain)
	);
// connect outputs
assign dox = x[21:6];	// maximum gain is 16
assign doy = y[21:6];
assign ov = v[2];			// output valid
endmodule
