Attention
This documentation is a work in progress. Expect to see errors and unfinished things.
phaset Source File
1// Digital phase-locked-loop tracker
2
3// At least in this application, the sampling clock is not phase-locked
4// to the clocks of interest. So a binary phase accumulator is as good
5// as any, and it makes the arithmetic for subtracting the two results
6// (from the two unknown clocks) easy.
7
8`timescale 1ns / 1ns
9
10module phaset #(
11 parameter order=1,
12 parameter dw=14,
13 parameter adv=3861,
14 parameter delta=16
15) (
16 input uclk,
17 input uclkg,
18 input sclk,
19 output [dw-1:0] phase,
20 output fault // single cycle
21);
22
23// _Still_ draw analogy to the AD9901
24// Generalize to a Johnson counter
25reg [order-1:0] ishr=0;
26always @(posedge uclk) if (uclkg) ishr <= (ishr << 1) | {{order-1{1'b0}},~ishr[order-1]};
27wire capture; reg_tech_cdc capture_cdc(.I(ishr[0]), .C(sclk), .O(capture));
28
29// Test bench fails for some initial phase_r values between 14900 and 15050.
30// In that case the fault output signals the problem.
31reg [dw-1:0] osc=0, acc=0, phase_r=0;
32reg fault_r=0;
33wire msb = acc[dw-1];
34wire nsb = acc[dw-2];
35wire peak = acc[dw-2] ^ acc[dw-3]; // peak of virtual sine wave
36wire move = capture != msb;
37wire dir = ~nsb;
38wire dn = move & dir;
39wire up = move & ~dir;
40always @(posedge sclk) begin
41 if (move) phase_r <= phase_r + (dir ? -delta : delta);
42 fault_r <= move & peak;
43 osc <= osc + adv;
44 acc <= osc + phase_r;
45end
46assign phase = phase_r;
47assign fault = fault_r;
48
49endmodule