massive overhaul of fpga code
[fleet.git] / src / edu / berkeley / fleet / fpga / mem / ddr_clkgen.v
1 //---------------------------------------------------------------------------
2 // Wishbone DDR Controller
3 // 
4 // (c) Joerg Bornschein (<jb@capsec.org>)
5 //---------------------------------------------------------------------------
6
7 `timescale 1ns / 1ps
8 `include "ddr_include.v"
9
10 module ddr_clkgen
11 #(
12         parameter phase_shift  = 0,
13         parameter clk_multiply = 13,
14         parameter clk_divide   = 5
15 ) (
16         input        clk,
17         input        reset,
18         output       locked,
19         //
20         output       read_clk,
21         output       write_clk,
22         output       write_clk90,
23         // 
24         input  [2:0] rot
25 );
26
27
28 //----------------------------------------------------------------------------
29 // rotary decoder
30 //----------------------------------------------------------------------------
31 rotary rotdec0 (
32         .clk(       clk        ),
33         .reset(     reset      ),
34         .rot(       rot        ),
35         // output
36         .rot_btn(   rot_btn    ),
37         .rot_event( rot_event  ),
38         .rot_left(  rot_left   )
39 );
40
41 //----------------------------------------------------------------------------
42 // ~133 MHz DDR Clock generator
43 //----------------------------------------------------------------------------
44 wire  read_clk_u;
45 wire  dcm_fx_locked;
46
47 DCM #(
48         .CLKDV_DIVIDE(2.0),          // Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
49                                  //   7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
50         .CLKFX_DIVIDE(clk_divide),   // Can be any integer from 1 to 32
51         .CLKFX_MULTIPLY(clk_multiply), // Can be any integer from 2 to 32
52         .CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature
53         .CLKIN_PERIOD(),             // Specify period of input clock
54         .CLKOUT_PHASE_SHIFT("NONE"), // Specify phase shift of NONE, FIXED or VARIABLE
55         .CLK_FEEDBACK("NONE"),       // Specify clock feedback of NONE, 1X or 2X
56         .DESKEW_ADJUST("SOURCE_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
57                                  //   an integer from 0 to 15
58         .DFS_FREQUENCY_MODE("LOW"),  // HIGH or LOW frequency mode for frequency synthesis
59         .DLL_FREQUENCY_MODE("LOW"),  // HIGH or LOW frequency mode for DLL
60         .DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE
61         .FACTORY_JF(16'hC080),       // FACTORY JF values
62         .PHASE_SHIFT(0),             // Amount of fixed phase shift from -255 to 255
63         .STARTUP_WAIT("FALSE")       // Delay configuration DONE until DCM LOCK, TRUE/FALSE
64 ) dcm_fx (
65         .DSSEN(),
66         .CLK0(),                   // 0 degree DCM CLK output
67         .CLK180(),                 // 180 degree DCM CLK output
68         .CLK270(),                 // 270 degree DCM CLK output
69         .CLK2X(),                  // 2X DCM CLK output
70         .CLK2X180(),               // 2X, 180 degree DCM CLK out
71         .CLK90(),                  // 90 degree DCM CLK output
72         .CLKDV(),                  // Divided DCM CLK out (CLKDV_DIVIDE)
73         .CLKFX(    read_clk_u ),   // DCM CLK synthesis out (M/D)
74         .CLKFX180(),               // 180 degree CLK synthesis out
75         .LOCKED(   dcm_fx_locked), // DCM LOCK status output
76         .PSDONE(),                 // Dynamic phase adjust done output
77         .STATUS(),                 // 8-bit DCM status bits output
78         .CLKFB(),                  // DCM clock feedback
79         .CLKIN(    clk   ),        // Clock input (from IBUFG, BUFG or DCM)
80         .PSCLK(    gnd   ),        // Dynamic phase adjust clock input
81         .PSEN(     gnd   ),        // Dynamic phase adjust enable input
82         .PSINCDEC( gnd   ),        // Dynamic phase adjust increment/decrement
83         .RST(      reset )         // DCM asynchronous reset input
84 );
85
86 //----------------------------------------------------------------------------
87 // BUFG read clock
88 //----------------------------------------------------------------------------
89 BUFG bufg_fx_clk (
90         .O(read_clk),             // Clock buffer output
91         .I(read_clk_u)            // Clock buffer input
92 );
93
94 //----------------------------------------------------------------------------
95 // Phase shifted clock for write path 
96 //----------------------------------------------------------------------------
97 wire  phase_dcm_reset;
98 wire  phase_dcm_locked;
99 wire  write_clk_u, write_clk90_u, write_clk180_u, write_clk270_u;
100
101 DCM #(
102         .CLKDV_DIVIDE(2.0),     // Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
103                             //   7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
104         .CLKFX_DIVIDE(2),       // Can be any integer from 1 to 32
105         .CLKFX_MULTIPLY(2),     // Can be any integer from 2 to 32
106         .CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature
107         .CLKIN_PERIOD(),        // Specify period of input clock
108         .CLK_FEEDBACK("1X"),    // Specify clock feedback of NONE, 1X or 2X
109         .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
110                                           //   an integer from 0 to 15
111         .DFS_FREQUENCY_MODE("LOW"),  // HIGH or LOW frequency mode for frequency synthesis
112         .DLL_FREQUENCY_MODE("LOW"),  // HIGH or LOW frequency mode for DLL
113         .DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE
114         .FACTORY_JF(16'hC080),   // FACTORY JF values
115         .CLKOUT_PHASE_SHIFT("VARIABLE"), // Specify phase shift of NONE, FIXED or VARIABLE
116         .PHASE_SHIFT( phase_shift ), // Amount of fixed phase shift from -255 to 255
117         .STARTUP_WAIT("FALSE")   // Delay configuration DONE until DCM LOCK, TRUE/FALSE
118 ) dcm_phase (
119         .DSSEN(),
120         .CLK0(   write_clk_u ),      // 0 degree DCM CLK output
121         .CLK90(  write_clk90_u ),    // 90 degree DCM CLK output
122         .CLK180( write_clk180_u ),   // 180 degree DCM CLK output
123         .CLK270( write_clk270_u ),   // 270 degree DCM CLK output
124         .CLK2X(),                    // 2X DCM CLK output
125         .CLK2X180(),                 // 2X, 180 degree DCM CLK out
126         .CLKDV(),                    // Divided DCM CLK out (CLKDV_DIVIDE)
127         .CLKFX(),                    // DCM CLK synthesis out (M/D)
128         .CLKFX180(),                 // 180 degree CLK synthesis out
129         .LOCKED( phase_dcm_locked ), // DCM LOCK status output
130         .PSDONE(),                   // Dynamic phase adjust done output
131         .STATUS(),                   // 8-bit DCM status bits output
132         .CLKFB( write_clk ),         // DCM clock feedback
133         .CLKIN( read_clk ),          // Clock input (from IBUFG, BUFG or DCM)
134         .PSCLK( clk ),               // Dynamic phase adjust clock input
135         .PSEN( rot_event ),          // Dynamic phase adjust enable input
136         .PSINCDEC( rot_left ),       // Dynamic phase adjust increment/decrement
137         .RST( phase_dcm_reset )      // DCM asynchronous reset input
138 );
139
140 reg [3:0] reset_counter;
141 assign phase_dcm_reset = reset | (reset_counter != 0);
142
143 always @(posedge clk)
144 begin
145         if (reset) 
146                 reset_counter <= 1;
147         else begin
148                 if (dcm_fx_locked & (reset_counter != 0))
149                         reset_counter <= reset_counter + 1;
150         end
151 end
152
153
154 //----------------------------------------------------------------------------
155 // BUFG write clock
156 //----------------------------------------------------------------------------
157
158 BUFG bufg_write_clk (
159         .O(write_clk  ),          // Clock buffer output
160         .I(write_clk_u)           // Clock buffer input
161 );
162
163 BUFG bufg_write_clk90 (
164         .O(write_clk90  ),        // Clock buffer output
165         .I(write_clk90_u)         // Clock buffer input
166 );
167
168 //----------------------------------------------------------------------------
169 // LOCKED logic
170 //----------------------------------------------------------------------------
171 reg phase_dcm_locked_delayed;
172
173 always @(posedge write_clk)
174 begin
175         phase_dcm_locked_delayed <= phase_dcm_locked;
176 end
177
178 assign locked = ~reset & phase_dcm_locked_delayed;
179
180
181 endmodule