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$


All bank refresh.
Read with auto precharge.
Write with auto precharge.

Timing Constraints

Row Address Select/Strobe. A signal used to latch the row address.
Column Address Select/Strobe. A signal used to latch the column address.
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}$.
CAS (Read) Latency. It is the time between an internal read command and the availability of the first bit of output data.
Read Latency. The overall read latency as seen by the memory controller is equal to $AL + CL$.
CAS Write Latency. It is the time between an internal write command and the availability of the first bit of input data.
Write Latency. The overall write latency is equal to $AL + CWL$.
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.
Row Precharge time i.e. time to precharge/close a row.
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).
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.
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}$.
Read to Precharge i.e. minimum time between a read and precharge command.
Write Recovery time or write to precharge delay.
CAS to CAS Delay i.e. time between successive column addresses (to read/write data).
Read to Write delay.
Write to Read delay.
Refresh Cycle time i.e. time to refresh a row or a group of rows. Refresh leaves a row in precharged/closed state.
Four Activate Window.
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 {

//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];


  1. DRAM Timings a, b, c
  2. DRAM Operation
  3. Additive Latency