Attention
This documentation is a work in progress. Expect to see errors and unfinished things.
phasex Source File
1`timescale 1ns / 1ns
2
3// DMTD-inspired investigation into clock phasing
4// No on-chip analysis, but that could be added later once we see the captured patterns
5module phasex #(
6 parameter aw=10
7) (
8 input uclk1, // unknown clock 1
9 input uclk2, // unknown clock 2
10 input sclk, // sampling clock
11 input rclk, // readout clock (data transfer, local bus)
12 // all of the following are in rclk domain
13 input trig,
14 output ready,
15 input [aw-1:0] addr,
16 output [15:0] dout
17);
18
19// Move software-created trigger to sclk domain
20wire trig2;
21flag_xdomain trigx(.clk1(rclk), .flagin_clk1(trig),
22 .clk2(sclk), .flagout_clk2(trig2));
23
24// Dividers for snapshot operation
25reg div1=0, div2=0;
26always @(posedge uclk1) div1 <= ~div1;
27always @(posedge uclk2) div2 <= ~div2;
28
29// Control logic in sclk domain
30// aw bits row address, 3 bits to control stuffing of 8 bit-pairs into one 16-bit word
31reg [aw+2:0] count=0;
32reg run=0;
33always @(posedge sclk) begin
34 if (trig2) run <= 1;
35 if (run) count <= count+1;
36 if (&count) run <= 0;
37end
38wire wen = run & (&count[2:0]);
39wire [aw-1:0] waddr = count[aw+2:3];
40
41// Data flow logic, also in sclk domain
42reg [15:0] shiftr=0;
43(* ASYNC_REG = "TRUE" *) reg [1:0] snap=0;
44always @(posedge sclk) begin
45 snap <= {div2, div1}; // safely crosses clock domain
46 if (run) shiftr <= {shiftr[13:0], snap};
47end
48
49// Store the result
50dpram #(.aw(aw), .dw(16)) phmem(.clka(sclk), .clkb(rclk),
51 .addra(waddr), .dina(shiftr), .wena(wen),
52 .addrb(addr), .doutb(dout));
53
54// Single status bit, OK to capture in rclk domain
55reg ready_r=0;
56reg invalid=0;
57always @(posedge rclk) begin
58 ready_r <= ~run; // safely crosses clock domain
59 if (trig) invalid <= 1;
60 if (~ready_r) invalid <= 0;
61end
62assign ready = ready_r & ~invalid;
63
64endmodule