diff options
Diffstat (limited to 'fpga/usrp2/control_lib/clock_control.v')
-rw-r--r-- | fpga/usrp2/control_lib/clock_control.v | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/fpga/usrp2/control_lib/clock_control.v b/fpga/usrp2/control_lib/clock_control.v new file mode 100644 index 000000000..000eaf1fb --- /dev/null +++ b/fpga/usrp2/control_lib/clock_control.v @@ -0,0 +1,132 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + + + +// AD9510 Register Map (from datasheet Rev. A) + +/* INSTRUCTION word format (16 bits) + * 15 Read = 1, Write = 0 + * 14:13 W1/W0, Number of bytes 00 - 1, 01 - 2, 10 - 3, 11 - stream + * 12:0 Address + */ + +/* ADDR Contents Value (hex) + * 00 Serial Config Port 10 (def) -- MSB first, SDI/SDO separate + * 04 A Counter + * 05-06 B Counter + * 07-0A PLL Control + * 0B-0C R Divider + * 0D PLL Control + * 34-3A Fine Delay + * 3C-3F LVPECL Outs + * 40-43 LVDS/CMOS Outs + * 45 Clock select, power down + * 48-57 Dividers + * 58 Func and Sync + * 5A Update regs + */ + + +module clock_control + (input reset, + input aux_clk, // 25MHz, for before fpga clock is active + input clk_fpga, // real 100 MHz FPGA clock + output [1:0] clk_en, // controls source of reference clock + output [1:0] clk_sel, // controls source of reference clock + input clk_func, // FIXME needs to be some kind of out SYNC or reset to 9510 + input clk_status, // Monitor PLL or SYNC status + + output sen, // Enable for the AD9510 + output sclk, // FIXME these need to be shared + input sdi, + output sdo + ); + + wire read = 1'b0; // Always write for now + wire [1:0] w = 2'b00; // Always send 1 byte at a time + + assign clk_sel = 2'b00; // Both outputs from External Ref (SMA) + assign clk_en = 2'b11; // Both outputs enabled + + reg [20:0] addr_data; + + reg [5:0] entry; + reg start; + reg [7:0] counter; + reg [23:0] command; + + always @* + case(entry) + 6'd00 : addr_data = {13'h00,8'h10}; // Serial setup + 6'd01 : addr_data = {13'h45,8'h00}; // CLK2 drives distribution, everything on + 6'd02 : addr_data = {13'h3D,8'h80}; // Turn on output 1, normal levels + 6'd03 : addr_data = {13'h4B,8'h80}; // Bypass divider 1 (div by 1) + 6'd04 : addr_data = {13'h08,8'h47}; // POS PFD, Dig LK Det, Charge Pump normal + 6'd05 : addr_data = {13'h09,8'h70}; // Max Charge Pump current + 6'd06 : addr_data = {13'h0A,8'h04}; // Normal operation, Prescalar Div by 2, PLL On + 6'd07 : addr_data = {13'h0B,8'h00}; // RDIV MSB (6 bits) + 6'd08 : addr_data = {13'h0C,8'h01}; // RDIV LSB (8 bits), Div by 1 + 6'd09 : addr_data = {13'h0D,8'h00}; // Everything normal, Dig Lock Det + 6'd10 : addr_data = {13'h07,8'h00}; // Disable LOR detect - LOR causes failure... + 6'd11 : addr_data = {13'h04,8'h00}; // A Counter = Don't Care + 6'd12 : addr_data = {13'h05,8'h00}; // B Counter MSB = 0 + 6'd13 : addr_data = {13'h06,8'h05}; // B Counter LSB = 5 + default : addr_data = {13'h5A,8'h01}; // Register Update + endcase // case(entry) + + wire [5:0] lastentry = 6'd15; + wire done = (counter == 8'd49); + + always @(posedge aux_clk) + if(reset) + begin + entry <= #1 6'd0; + start <= #1 1'b1; + end + else if(start) + start <= #1 1'b0; + else if(done && (entry<lastentry)) + begin + entry <= #1 entry + 6'd1; + start <= #1 1'b1; + end + + always @(posedge aux_clk) + if(reset) + begin + counter <= #1 7'd0; + command <= #1 20'd0; + end + else if(start) + begin + counter <= #1 7'd1; + command <= #1 {read,w,addr_data}; + end + else if( |counter && ~done ) + begin + counter <= #1 counter + 7'd1; + if(~counter[0]) + command <= {command[22:0],1'b0}; + end + + + assign sen = (done | counter == 8'd0); // CSB is high when we're not doing anything + assign sclk = ~counter[0]; + assign sdo = command[23]; + +endmodule // clock_control |