Hardware Design: SIE
Sign in or create your account | Project List | Help
Hardware Design: SIE Git Source Tree
Root/
| 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 | // DCM phase shift control |
| 24 | output reg ps_ready, |
| 25 | input ps_up, |
| 26 | input ps_down |
| 27 | ); |
| 28 | |
| 29 | |
| 30 | //---------------------------------------------------------------------------- |
| 31 | // ~133 MHz DDR Clock generator |
| 32 | //---------------------------------------------------------------------------- |
| 33 | wire read_clk_u; |
| 34 | wire dcm_fx_locked; |
| 35 | |
| 36 | DCM #( |
| 37 | .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 |
| 38 | // 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0 |
| 39 | .CLKFX_DIVIDE(clk_divide), // Can be any integer from 1 to 32 |
| 40 | .CLKFX_MULTIPLY(clk_multiply), // Can be any integer from 2 to 32 |
| 41 | .CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature |
| 42 | .CLKIN_PERIOD(), // Specify period of input clock |
| 43 | .CLKOUT_PHASE_SHIFT("NONE"), // Specify phase shift of NONE, FIXED or VARIABLE |
| 44 | .CLK_FEEDBACK("NONE"), // Specify clock feedback of NONE, 1X or 2X |
| 45 | .DESKEW_ADJUST("SOURCE_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or |
| 46 | // an integer from 0 to 15 |
| 47 | .DFS_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for frequency synthesis |
| 48 | .DLL_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for DLL |
| 49 | .DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE |
| 50 | .FACTORY_JF(16'hC080), // FACTORY JF values |
| 51 | .PHASE_SHIFT(0), // Amount of fixed phase shift from -255 to 255 |
| 52 | .STARTUP_WAIT("FALSE") // Delay configuration DONE until DCM LOCK, TRUE/FALSE |
| 53 | ) dcm_fx ( |
| 54 | .DSSEN(), |
| 55 | .CLK0(), // 0 degree DCM CLK output |
| 56 | .CLK180(), // 180 degree DCM CLK output |
| 57 | .CLK270(), // 270 degree DCM CLK output |
| 58 | .CLK2X(), // 2X DCM CLK output |
| 59 | .CLK2X180(), // 2X, 180 degree DCM CLK out |
| 60 | .CLK90(), // 90 degree DCM CLK output |
| 61 | .CLKDV(), // Divided DCM CLK out (CLKDV_DIVIDE) |
| 62 | .CLKFX( read_clk_u ), // DCM CLK synthesis out (M/D) |
| 63 | .CLKFX180(), // 180 degree CLK synthesis out |
| 64 | .LOCKED( dcm_fx_locked), // DCM LOCK status output |
| 65 | .PSDONE(), // Dynamic phase adjust done output |
| 66 | .STATUS(), // 8-bit DCM status bits output |
| 67 | .CLKFB(), // DCM clock feedback |
| 68 | .CLKIN( clk ), // Clock input (from IBUFG, BUFG or DCM) |
| 69 | .PSCLK( gnd ), // Dynamic phase adjust clock input |
| 70 | .PSEN( gnd ), // Dynamic phase adjust enable input |
| 71 | .PSINCDEC( gnd ), // Dynamic phase adjust increment/decrement |
| 72 | .RST( reset ) // DCM asynchronous reset input |
| 73 | ); |
| 74 | |
| 75 | //---------------------------------------------------------------------------- |
| 76 | // BUFG read clock |
| 77 | //---------------------------------------------------------------------------- |
| 78 | BUFG bufg_fx_clk ( |
| 79 | .O(read_clk), // Clock buffer output |
| 80 | .I(read_clk_u) // Clock buffer input |
| 81 | ); |
| 82 | |
| 83 | //---------------------------------------------------------------------------- |
| 84 | // Phase shifted clock for write path |
| 85 | //---------------------------------------------------------------------------- |
| 86 | wire phase_dcm_reset; |
| 87 | wire phase_dcm_locked; |
| 88 | wire write_clk_u, write_clk90_u, write_clk180_u, write_clk270_u; |
| 89 | reg psen, psincdec; |
| 90 | wire psdone; |
| 91 | |
| 92 | DCM #( |
| 93 | .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 |
| 94 | // 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0 |
| 95 | .CLKFX_DIVIDE(2), // Can be any integer from 1 to 32 |
| 96 | .CLKFX_MULTIPLY(2), // Can be any integer from 2 to 32 |
| 97 | .CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature |
| 98 | .CLKIN_PERIOD(), // Specify period of input clock |
| 99 | .CLK_FEEDBACK("1X"), // Specify clock feedback of NONE, 1X or 2X |
| 100 | .DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or |
| 101 | // an integer from 0 to 15 |
| 102 | .DFS_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for frequency synthesis |
| 103 | .DLL_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for DLL |
| 104 | .DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE |
| 105 | .FACTORY_JF(16'hC080), // FACTORY JF values |
| 106 | .CLKOUT_PHASE_SHIFT("VARIABLE"), // Specify phase shift of NONE, FIXED or VARIABLE |
| 107 | .PHASE_SHIFT( phase_shift ), // Amount of fixed phase shift from -255 to 255 |
| 108 | .STARTUP_WAIT("FALSE") // Delay configuration DONE until DCM LOCK, TRUE/FALSE |
| 109 | ) dcm_phase ( |
| 110 | .DSSEN(), |
| 111 | .CLK0( write_clk_u ), // 0 degree DCM CLK output |
| 112 | .CLK90( write_clk90_u ), // 90 degree DCM CLK output |
| 113 | .CLK180( write_clk180_u ), // 180 degree DCM CLK output |
| 114 | .CLK270( write_clk270_u ), // 270 degree DCM CLK output |
| 115 | .CLK2X(), // 2X DCM CLK output |
| 116 | .CLK2X180(), // 2X, 180 degree DCM CLK out |
| 117 | .CLKDV(), // Divided DCM CLK out (CLKDV_DIVIDE) |
| 118 | .CLKFX(), // DCM CLK synthesis out (M/D) |
| 119 | .CLKFX180(), // 180 degree CLK synthesis out |
| 120 | .LOCKED( phase_dcm_locked ), // DCM LOCK status output |
| 121 | .STATUS(), // 8-bit DCM status bits output |
| 122 | .CLKFB( write_clk ), // DCM clock feedback |
| 123 | .CLKIN( read_clk ), // Clock input (from IBUFG, BUFG or DCM) |
| 124 | .PSCLK( clk ), // Dynamic phase adjust clock input |
| 125 | .PSEN( psen ), // Dynamic phase adjust enable input |
| 126 | .PSINCDEC( psincdec ), // Dynamic phase adjust increment/decrement |
| 127 | .PSDONE( psdone ), // Dynamic phase adjust done output |
| 128 | .RST( phase_dcm_reset ) // DCM asynchronous reset input |
| 129 | ); |
| 130 | |
| 131 | // delayed reset for phase shifting DCM |
| 132 | reg [3:0] reset_counter; |
| 133 | assign phase_dcm_reset = reset | (reset_counter != 0); |
| 134 | |
| 135 | always @(posedge clk) |
| 136 | begin |
| 137 | if (reset) |
| 138 | reset_counter <= 1; |
| 139 | else begin |
| 140 | if (dcm_fx_locked & (reset_counter != 0)) |
| 141 | reset_counter <= reset_counter + 1; |
| 142 | end |
| 143 | end |
| 144 | |
| 145 | //---------------------------------------------------------------------------- |
| 146 | // DCM phase shifting state machine |
| 147 | //---------------------------------------------------------------------------- |
| 148 | parameter s_init = 0; |
| 149 | parameter s_idle = 1; |
| 150 | parameter s_waitdone = 2; |
| 151 | parameter s_waitdone2= 3; |
| 152 | |
| 153 | reg [1:0] state; |
| 154 | |
| 155 | always @(posedge clk) |
| 156 | begin |
| 157 | if (reset) begin |
| 158 | state <= s_init; |
| 159 | psen <= 0; |
| 160 | ps_ready <= 0; |
| 161 | end else begin |
| 162 | case (state) |
| 163 | s_init: begin |
| 164 | if (phase_dcm_locked) begin |
| 165 | ps_ready <= 1; |
| 166 | state <= s_idle; |
| 167 | end |
| 168 | end |
| 169 | s_idle: begin |
| 170 | if (ps_up) begin |
| 171 | ps_ready <= 0; |
| 172 | psen <= 1; |
| 173 | psincdec <= 1; |
| 174 | state <= s_waitdone; |
| 175 | end else if (ps_down) begin |
| 176 | ps_ready <= 0; |
| 177 | psen <= 1; |
| 178 | psincdec <= 0; |
| 179 | state <= s_waitdone; |
| 180 | end |
| 181 | end |
| 182 | s_waitdone: begin |
| 183 | psen <= 0; |
| 184 | if (psdone) begin |
| 185 | state <= s_waitdone2; |
| 186 | end |
| 187 | end |
| 188 | s_waitdone2: begin |
| 189 | if (~ps_up && ~ps_down) begin |
| 190 | ps_ready <= 1; |
| 191 | state <= s_idle; |
| 192 | end |
| 193 | end |
| 194 | endcase |
| 195 | end |
| 196 | end |
| 197 | |
| 198 | //---------------------------------------------------------------------------- |
| 199 | // BUFG write clock |
| 200 | //---------------------------------------------------------------------------- |
| 201 | BUFG bufg_write_clk ( |
| 202 | .O(write_clk ), // Clock buffer output |
| 203 | .I(write_clk_u) // Clock buffer input |
| 204 | ); |
| 205 | |
| 206 | BUFG bufg_write_clk90 ( |
| 207 | .O(write_clk90 ), // Clock buffer output |
| 208 | .I(write_clk90_u) // Clock buffer input |
| 209 | ); |
| 210 | |
| 211 | //---------------------------------------------------------------------------- |
| 212 | // LOCKED logic |
| 213 | //---------------------------------------------------------------------------- |
| 214 | reg phase_dcm_locked_delayed; |
| 215 | |
| 216 | always @(posedge write_clk) |
| 217 | begin |
| 218 | phase_dcm_locked_delayed <= phase_dcm_locked; |
| 219 | end |
| 220 | |
| 221 | assign locked = ~reset & phase_dcm_locked_delayed; |
| 222 | |
| 223 | |
| 224 | endmodule |
| 225 |
Branches:
master
