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
| `timescale 1ps / 1ps // do not change
module fsl_ddr_eye_ctl (
output ck,
output addr_cmd,
output ctl,
output dm,
inout dq,
inout dqs
);
/****************************************************************************************
* Default values, in case something slips through undefined...
****************************************************************************************/
`ifndef tCK
`define tCK 1250
`endif
parameter tDQBit = `tCK / 2; // Data bit time
// Comment the following to use the "approximate" method
`define USE_EXACT_VALUES
// translated values (approx) // datasheet values
parameter tDDKHMH = (tDQBit < 580) ? 150 : (tDQBit < 688) ? 150 : (tDQBit < 791) ? 245 ; // straight from datasheet...
`ifdef USE_EXACT_VALUES
parameter tCISKEW = (tDQBit < 580) ? 93 : (tDQBit < 688) ? 112 : (tDQBit < 791) ? 125 ;
parameter tDDKHAS = (tDQBit < 580) ? 410 : (tDQBit < 688) ? 495 : (tDQBit < 791) ? 606 ;
parameter tDDKXDEYE = (tDQBit < 580) ? 350 : (tDQBit < 688) ? 400 : (tDQBit < 791) ? 500 ;
`else
parameter tCISKEW = 0.1800 * tDQBit; // @1333= 125
parameter tDDKHAS = 0.3900 * `tCK; // @1333= 606
parameter tDDKXDEYE = 0.6667 * tDQBit; // @1333= 500
`endif
integer CLK_ADJ = 10;
integer CNTL_ADJ = 0;
integer WR_DATA_DLY = 0;
/****************************************************************************************
* Derived timing parameters
****************************************************************************************/
parameter tACCSkew = `tCK/2 - tDDKHAS; // The raw tDDKHAS term assumes 1/2 tCK nominal shift
parameter tACCShift = CLK_ADJ * `tCK/16; // Base Addr/Cmd/Ctl to CK delay
parameter tACCDlyMin = -tACCShift - tACCSkew; // Delay from CK rising to Addr/Cmd/Ctl valid (min)
parameter tACCDlyMax = -tACCShift + tACCSkew; // Delay from CK rising to Addr/Cmd/Ctl valid (max)
parameter tCKCTLmin = tACCDlyMin; // CK rising out to earliest valid CTL (CK-1)
parameter tCKCTLmax = tACCDlyMax; // CK rising out to latest valid CTL (CK-1)
`ifdef ADDRCMD2T
parameter tCKACmin = tACCDlyMin - `tCK; // CK rising out to earliest valid Addr/Cmd (CK-2)
parameter tCKACmax = tACCDlyMax - `tCK; // CK rising out to latest valid Addr/Cmd (CK-2)
`else `define ADDRCMD1T
parameter tCKACmin = tACCDlyMin; // CK rising out to earliest valid Addr/Cmd (CK-1)
parameter tCKACmax = tACCDlyMax; // CK rising out to latest valid Addr/Cmd (CK-1)
`endif
parameter tDQPrelaunch = -tDQBit/2; // DQ to DQS pre-launch shift (Write to DRAM)
parameter tDQSDQQ = tDQBit/2 - tDDKXDEYE/2; // DQ output skew, relative to DQS
parameter tDQSDQmin = tDQPrelaunch - tDQSDQQ;
parameter tDQSDQmax = tDQPrelaunch + tDQSDQQ;
parameter tDQSShift = WR_DATA_DLY * `tCK/4; // Base Addr/Cmd/Ctl to DQS delay (write)
parameter tDQSDly = tDQSShift - tACCShift; // Base CK to DQS delay (write)
parameter tCKDQSmin = tDQSDly - tDDKHMH;
parameter tCKDQSmax = tDQSDly + tDDKHMH;
parameter tDISKEW = `tCK/4 - tCISKEW;
parameter tDS = tCISKEW;
parameter tDH = tCISKEW;
/****************************************************************************************
* Timing relationships
****************************************************************************************/
specify
// ADDR/CMD prelaunch window from next CK
$delay( posedge ck, addr_cmd, tCKACmin, tCKACmax);
// CTL prelaunch window from next CK (1T always)
$delay( posedge ck, ctl, tCKCTLmin, tCKCTLmax);
// DRAM Write cycles
$delay(ck, dqs, tCKDQSmin, tCKDQSmax);
$delay(dqs, dq, tDQSDQmin, tDQSDQmax);
$delay(dqs, dm, tDQSDQmin, tDQSDQmax);
// DRAM Read cycles
$setuphold(dqs, dq, tDS, tDH);
endspecify
endmodule |