// totalizer.v
// Totalizer for averaging the I/Q/-I/-Q samples independently
// $Id$
// Larry Doolittle, LBNL
// llc-suite Copyright (c) 2004, The Regents of the University of
// California, through Lawrence Berkeley National Laboratory (subject
// to receipt of any required approvals from the U.S. Dept. of Energy).
// All rights reserved.
// Your use of this software is pursuant to a "BSD-style" open
// source license agreement, the text of which is in license.txt
// (md5sum a1e0e81c78f6eba050b0e96996f49fd5) that should accompany
// this file. If the license agreement is not there, or if you
// have questions about the license, please contact Berkeley Lab's
// Technology Transfer Department at TTD@lbl.gov referring to
// "llc-suite (LBNL Ref CR-1988)"
// Initial coding: 3/2/2003
// Based on Xilinx's SRL16E primitive.
// It is therefore useful only on Xilinx Virtex-derived chips,
// including Spartan-II, Spartan-IIe, Spartan-3, Virtex, Virtex-E,
// Virtex-II, and Virtex-IIpro (May 2003 list).
//
// to use:
// send shifte high for a multiple of 4 ADC cycles, up to a
// maximum of 1024.
// read out four 16-bit words on dout, selected by addr
// (Each accumulated word is the total of of up to 256 input
// samples. The 4 low order bits of the total are accumulated
// but not presented to the host)
// accumulators (virtually) zero themselves when shifte goes low
// (actually, recirculation is disabled for the first four cycles
// of a newly high shifte)
// corrupted data is read if you try to read when shifte is high,
// but that corruption only affects that particular readout; the
// data stored is always correct, if you can read it out at the
// appropriate time.
// rough cell count, assuming the synthesizer can create a conditional
// adder for load_data (my tests show XST 5.2sp1 can):
// adder 20
// static FIFO 20
// readout FIFO 16
// countdown 3
// total 59 (2% of XCV150)
`timescale 1ns / 1ns
module totalizer
(
input [13:0] host_addr, // interconnect
output [15:0] dout, // register TOTALIZER
input [13:0] totalizer_in, // interconnect
input rst, // interconnect
input clk40, // interconnect
input totalizer_gate // interconnect
);
wire [21:0] load_data;
wire [21:0] recirc;
srl16x22e s1(.Q(recirc), .A0(1'b1), .A1(1'b1), .A2(1'b0), .A3(1'b0),
.CE(totalizer_gate), .CLK(clk40), .D(load_data));
srl16x16e s2(.Q(dout), .A0(host_addr[0]), .A1(host_addr[1]), .A2(1'b0), .A3(1'b0),
.CE(totalizer_gate), .CLK(clk40), .D(load_data[21:6]));
reg [2:0] countdown;
wire zerome = (countdown != 3'b000);
assign load_data = {{8{totalizer_in[13]}},totalizer_in} + ( zerome ? 0 : recirc );
always @(posedge clk40 or posedge rst) begin
if (rst) countdown <= 3'b000;
else begin
countdown <= totalizer_gate ?
( (countdown != 3'b000) ? countdown-1 : 3'b000 ) :
( 3'b100);
end
end
// always @(negedge clk) $display( shifte, countdown, zerome, " ", inp, " ", recirc);
endmodule