Attention
This documentation is a work in progress. Expect to see errors and unfinished things.
timestamp Source File
1// High-speed cycle counter
2
3// This module attaches to the slow readout bus used in many
4// LBNL DAQ builds. It provides a 59-bit cycle counter (since chip boot),
5// and an optional timestamp capture register.
6
7// The 8-bit-wide shift-register-style output is ready to be merged
8// in a "slow" DSP data stream, LSB-first. Sorry about the byte-order,
9// but it's intrinsic to the mechanism used.
10
11// Synthesizes to 54 LUTs and 31 Flip flops at 150 MHz in XC3S1000-5 with XST 12.1 (aux_reg=0)
12// Synthesizes to 101 LUTs and 65 Flip flops at 150 MHz in XC3S1000-5 with XST 12.1 (aux_reg=1)
13// 59-bit counter will wrap every 182 years if clocked at 100 MHz.
14`timescale 1ns / 1ns
15module timestamp(
16 input clk, // timespec 6.6 ns
17 // aux_ ports are only useful if parameter aux_reg is 1
18 input aux_trig,
19 output aux_skip,
20 input slow_op,
21 input slow_snap,
22 input [7:0] shift_in,
23 output [7:0] shift_out
24);
25
26// Re-use some ideas from SNS
27
28// Data bus width, used to make the testing process shorter and more believable.
29parameter dw=8;
30parameter aux_reg=0;
31
32reg [2:0] fast=0;
33reg [dw-1:0] count_loop=0;
34reg c_out=0;
35wire [dw-1:0] count_out;
36wire c_in = (fast==0) ? 1 : c_out;
37always @(posedge clk) begin
38 fast <= fast+1;
39 {c_out,count_loop} <= count_out + c_in;
40end
41
42reg_delay #(.dw(dw), .len(7))
43 count(.clk(clk), .reset(1'b0), .gate(1'b1), .din(count_loop), .dout(count_out));
44
45// Can snapshot fast anytime. Have to wait for the next cycle of
46// fast sequencing from 0 through 7 before the rest of the counter
47// state can be read out
48reg pending=0, sending=0, grab_fast=0;
49always @(posedge clk) begin
50 grab_fast <= slow_op & slow_snap;
51 if (fast==7) pending <= 0;
52 if (slow_op & slow_snap) pending <= 1;
53 if (fast==7) sending <= pending;
54 if (fast==6) sending <= 0;
55end
56wire [dw-1:0] fast_pad={fast,{dw-3{1'b0}}};
57wire [dw-1:0] shift_in2; // output of aux subsystem
58wire [dw-1:0] snap_in = grab_fast ? fast_pad : (slow_op&~slow_snap) ? shift_in2 : count_out;
59wire snap_shift=grab_fast|(slow_op&~slow_snap)|sending;
60wire [dw-1:0] snap_out;
61reg_delay #(.dw(dw), .len(8))
62 s1(.clk(clk), .reset(1'b0), .gate(snap_shift), .din(snap_in), .dout(snap_out));
63
64// Second snapshot register
65// If aux_reg is a constant 0 at compile-time, this will get optimized away
66reg abusy=0, axmit=0, astored=0;
67reg apending=0, asending=0, agrab_fast=0;
68always @(posedge clk) begin
69 agrab_fast <= aux_trig & ~abusy;
70 if (aux_trig) abusy <= 1;
71 if (fast==7) apending <= 0;
72 if (aux_trig & ~abusy) apending <= 1;
73 if (fast==7) asending <= apending;
74 if (fast==6) asending <= 0;
75 if ((fast==6)&asending) astored<=1;
76 if (astored&slow_op&slow_snap) begin astored<=0; axmit<=1; end
77 if (axmit&slow_op&slow_snap) begin axmit<=0; abusy<=0; end
78end
79wire [dw-1:0] ashiftd; // hold shift register data in parallel with aux slot
80reg_delay #(.dw(dw), .len(8))
81 aslow(.clk(clk), .reset(1'b0), .gate(slow_op), .din(shift_in[dw-1:0]), .dout(ashiftd));
82wire [dw-1:0] asnap_in = agrab_fast ? fast_pad : count_out;
83wire asnap_shift=agrab_fast|asending|(axmit&slow_op&~slow_snap);
84wire [dw-1:0] asnap_out; // shift register fills with time info
85reg_delay #(.dw(dw), .len(8))
86 a1(.clk(clk), .reset(1'b0), .gate(asnap_shift), .din(asnap_in), .dout(asnap_out));
87// Keep track of the first 8 shift commands
88reg [2:0] ascnt=0;
89reg apost8=0;
90always @(posedge clk) begin
91 if (slow_op&slow_snap) begin ascnt<=0; apost8<=0; end
92 if (slow_op&~slow_snap&~apost8) ascnt<=ascnt+1;
93 if (slow_op&~slow_snap&(ascnt==7)) apost8<=1;
94end
95// Note dependence on aux_reg
96// Always skips in the non-aux_reg case
97assign aux_skip = aux_reg ? (aux_trig & abusy) : aux_trig;
98assign shift_in2 = aux_reg ? (apost8 ? ashiftd : axmit ? asnap_out : 0) : shift_in;
99
100// Output of this module is simply the output of the above shift register
101// Making an explicit copy like this avoids a warning when dw != 8
102assign shift_out=snap_out;
103
104// More-or-less equivalent to adding
105// { time1, time2, time3, time4, atime1, atime2, atime3, atime4 }
106// to slow_sr_data, but uses far fewer resources
107
108endmodule