// hist2.v
// LLRF averaging history buffers submodule
// $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: March 2003
//
// See hist2.v for its timing controller, history2e.v for overview
// 512 x 16 buffer, programmable averaging
// Most of the RAW_ADC_BITS and ADDRESS_BITS dependencies are parameterized
// the way they're supposed to be. In a couple of places, the constructs
// require conditional code, and AFAIK Verilog can't do compile-time
// conditionals based on parameters. So the user is forced to do the
// following:
//
// if RAW_ADC_BITS=14, do nothing
// if RAW_ADC_BITS=12, set the preprocessor token ADC_BIT12
// other values of RAW_ADC_BITS are not supported
//
// if ADDRESS_BITS=10, do nothing
// if ADDRESS_BITS=9, set the preprocessor token ADDRESS_BIT9
// other values of ADDRESS_BITS are not supported
//
// If you use the supplied Makefile to set RAW_ADC_BITS and ADDRESS_BITS,
// this logic is taken care of automatically.
`timescale 1ns / 1ns
![[Up: history2e traced]](v2html-up.gif)
![[Up: history2e trace1]](v2html-up.gif)
![[Up: history2e trace2]](v2html-up.gif)
module hist2
(
clk40, in_data, trace_address, write_enable, clear, average,
clk_host, host_dout, host_addr);
parameter RAW_ADC_BITS=`RAW_ADC_BITS;
parameter AVERAGE_BITS=`AVERAGE_BITS;
parameter ADDRESS_BITS=`ADDRESS_BITS;
input clk40; // input data clock
input [RAW_ADC_BITS-1:0] in_data; // must be signed
input [ADDRESS_BITS-1:0] trace_address; // from histmode.v
input write_enable, clear; // from histmode.v
input [AVERAGE_BITS-1:0] average; // 0-127, (number of input samples per output bin)-1
input clk_host;
output [15:0] host_dout;
input [ADDRESS_BITS-1:0] host_addr;
// output of the two-deep FIFO instantiated at the end
wire [RAW_ADC_BITS+AVERAGE_BITS-1:0] recirc;
// sign extend from 12 to 19 bits
wire [RAW_ADC_BITS+AVERAGE_BITS-1:0] extend_in = {{(AVERAGE_BITS){in_data[RAW_ADC_BITS-1]}},in_data};
// note the subtraction, which in combination with the two-deep FIFO
// provides appropriate averaging of input +I +Q -I -Q data stream
wire [RAW_ADC_BITS+AVERAGE_BITS-1:0] sum = extend_in - (clear ? 0 : recirc);
// low budget multiplexer that saves the "important" data bits;
// the resulting bits must be rotated into a useful order by the software
wire [15:0] keep = {
`ifdef ADC_BIT12
sum[15:3],
average[6] ? sum[18] : sum[2],
|average[6:5] ? sum[17] : sum[1],
|average[6:4] ? sum[16] : sum[0]};
`else
sum[15:5],
average[6] ? sum[20] : sum[4],
|average[6:5] ? sum[19] : sum[3],
|average[6:4] ? sum[18] : sum[2],
|average[6:3] ? sum[17] : sum[1],
|average[6:2] ? sum[16] : sum[0]};
`endif
// in a Spartan-2, this is an aggregation of some 4096-bit Block RAMs
// port A is used to stream the data in from the ADC
// port B is available for the host to read out results
`ifdef ADDRESS_BIT9
ramdp512x16
`else
ramdp1024x16
`endif
trace1(
.ADDRA(trace_address),
.RSTA(1'b0),
.ENA(1'b1),
.WEA(write_enable),
.CLKA(clk40),
.DIA(keep),
//.DOA(void), // never any reason to read from port A
.ADDRB(host_addr),
.RSTB(1'b0),
.ENB(1'b1),
.WEB(1'b0), // host write not implemented
.CLKB(clk_host),
.DIB(16'd0), // not used
.DOB(host_dout));
// always @(negedge clk40)
// $display("sum=0x%x clear=%d recirc=0x%x extend_in=0x%x in_data=%b",
// sum, clear, recirc, extend_in, in_data);
// two-deep FIFO, full accumulator precision
//
// If we didn't have the cute Xilinx SRLE feature, this could also
// be done (with sort-of twice the footprint) as two simple banks
// of flip flops.
`ifdef ADC_BIT12
srl16x19e
`else
srl16x21e
`endif
fifo(
.Q(recirc), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0),
.CE(write_enable), .CLK(clk40), .D(sum));
endmodule