/* 38-76 MHz Fractional-N synthesizer http://www.holmea.demon.co.uk/Frac3/Main.htm Copyright (c) 2009 Andrew Holme */ module Frac3( input VCO_P, input VCO_N, input REF_P, input REF_N, output PFD_P, output PFD_N); wire tck, shift, tdi, update; reg [ 6:0] N; reg [31:0] F; reg [38:0] dr; reg tdo; BSCAN_SPARTAN3 jtag ( .DRCK1 (tck), .SHIFT (shift), .TDI (tdi), .UPDATE (update)); always @ (posedge tck) if (shift) {tdo,dr} <= {dr,tdi}; always @ (posedge update) {N,F} <= dr; wire vco_clk, vco_gate, vco_phase; wire ref_clk, ref_gate, ref_phase; wire pfd_out, msh_cycle; wire [6:0] dN, div; reg msh_gate; IBUFGDS vco_ibufgds(.I(VCO_P), .IB(VCO_N), .O(vco_clk)); IBUFGDS ref_ibufgds(.I(REF_P), .IB(REF_N), .O(ref_clk)); DIVIDER ref_div(.clk(ref_clk), .ce(ref_gate), .data(7'd99)); DIVIDER vco_div(.clk(vco_clk), .ce(vco_gate), .data(N + dN), .div(div)); BUFGCE vco_bufgce(.I(vco_clk), .CE(vco_gate), .O(vco_phase)); BUFGCE ref_bufgce(.I(ref_clk), .CE(ref_gate), .O(ref_phase)); BUFGCE msh_bufgce(.I(vco_clk), .CE(msh_gate), .O(msh_cycle)); always @ (negedge vco_clk) msh_gate <= (div==7'd4); MASH msh(.clk(msh_cycle), .F(F), .dN(dN)); AD9901 pfd(.vco_phase(vco_phase), .ref_phase(ref_phase), .pfd_out(pfd_out)); OBUFDS obufds(.I(pfd_out), .O(PFD_P), .OB(PFD_N)); endmodule module DIVIDER( input clk, input [6:0] data, output reg ce, output reg [6:0] div); always @ (posedge clk) div <= div? div-1'b1 : data; always @ (negedge clk) ce <= ~|div; endmodule module AD9901( input vco_phase, input ref_phase, output pfd_out); wire ref_tff_q, ref_dff_q; wire vco_tff_q, vco_dff_q; FD ref_tff(.Q(ref_tff_q), .D(~ref_tff_q), .C(ref_phase)); FD vco_tff(.Q(vco_tff_q), .D(~vco_tff_q), .C(vco_phase)); wire xout = ref_tff_q ^ vco_tff_q; FDC ref_dff(.Q(ref_dff_q), .D(xout), .C(ref_phase), .CLR(~vco_dff_q)); FDP vco_dff(.Q(vco_dff_q), .D(xout), .C(vco_phase), .PRE(ref_dff_q)); assign pfd_out = (xout & vco_dff_q) | ref_dff_q; endmodule module MASH( input clk, input [31:0] F, output [6:0] dN); wire [127:0] cmd, sum; wire [ 27:0] fbi, fbo; STAGE stage [3:0] (.clk(clk), .cmd(cmd), .sum(sum), .fbi(fbi), .fbo(fbo)); assign cmd = {sum[95:0],F}; assign {fbi,dN} = {7'b0,fbo}; endmodule module STAGE( input clk, input [31:0] cmd, output [31:0] sum, input [6:0] fbi, output [6:0] fbo); wire carry; reg [31:0] acc; reg [6:0] fbd; initial {acc,fbd} <= 0; assign {carry,sum} = acc + cmd; assign fbo = carry + fbi - fbd; always @ (posedge clk) begin acc <= sum; fbd <= fbi; end endmodule