// dds.v
// Setpoint waveform generation for LLRF
// $Id$
// Larry Doolittle, LBNL
// llc-suite Copyright (c) 2004, The Regents of the University of
// California, through Lawrence Berkeley National Laboratory (subject
// to receipt of any required approvals from the U.S. Dept. of Energy).
// All rights reserved.
// Your use of this software is pursuant to a "BSD-style" open
// source license agreement, the text of which is in license.txt
// (md5sum a1e0e81c78f6eba050b0e96996f49fd5) that should accompany
// this file. If the license agreement is not there, or if you
// have questions about the license, please contact Berkeley Lab's
// Technology Transfer Department at TTD@lbl.gov referring to
// "llc-suite (LBNL Ref CR-1988)"
// Initial coding: December 2002 - January 2003
// Given the 40 MHz clock and a vector setpoint, creates
// the steady 10 MHz (a.k.a. 50 MHz) waveform. If compiled
// with full DDS support, that frequency can be adjusted,
// and of course in that case the initial phase of the result
// is not terribly important.
// Testing should verify that when the input freq is zero,
// the phase of the output waveform is the same for the two
// compilation options. The discrepancy during the cordic
// pipeline fill time can be ignored.
// Note that the CORDIC routine scales the output by the usual
// factor of 1.64676. This introduces an incompatibility between
// the fixed and adjustable frequency configurations. The output
// signal "unadjustable" is intended to be passed through to some
// upper level of software, that can then take this into account.
// 16-bit input freq is a signed number, full scale is +/- 625 kHz,
// so one bit is 19.073486328125 Hz.
`timescale 1ns / 1ns
// `define DDS_UNADJUSTABLE
module dds
(
input [15:0] set_i, // register SET_I
input [15:0] set_q, // register SET_Q
input [15:0] freq, // register DDS_FREQ
input clk40, // interconnect
input dds_run, // interconnect
output [15:0] set_wave // interconnect
);
`ifdef DDS_UNADJUSTABLE
reg [1:0] t;
wire [15:0] iqset = t[0] ? set_i : set_q;
always @(posedge clk40) begin
t <= dds_run ? t+1 : 1;
set_wave <= t[1] ? iqset : -iqset;
end
`else
reg [20:0] phase;
wire [15:0] wave16;
// The cordic routine now uses 16-bits internally, to improve
// internally generated roundoff and truncation error.
cordic c(clk40, set_i, set_q, phase[20:4], set_wave, ,);
// add the signed freq to 10 MHz
// 20.0 10.0 5.0 2.5 1.25 0.625
wire [20:0] dphase = {1'b0, ~freq[15], freq[15], freq[15], freq[15], freq};
always @(posedge clk40) begin
phase <= dds_run ? phase+dphase : 0;
end
// always @(negedge clk) $display("%d %d",$time,phase);
`endif
endmodule