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