-
Notifications
You must be signed in to change notification settings - Fork 3
/
sdram_phase.v
153 lines (138 loc) · 6.21 KB
/
sdram_phase.v
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