// Totalizer for averaging the I/Q/-I/-Q samples independently // Initial coding: Larry Doolittle, 3/2/2003 // // Based on Xilinx's SRL16E primitive. // It is therefore useful only on Xilinx Virtex-derived chips, // including Spartan-II, Spartan-IIe, Virtex, Virtex-E, // Virtex-II, and Virtex-IIpro (February 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: // adder 24 // static FIFO 24 // readout FIFO 16 // countdown 3 // total 67 (2% of XCV150) `timescale 1ns / 1ns // module srl16x16e(Q, A0, A1, A2, A3, CE, CLK, D); // see srl16s16e.v module totalizer(inp, rst, clk, shifte, addr, dout); input [11:0] inp; input rst, clk, shifte; input [1:0] addr; output [15:0] dout; wire [23:0] load_data; wire [23:0] recirc; srl16x24e s1(.Q(recirc), .A0(1'b1), .A1(1'b1), .A2(1'b0), .A3(1'b0), .CE(shifte), .CLK(clk), .D(load_data)); srl16x16e s2(.Q(dout), .A0(1'b1), .A1(addr[0]), .A2(addr[1]), .A3(1'b0), .CE(shifte), .CLK(clk), .D(load_data[23:8])); reg [2:0] countdown; wire zerome = (countdown != 3'b000); wire [23:0] extended_inp = {{8{inp[11]}},inp}; assign load_data = zerome ? extended_inp : (recirc + extended_inp); always @(posedge clk or rst) begin if (rst) countdown <= 3'b000; else begin countdown <= shifte ? ( (countdown != 3'b000) ? countdown-1 : 3'b000 ) : ( 3'b100); end end always @(negedge clk) $display( shifte, countdown, zerome, inp, recirc); endmodule module main(); integer cc; reg clk, rst; initial begin rst = 1'b1; for (cc = 0; cc < 200; cc = cc + 1) begin clk = 1; #12; clk = 0; #13; rst = 0; end $finish; end reg shifte; initial shifte=1'b0; reg [1:0] addr; initial addr=2'b00; reg [11:0] din; wire [15:0] dout; totalizer u(din, rst, clk, shifte, addr, dout); always @(posedge clk) begin if ((cc == 10) || (cc == 90)) shifte <= 1'b1; if ((cc == 74) || (cc == 154)) shifte <= 1'b0; din <= cc; end endmodule