Attention

This documentation is a work in progress. Expect to see errors and unfinished things.

rot_dds Source File

 1// Phase Rotating Direct Digital Synthesis of sin/cos
 2// 18 bit output coming from cordicg
 3// Note that phase_step_h and phase_step_l combined fit in a 32-bit word.
 4// This is intentional, to allow atomic updates of the two controls
 5// in 32-bit systems.  Indeed, when modulo==0, those 32 bits can be considered
 6//
 7// a simple fast binary DDS control for quirky (non-binary-rounding) phase
 8// steps like:
 9// 7/33 for LCLS-II
10// 8/11 for SSRF
11// 9/13 for Argonne RIA
12//
13// The phase generation algorithm
14// 0. The phase increments for dds are generated using a technique described
15// in these 2 places:
16// Section: PROGRAMMABLE MODULUS MODE in:
17//  https://www.analog.com/media/en/technical-documentation/data-sheets/ad9915.pdf
18//  (AND) https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
19//  Basically, increment the phase step at a coarse resolution, accumulate the
20//  error on the side, and when that error accumulates to the lowest bit of
21//  the coarse counter, add an extra 1 to the following phase step.
22// 1. phase_step_h is the coarse (20 bit) integer truncated phase increment for
23//  the cordic. There is a 1-bit increment of phase that comes from
24//  accumulating residue phase.
25// 2. This residue phase is accumulating in steps of phase_step_l, in a 12-bit
26//  counter.
27// 3. However, there will be an extra residue even for this 12-bit counter,
28// which is the modulus, and this added as an offset when the counter crosses 0
29
30// 12-bit modulo supports largest known periodicity in a suggested LLRF system,
31// 1427 for JLab.  For more normal periodicities, use a multiple to get finer
32// granularity.
33// Note that the downloaded modulo control is the 2's complement of the
34// mathematical modulus.
35// e.g., SSRF IF/F_s ratio 8/11, use
36//     modulo = 4096 - 372*11 = 4
37//     phase_step_h = 2^20*8/11 = 762600
38//     phase_step_l = (2^20*8%11)*372 = 2976
39// e.g., Argonne RIA test IF/F_s ratio 9/13, use
40//     modulo = 4096 - 315*13 = 1
41//     phase_step_h = 2^20*9/13 = 725937
42//     phase_step_l = (2^20*9%13)*315 = 945
43
44// TODO:
45// Potentially, isolate phase generation into a separate module.
46// Haha, turns out there is ph_acc.v (We should USE it).
47// Synthesizes to ??? slices at ??? MHz in XC3Sxxx-4 using XST-??
48//
49
50`timescale 1ns / 1ns
51
52module rot_dds(
53     input clk,  // timespec 9.0 ns
54     input reset,  // active high, synchronous with clk
55     output signed [17:0] sina,
56     output signed [17:0] cosa,
57     input [19:0] phase_step_h,
58     input [11:0] phase_step_l,
59     input [11:0] modulo
60);
61
62// 2^17/1.64676 = 79594, use a smaller value to keep CORDIC round-off
63// from overflowing the output
64parameter lo_amp = 18'd79590;
65// Sometimes we cheat and use slightly smaller values than above,
66// to make other computations fit better.
67
68// See rot_dds_config
69
70reg carry=0, reset_d=0;
71reg [19:0] phase_h=0, phase_step_hp=0;
72reg [11:0] phase_l=0;
73always @(posedge clk) begin
74     {carry, phase_l} <= reset ? 13'b0 : ((carry ? modulo : 12'b0) + phase_l + phase_step_l);
75     phase_step_hp <= phase_step_h;
76     reset_d <= reset;
77     phase_h <= reset_d ? 20'b0 : (phase_h + phase_step_hp + carry);
78end
79cordicg_b22 #(.nstg(20), .width(18), .def_op(0)) trig(.clk(clk), .opin(2'b00),
80     .xin(lo_amp), .yin(18'd0), .phasein(phase_h[19:1]),
81// 2^17/1.64676 = 79594, use a smaller value to keep CORDIC round-off
82// from overflowing the output
83     .xout(cosa), .yout(sina));
84
85endmodule