sdram_phase.v 6.21 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
/*
** -----------------------------------------------------------------------------**
** sdram_phase.v
**
** I/O pads related circuitry
**
** Copyright (C) 2002 Elphel, Inc
**
** -----------------------------------------------------------------------------**
**  This file is part of X333
**  X333 is free software - hardware description language (HDL) code.
** 
**  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/>.
** -----------------------------------------------------------------------------**
**
** $Log: sdram_phase.v,v $
** Revision 1.5  2010/05/14 18:48:35  dzhimiev
** 1. added hacts shifts for buffered channels
** 2. set fixed SDRAM spaces
**
** Revision 1.1  2009/06/11 17:39:00  dzhimiev
** new initial version
** 1. simulation and board test availability
**
** Revision 1.1  2008/12/08 09:07:57  dzhimiev
** 1. set up of the data path for the transform
** 2. 2 read and 2 write channels
** 3. in snapshot mode - 3 frames output sequence -
**   1st - direct
**   2nd - stored 'direct' from the 1st buffer
**   3rd - stored '1st buffer' from the 2nd buffer
**
** Revision 1.1  2008/04/23 01:55:49  dzhimiev
** 1. added x359 files to src lists
** 2. x359 read/write DDR
** 3. x359 3 channels mux directly to out
** 4. x359 one channel through DDR and another directly frames switching at out
**
*/

// assumed CL=2.5

`timescale 1 ns / 1 ps

module sdram_phase (// wclk,       // global CPU WE pulse
							clk,
                     pre_wcmd,   // decoded address - enables wclk
                     wd,         // CPU write data [1:0]
                                 //       0 - nop, just reset status data
                                 //       1 - increase phase shift
                                 //       2 - decrease phase shift
                                 //       3 - reset phase shift to default (preprogrammed in FPGA configuration)
                                 //       c - reset phase90
                                 //       4 - incr pahse90
                                 //       8 - decrease phase90
                     ph_err,     // [1:0] 0 - no data (SDRAM reads) since last change (wclk*wcmd)
                                 //       1 - clock is too late
                                 //       2 - clock is too early
                                 //       3 - OK (some measurements show too late, some - too early)
                     sclk0,      // global clock, phase 0
/*                     sclk90,     // global clock, phase 0 */
                     sclk270,    // global clock, phase 0
                     enrd180,    // read enable, latency 2 from the command, sync with sclk falling edge
                     udqsr90,    // data from SDRAM interface pin UDQS strobed at rising sclk90
                     ldqsr90,    // data from SDRAM interface pin LDQS strobed at rising sclk90
                     udqsr270,   // data from SDRAM interface pin UDQS strobed at rising sclk270
                     ldqsr270,   // data from SDRAM interface pin UDQS strobed at rising sclk270
                     dcm_rst,    // set DCM phase to default
                     dcm_clk,    // clock for changing DCM phase (now == sclk0)
                     dcm_en,     // enable inc/dec of the DCM phase
                     dcm_incdec, // 0 - increment, 1 - decrement DCM phase
                     phase90sel  // add phase 0 - 0, 1 - 90, 2 - 180, 3 - 270

                     );
							
	input         clk;
   input         pre_wcmd;
   input  [ 3:0] wd;
   output [ 1:0] ph_err;
   input         sclk0, /*sclk90, */sclk270;
   input         enrd180;
   input         udqsr90, udqsr270, ldqsr90, ldqsr270;
   output        dcm_rst, dcm_clk, dcm_en, dcm_incdec;
   output [ 1:0] phase90sel;
//	reg           wcmd;
	wire          wcmd = pre_wcmd;
   reg    [ 1:0] phase90sel=2'b0;
   reg dcm_rst;
   reg [1:0] dcm_drst;
   reg       dcm_en;
   reg       dcm_incdec; 


   reg           enrd0, enrd180_d,enrd90,enrd270;
   reg           waslate90, waslate270, wasearly90, wasearly270;
// generate control pulses from CPU command

  always @ (negedge clk) begin
//    wcmd   <=pre_wcmd;
    dcm_drst[1:0] <= {dcm_drst[0], (wcmd && (wd[1:0] == 2'b11))};
    dcm_rst    <= (wcmd && (wd[1:0] == 2'b11)) || dcm_drst[0]  || dcm_drst[1] ;
    dcm_en     <= wcmd && (wd[1]!=wd[0]);
    dcm_incdec <= wcmd && wd[0]; 
    if      (wcmd && wd[2] && wd[3]) phase90sel[1:0] <= 2'h0;
    else if (wcmd && wd[2]) phase90sel[1:0] <= phase90sel[1:0] +1;
    else if (wcmd && wd[3]) phase90sel[1:0] <= phase90sel[1:0] -1;
  end



// DCM control outputs (use automatic adjustment later?) 
//   assign  dcm_clk=sclk0;
   assign  dcm_clk=!clk;//!sclk0; // DCM is triggered by posedge

// generate phase error signals

   always @ (posedge sclk0)   enrd0     <= enrd180;
   always @ (negedge sclk0)   enrd180_d <= enrd180;
//   always @ (posedge sclk90)  enrd90    <= enrd180_d;
   always @ (negedge sclk270)  enrd90    <= enrd180_d;
   always @ (posedge sclk270) enrd270   <= enrd0;
//   always @ (posedge sclk90 or posedge wcmd)
   always @ (negedge sclk270 or posedge wcmd)
     if (wcmd) begin
       waslate90  <= 1'b0;
       wasearly90 <= 1'b0;
     end else begin
       waslate90  <= waslate90  || (enrd90 && ( udqsr90 ||  ldqsr90));
       wasearly90 <= wasearly90 || (enrd90 && (!udqsr90 || !ldqsr90));
     end
   always @ (posedge sclk270 or posedge wcmd)
     if (wcmd) begin
       waslate270  <= 1'b0;
       wasearly270 <= 1'b0;
     end else begin
       waslate270  <= waslate270  || (enrd270 && (!udqsr270 || !ldqsr270));
       wasearly270 <= wasearly270 || (enrd270 && ( udqsr270 ||  ldqsr270));
     end

     assign ph_err[1:0]= {(wasearly90 || wasearly270), (waslate90 || waslate270)};

endmodule