Understanding and Implementing DRAM Timings

November 11, 2018

DRAM devices have more than a dozen commands e.g $READ$, $WRITE$, $REFRESH$, and more than two dozen timing constraints e.g. $t_{RC}$, $t_{RAS}$, $t_{RCD}$, for their correct operation. The timing constraints control intra-bank, inter-bank and inter-rank operation. Understanding these constraints can be challenging. In addition, implementing these constraints in a memory controller, in RTL or in a performance simulator, can be error prone.

It is easy to understand and implement the timing constraints if they are viewed as a matrix. The table below shows the intra-bank timing constraints. The table can be easily extended to include additional commands e.g. single bank refresh, power up, power down etc. Similar tables can be constructed for inter-bank and inter-rank constraints. There are a few power constraints e.g. $t_{TAW}$, $t_{FAW}$ which are not captured by this table but are required for correct operation.

$\def\lc{\left\lceil}$ $\def\rc{\right\rceil}$ $\def\na{\times}$

$From\ (To\rightarrow)$ $PRE$ $ACT$ $RD$ $WR$ $REF$ $RD\_AP$ $WR\_AP$
$PRE$ $t_{RP}$ $\na$ $\na$ $t_{RP}$ $\na$ $\na$
$ACT$ $t_{RAS}$ $t_{RC}$ $t_{RCD}$ $t_{RCD}$ $t_{RC}$ $t_{RCD}$ $t_{RCD}$
$RD$ $t_{RTP}$ $\na$ $t_{CCD}$ $t_{RTW}$ $\na$ $t_{CCD}$ $t_{RTW}$
$WR$ $\small{WL+\frac{BL}{2}+WR}$ $\na$ $t_{WTR}$ $t_{CCD}$ $\na$ $t_{WTR}$ $t_{CCD}$
$REF$ $t_{RFC}$ $\na$ $\na$ $t_{RFC}$ $\na$ $\na$
$RD\_AP$ $t_{RTP} + t_{RP}$ $\na$ $\na$ $t_{RTP} + t_{RP}$ $\na$ $\na$
$WR\_AP$ $\small{WL + \frac{BL}{2} + WR + t_{RP}}$ $\na$ $\na$ $\small{WL + \frac{BL}{2} + WR + t_{RP}}$ $\na$ $\na$

Commands

$PRE$
Precharge.
$ACT$
Activate.
$RD$
$WR$
Write.
$REF$
All bank refresh.
$RD\_AP$
$WR\_AP$
Write with auto precharge.

Timing Constraints

$RAS$
$CAS$
$AL$
Additive Latency. It was introduced in DDR2 [3] and allows the memory controller to issue a read or write command, after an activate command, but before $t_{RCD}$ has elapsed. An external read/write command (from the memory controller) becomes an internal read/write command after a delay of $AL$. This is called posted CAS i.e. posted read or write operation. Note that $AL$ can be zero (disabled) i.e. the minimum time between an activate and read or write command is $t_{RCD}$.
$CL$
CAS (Read) Latency. It is the time between an internal read command and the availability of the first bit of output data.
$RL$
Read Latency. The overall read latency as seen by the memory controller is equal to $AL + CL$.
$CWL$
CAS Write Latency. It is the time between an internal write command and the availability of the first bit of input data.
$WL$
Write Latency. The overall write latency is equal to $AL + CWL$.
$BL$
Burst Length. The number of clock edges (rising and falling) taken for data transfer e.g. 4 for DDR2, 8 for DDR3 and DDR4, 2 for HBM.
$t_{RP}$
Row Precharge time i.e. time to precharge/close a row.
$t_{RCD}$
RAS to CAS Delay i.e. time to activate/open a row i.e. time delay between sending a row address (to activate/open a row) and sending the first column address (to read/write data).
$t_{RAS}$
Row Active time i.e. activate to precharge delay. This includes the time to activate/open a row ($t_{RCD}$) and internally restore/refresh the row back into the array.
$t_{RC}$
Row Cycle time i.e. activate to activate delay. The minimum time between an activate and a precharge is $t_{RAS}$ and the time to precharge/close a row is $t_{RP}$. Therefore, $t_{RC} = t_{RAS} + t_{RP}$.
$t_{RTP}$
Read to Precharge i.e. minimum time between a read and precharge command.
$WR$
Write Recovery time or write to precharge delay.
$t_{CCD}$
CAS to CAS Delay i.e. time between successive column addresses (to read/write data).
$t_{RTW}$
$t_{WTR}$
$t_{RFC}$
Refresh Cycle time i.e. time to refresh a row or a group of rows. Refresh leaves a row in precharged/closed state.
$t_{FAW}$
Four Activate Window.
$t_{TAW}$
Two Activate Window.

Implementing Timing Constraints

The psuedo code below shows how the numerous timing constraints can be easily implemented in a performance simulator. This approach makes the code readable and error free.


//Declare an enum of commands
enum CMD {
PRE,
ACT,
RD,
WR,
REF,
RD_AP,
WR_AP,
MAX
};

//Declare and populate a timing matrix
int constraint[CMD::MAX][CMD::MAX];
constraint[PRE][ACT] = tRP;
constraint[PRE][REF] = tRP;
...

//Track when a command can be legally issued in the future
int next[CMD::MAX];

//Let the current command be a read command
CMD current = CMD::RD;

//Apply all constraints
for (int i = 0; i < CMD::MAX; i++) {
next[i] += constraint[current][i];
}


References

1. DRAM Timings a, b, c
2. DRAM Operation