/*
 RMS detector: X^2 followed by a CIC. An adjustable shifter allows to
 pick out the appropriate bits from the full register based on the decimation
 factor. For safety bit shift should be set based on the decimation factor.
 The rule is that for decimation of 2^27 sft=0, 2^26 - 1, 2^25 - 2, etc.
 So the formula is sft = floor(27-log2(decim)). Maximum supported shift
 value is 11. Due to shifting the minimum input width (iwidth) is 11.

 Copyright (c) 2008 Dimtel, Inc., All Rights Reserved

 $Id: rms.v,v 1.1.1.1 2009/06/02 20:26:02 dim Exp $
 $Date: 2009/06/02 20:26:02 $
 $Author: dim $
 $Revision: 1.1.1.1 $
 $Log: rms.v,v $
 Revision 1.1.1.1  2009/06/02 20:26:02  dim
 Initial import


*/

`timescale 1ns/100ps

module rms #(parameter iwidth=14) (
  input clk,			// Signal processing clock
  input signed [iwidth-1:0] in,	// 4 samples
  input enable,			// Enable
  
  input usbclk,			// Local bus clock
  input [26:0] decim,		// Decimation factor
  input [3:0]  sft_in,		// Left shift factor
  output [31:0] out,		// Decimated output
  output strobe			// Data update strobe
);
  reg enable_pipe = 1'b0;
  reg signed [2*iwidth-1:0]  square = 0;
  wire [2*iwidth+26:0] crout; // CIC raw output
  wire [3:0] sft = sft_in;
  
  always @(posedge clk) begin
    square      <= in * in;
    enable_pipe <= enable;
  end

  cic #(.iwidth(2*iwidth)) avg(.clk(clk), 
        .in({1'b0, square[2*iwidth-2:0]}), .decim(decim), .enable(enable_pipe),
        .usbclk(usbclk), .out(crout), .strobe(strobe));
        

  // Pick out the right subfield for the output
 
  assign out = (sft == 4'b0000) ? crout[2*iwidth+26:2*iwidth-5] :
	       (sft == 4'b0001) ? crout[2*iwidth+25:2*iwidth-6] :
	       (sft == 4'b0010) ? crout[2*iwidth+24:2*iwidth-7] :
	       (sft == 4'b0011) ? crout[2*iwidth+23:2*iwidth-8] :
	       (sft == 4'b0100) ? crout[2*iwidth+22:2*iwidth-9] :
	       (sft == 4'b0101) ? crout[2*iwidth+21:2*iwidth-10] :
	       (sft == 4'b0110) ? crout[2*iwidth+20:2*iwidth-11] :
	       (sft == 4'b0111) ? crout[2*iwidth+19:2*iwidth-12] :
	       (sft == 4'b1000) ? crout[2*iwidth+18:2*iwidth-13] :
	       (sft == 4'b1001) ? crout[2*iwidth+17:2*iwidth-14] :
	       (sft == 4'b1010) ? crout[2*iwidth+16:2*iwidth-15] :
	                          crout[2*iwidth+15:2*iwidth-16] ;

/*
  // Pick out the right subfield for the output
  always @(sft or out or crout[2*iwidth+26:2*iwidth-16])
    case (sft)
      4'b0000: out = crout[2*iwidth+26:2*iwidth-5];
      4'b0001: out = crout[2*iwidth+25:2*iwidth-6];
      4'b0010: out = crout[2*iwidth+24:2*iwidth-7];
      4'b0011: out = crout[2*iwidth+23:2*iwidth-8];
      4'b0100: out = crout[2*iwidth+22:2*iwidth-9];
      4'b0101: out = crout[2*iwidth+21:2*iwidth-10];
      4'b0110: out = crout[2*iwidth+20:2*iwidth-11];
      4'b0111: out = crout[2*iwidth+19:2*iwidth-12];
      4'b1000: out = crout[2*iwidth+18:2*iwidth-13];
      4'b1001: out = crout[2*iwidth+17:2*iwidth-14];
      4'b1010: out = crout[2*iwidth+16:2*iwidth-15];
      default: out = crout[2*iwidth+15:2*iwidth-16];
    endcase
*/
endmodule // rms
