DDR · Module 30
tRCD Question
Earliest legal time is a maximum over every applicable rule, so one parameter yields a lower bound. The same timing sentence has three readings differing by one cycle, and a conservative checker violates nothing while costing bandwidth.
What does tRCD stand for is acronym expansion and tells an interviewer nothing. The real question hands you a cycle number and asks when the next command may legally issue — and the correct answer usually begins by saying what information is still missing.
The reason is structural. Chapter 13.3 owns the derivation of earliest legal time as a maximum: a command is legal when it satisfies every applicable constraint, so the earliest legal issue time is the maximum over all of them. A single parameter therefore never determines a legal issue time on its own — it contributes one candidate to a maximum.
A candidate who answers N + tRCD immediately has answered a different, easier question.
1. What the Question Actually Asks
The question, in the form it is usually posed:
An
ACTwas issued at cycle 100. When may the firstREADlegally issue?
What a weak answer says: 100 + tRCD.
What is wrong with it is not the arithmetic — it is the confidence. That expression is the answer to what does tRCD constrain, which is a different question. The question asked was when a command may legally issue, and that requires knowing every constraint in force.
The four things a strong answer establishes before producing a number:
| Required | Why | Owner |
|---|---|---|
Which resource the READ targets | a constraint applies to a pair on a shared resource | 13.3 |
| Whether that resource has other recent commands | earliest legal is a maximum over all applicable rules | 13.3 |
| The boundary convention for the parameter | the same sentence has three readings — §5 | 28.2 §10 |
| The generation and configuration | some rules exist only with certain organisations | 14.6 |
So the honest opening is a question, not a number, and asking it is not evasion — it is the first step of the reconstruction.
2. The Reconstruction Discipline
CURRICULUM-DERIVED from 28.2 §3, which owns the six fields that localise a timing violation. The same six fields answer a legality question, run forwards instead of backwards.
| Field | For the interview question |
|---|---|
| 1. The command in question | the READ |
| 2. The previous relevant command on the same resource | the ACT — and anything else |
| 3. Resource identity of both | same bank? same bank group? |
| 4. Required separation | tRCD — and every other applicable rule |
| 5. Elapsed separation | measured between commits |
| 6. The binding rule | the maximum, not the first one you thought of |
Field 2 is where the interview is won or lost, because the question deliberately mentions only one previous command. A candidate who assumes the ACT is the only relevant predecessor has accepted the question's framing rather than reconstructing the state.
Field 5 matters even in a question with no controller in it. Chapter 17.1 owns the commit point — the single instant architectural state may change — and timing is measured between commits, not requests. In an interview this usually surfaces as a trap: if the question says "a read was requested at cycle 103", that is not an issue event.
3. Working the Question Properly
Q1. An ACT to bank 5 row R was committed at cycle 100. When may the first READ to bank 5 legally issue?
Step 1 — state the model. A column command to a bank requires the row to be open, and the row is not usable until tRCD after the activate. Chapter 14.1 owns that parameter.
Step 2 — state what is missing and why it matters.
what I still need, and what each changes
the tRCD VALUE for this device and speed bin
-> without it the answer is symbolic, which is fine
the BOUNDARY CONVENTION
-> changes the answer by exactly 1 cycle (§5)
whether any OTHER command to bank 5 is recent
-> a tRAS or tRC obligation could bind later
whether a column command to ANOTHER bank in the same
bank group was recent
-> column spacing is a SHARED-resource rule (14.6),
so it can bind even though the ACT was to bank 5
whether a refresh is due
-> 17.3's manager may drain traffic first
the DDR generation and organisation
-> whether a group-dependent rule applies at allStep 3 — give the symbolic answer with the convention stated.
DERIVED, ILLUSTRATIVE tRCD = 14, and stating the convention explicitly as the second command may issue on cycle a + tRCD:
earliest legal READ = max over applicable rules
from the ACT at 100, tRCD : 100 + 14 = 114
from any prior column command in
the same bank group, tCCD_L : depends -- unknown
from any prior column command in
a different group, tCCD_S : depends -- unknown
from read/write turnaround if the
previous column op was a WRITE : depends -- unknown
with ONLY the ACT known: earliest legal READ = cycle 114.
and the honest qualification: 114 is a LOWER BOUND on the
earliest legal issue time. Any additional constraint can only
push it LATER, never earlier -- because the earliest legal time
is a maximum.That final sentence is the strongest thing in the answer. It converts I don't know into a direction: with incomplete information the computed value is a lower bound, and the missing constraints can only delay. A candidate who says that has demonstrated they understand the maximum structure rather than reciting it.
Q2 (follow-up). Now I tell you a READ to bank 3 — a different bank in the same bank group — was committed at cycle 108. Does your answer change?
Possibly, and the reasoning is the interesting part.
CURRICULUM-DERIVED from 14.6, which owns column-to-column spacing as a shared-resource obligation and the same-group / different-group split with explicit generation labelling: two column commands in the same bank group are separated by the longer rule.
DERIVED, ILLUSTRATIVE tCCD_L = 8:
two candidates now:
tRCD from the ACT at 100 : 114
tCCD_L from the READ at 108 : 108 + 8 = 116
earliest legal = max(114, 116) = 116
so the binding constraint is NOT the one the question named.And the qualification that must accompany it: the same-group rule exists only on devices with that organisation. Chapter 14.6 labels its split with the generation for exactly this reason. So the complete answer is conditional: 116 if this device has bank groups and both accesses are in the same one; 114 if there is no group-dependent rule, subject to the shorter spacing.
This is the question's real purpose. It checks whether you know that a column command to a different bank can constrain a column command to your bank — which is 14.6's scope argument for why per-bank state fails, and the single most common gap in timing answers.
Q3 (removing an assumption). Everything so far treated tRCD as a number of clock cycles. Is it?
Not necessarily, and this is the question that separates levels.
CURRICULUM-DERIVED from 14.7, which owns the max(nCK, ns) dual-term form: some timing requirements are specified as the larger of a cycle count and an absolute time. The cycle count is a protocol floor; the absolute time is the physics.
Why that changes the answer structurally:
a parameter given as max(nCK_min, t_ns) must be CONVERTED
before it can be compared against a cycle counter:
cycles_required = max( nCK_min,
ceil( t_ns / t_CK ) )
and t_CK is the CLOCK PERIOD, which is a property of the
operating point -- not of the parameter.
consequence: the SAME parameter yields a DIFFERENT cycle
count at a different frequency. The absolute time is fixed;
the number of cycles it spans is not.DERIVED, ILLUSTRATIVE: a requirement of max(4 nCK, 5 ns).
ILLUSTRATIVE t_CK | ceil(5 / t_CK) | Required cycles | Which term binds |
|---|---|---|---|
| 1.25 ns | 4 | 4 | tie — both |
| 0.625 ns | 8 | 8 | the absolute-time term |
| 2.5 ns | 2 | 4 | the cycle-count term |
Two results a strong candidate states:
First, the rounding direction is not free. ceil is the only safe choice for a minimum separation — floor produces a cycle count shorter than the physics requires, which is §5's asymmetry again at a different layer. Rounding a minimum down is a correctness failure; rounding it up costs bandwidth.
Second, which term binds moves with frequency. At a slow clock the protocol floor dominates and the requirement looks like a constant cycle count; at a fast clock the physical time dominates and the cycle count grows. A candidate who has only ever seen one operating point will report the parameter as a constant and be confidently wrong at the next speed bin.
And the interview trap built on this: does running the memory faster reduce latency? Not for any obligation expressed in absolute time — the cycle count simply grows to cover the same nanoseconds. Chapter 30.4 is entirely this observation applied to CL.
Q4 (removing another assumption). The bank is eligible and no timing rule blocks the READ. Is it definitely going to issue?
No — legality is necessary, not sufficient, and conflating the two is the most common structural error in scheduling answers.
CURRICULUM-DERIVED from 17.1, which owns the distinction between a candidate and a committed command, and from 17.3: a refresh obligation can outrank every pending read regardless of their legality.
| Reason a legal command still does not issue | Owner |
|---|---|
| The command bus already carries another command this cycle | 17.1 |
| The manager is draining ahead of a refresh, so no new row opens (policy) | 17.3 |
| The device is occupied by a refresh, in which case the command is not deferred but illegal | 17.3 §2 |
| Arbitration chose a different, also-legal candidate | 17.4 |
| A power state must be exited first | 6.2 |
Rows two and three differ in kind, and 17.3 §2 owns the difference. During the drain the command is legal and merely not chosen — a policy outcome. During refresh occupancy it is not a candidate at all, because normal commands are illegal while the device is occupied. So a refresh does not "outrank" a read; for part of the window it removes the read from the legal set entirely — which is why 17.3 argues refresh cannot be modelled as a high-priority request.
So the complete answer to "when may the first READ legally issue" ends with a qualification: that time is when the command becomes legal. When it actually issues is a scheduling question, and the gap between the two is where controller performance lives.
This is worth saying unprompted, because it shows the candidate holds the same separation 30.5 is built on: which requests are legal is answered before which should issue, and the two are never merged.
4. The Same Question Backwards
Q5. A READ was committed at cycle 112 and a violation was reported. Which rule, and what do you need to know?
Running the reconstruction in reverse is 28.2's subject, and interviewers use it because it cannot be answered by recall at all.
| Step | For this trace |
|---|---|
| Previous command on the same resource | the ACT at 100 — and the READ at 108 to the same group |
| Required separations | tRCD = 14 → 114; tCCD_L = 8 → 116 |
| Observed separation | issued at 112 |
| Rules violated | both — short by 2 against tRCD, by 4 against tCCD_L |
| Binding rule | tCCD_L — the maximum |
The critical observation: a checker reporting only tRCD understates the violation by 2 cycles and names the wrong rule. Chapter 28.2 §4 owns this: a report naming one rule may be hiding a worse one, which is why a violation snapshot should record a rule mask rather than a rule identifier.
Follow-up: what if every violation you see is short by exactly one cycle? Then the defect is almost certainly a shared boundary convention rather than many parameter errors — §5, and 28.2 §9 owns it. One cause, not nine.
5. The Boundary Convention — Where the Off-by-One Lives
The most common wrong answer to a timing question is off by one, and it is not carelessness. The sentence "at least N cycles between two commands" has three defensible readings.
CURRICULUM-DERIVED from 28.2 §10 and 13.3's countdown-versus-timestamp choice:
| Reading | Legal when | N = 14, a = 100: earliest |
|---|---|---|
| Cycles between the commands | b − a − 1 ≥ N | 115 |
| Cycles from the first to the second | b − a ≥ N | 114 |
The second may issue on a + N | b ≥ a + N | 114 |
Readings two and three agree; reading one differs by one. So the correct interview behaviour is to state which convention you are using before producing a number — and a candidate who does that cannot be wrong, because the interviewer can only correct the convention rather than the arithmetic.
Why the ambiguity is real rather than pedantic. Chapter 13.3 owns the countdown-versus-timestamp representation choice, and the two fail this differently: a countdown loaded on the issue cycle permits issue at a + N, while one loaded the cycle after permits a + N + 1. A one-line implementation difference with a one-cycle consequence, and §7's RTL is exactly that bug.
And the direction matters asymmetrically. A minimum requirement rounded or counted the short way produces a separation the device does not permit — a correctness failure. Counted the long way it merely costs bandwidth. So when unsure, the safe engineering choice and the safe interview answer are the same: take the longer reading and say you did.
6. One Command Sequence, Two Binding Constraints
The two history queries are the point. A design with only the per-bank structure computes 114 and issues an illegal command. CURRICULUM-DERIVED from 14.6, which owns the scope argument for why per-bank state fails — and this diagram is that argument in one picture.
And the last message is the commit. Timing is measured between commits, so the commit is what both structures record — 17.1's commit point, and §2's field 5.
7. RTL Review — A Timing Eligibility Tracker
The intended contract:
- For each bank, record the cycle at which the most recent
ACTwas committed. - A column command to a bank is eligible when at least
TRCDcycles have elapsed since thatACT, using the convention that the column command may issue on cycleact_cycle + TRCD. - Before any
ACTto a bank, no column command to that bank is eligible. - The elapsed measure must not wrap; a long idle period must remain eligible.
// ---------------------------------------------------------------------
// trcd_eligibility -- INTENTIONALLY DEFECTIVE, for review (§7).
//
// CLASSIFICATION: synthesisable, ILLUSTRATIVE, and CONTAINS A BUG.
//
// WHAT IT IS MEANT TO DO: the four-clause contract above -- per-bank
// row-to-column eligibility under a STATED boundary convention.
//
// WHY IT EXISTS HERE: §5 establishes that the same timing sentence has
// three readings differing by one cycle, and 13.3 owns the
// countdown-versus-timestamp choice that makes the difference a
// one-line implementation detail. This block is that one line, wrong.
//
// HOW TO RUN IT: commit an ACT, then present a column command at
// exactly act_cycle + TRCD.
// EXPECTED RESULT under clause 2: eligible.
// EXPECTED TRACE: `eligible` must be high on the cycle
// act_cycle + TRCD, not one cycle later.
//
// SYNTHESIS: one saturating counter per bank. No memory.
// LIMITATIONS: models tRCD ONLY. A real eligibility check takes the
// MAXIMUM over every applicable rule (§3, 13.3), and this block
// deliberately implements one candidate so the convention bug is
// visible in isolation.
// ---------------------------------------------------------------------
module trcd_eligibility #(
parameter int BANKS = 16,
parameter int TRCD = 14, // ILLUSTRATIVE
parameter int CNT_W = 8
)(
input logic clk,
input logic rst_n,
input logic act_commit,
input logic [$clog2(BANKS)-1:0] act_bank,
input logic [$clog2(BANKS)-1:0] q_bank,
output logic eligible
);
initial begin
if (BANKS < 2) $fatal(1, "trcd_eligibility: BANKS must be >= 2 (got %0d)", BANKS);
if (TRCD < 1) $fatal(1, "trcd_eligibility: TRCD must be >= 1");
// The counter must REPRESENT TRCD, so it needs $clog2(TRCD+1)
// bits -- COUNT versus INDEX. Too narrow and it saturates below
// the threshold, making everything permanently ineligible.
if (CNT_W < $clog2(TRCD + 1))
$fatal(1, "trcd_eligibility: CNT_W too narrow for TRCD");
end
logic [CNT_W-1:0] since_act [BANKS];
logic seen_act [BANKS];
always_ff @(posedge clk) begin
if (!rst_n) begin
for (int b = 0; b < BANKS; b++) begin
since_act[b] <= '0;
seen_act[b] <= 1'b0;
end
end else begin
// Age every bank, saturating -- clause 4.
for (int b = 0; b < BANKS; b++)
if (seen_act[b] && since_act[b] != {CNT_W{1'b1}})
since_act[b] <= since_act[b] + 1'b1;
// An ACT restarts this bank's counter.
if (act_commit) begin
since_act[act_bank] <= '0;
seen_act[act_bank] <= 1'b1;
end
end
end
// Eligibility.
assign eligible = seen_act[q_bank] && (since_act[q_bank] > TRCD);
endmoduleBefore reading on: which clause, what trace, and would the resulting design be too permissive or too strict?
8. The Defect, and Which Direction It Fails
The violated clause is 2, and the defect is the comparison operator: > where the stated convention requires >=.
The trace that exposes it:
ILLUSTRATIVE TRCD = 14. ACT to bank 5 committed at cycle 100.
cycle 100 act_commit; since_act[5] <= 0
cycle 101 since_act[5] = 1
...
cycle 114 since_act[5] = 14
contract clause 2 : ELIGIBLE (may issue on a+TRCD)
this code : 14 > 14 is FALSE -> NOT eligible
cycle 115 since_act[5] = 15
this code : eligible
so the block is ONE CYCLE TOO STRICT.The direction matters and it is the good direction. A too-strict eligibility check delays a legal command, which costs bandwidth and violates nothing. A too-permissive one issues an illegal command, which is a correctness failure.
So this bug is a performance defect, not a correctness defect — and that is exactly why it survives. It produces no assertion failure, no data error and no protocol violation. It shows up as bandwidth a few per cent below expectation, attributed to the workload.
The corrected line, with the convention written where a reader can see it:
// CORRECTED. Clause 2's convention is "may issue ON act_cycle +
// TRCD", so the comparison is >=. §5: the same sentence has three
// readings and the implementation must name the one it uses --
// which is why the convention is in this comment and not only in a
// specification somewhere else.
//
// Note the asymmetry (§5): choosing > instead of >= is one cycle
// too STRICT, which costs bandwidth. Choosing >= when the device
// means "between" would be one cycle too PERMISSIVE, which is a
// correctness failure. When the convention is uncertain, the safe
// direction is the stricter one.
assign eligible = seen_act[q_bank] && (since_act[q_bank] >= TRCD);An interviewer's likely follow-up: how would you have caught this? Not with an assertion — a too-strict check violates nothing. The catch is a coverage question: cover the case since_act == TRCD with a column command presented, and check that eligible was high. A property proves illegality did not happen; only a cover proves the boundary was exercised at all — which is §9's subject.
9. SVA Review — Proving Legality Versus Proving Tightness
A property offered as proof that the eligibility logic is correct:
// Offered as "proves tRCD is respected".
property p_no_early_column;
@(posedge clk) disable iff (!rst_n)
(col_commit && col_bank == q_bank) |-> eligible;
endproperty
assert property (p_no_early_column)
else $error("column command issued while ineligible");Q. This property passes on the defective code in §7. Why is the design still wrong?
Because it proves a one-sided contract. The property says nothing issues while ineligible — a safety property. The defect makes the block more ineligible than it should be, which satisfies safety perfectly.
A too-strict design passes every safety property about timing. This is the general shape and it is worth carrying: safety properties cannot detect conservatism. They constrain what must not happen, and being slow does not happen-wrongly.
What would catch it:
// The boundary, covered rather than asserted. A property cannot
// require the design to be FAST; it can only require that the
// interesting case was exercised, and then a directed check
// compares against the expected boundary.
cover property (@(posedge clk) disable iff (!rst_n)
seen_act[q_bank] && since_act[q_bank] == TRCD);
// And the tightness check, written as a property only because the
// convention is STATED in the contract. Without a stated
// convention this property would be asserting a choice rather than
// a requirement -- which is §5's point in verification form.
property p_eligible_exactly_at_boundary;
@(posedge clk) disable iff (!rst_n)
(seen_act[q_bank] && since_act[q_bank] == TRCD) |-> eligible;
endproperty
assert property (p_eligible_exactly_at_boundary)
else $error("not eligible at the stated boundary act+TRCD");The second property is legitimate only because clause 2 stated the convention. Without it, asserting eligibility at exactly a + TRCD would be encoding one of §5's three readings as though it were the requirement — and an interviewer who notices that distinction is testing whether you know the difference between a specification and an implementation choice.
Follow-up: could a single property prove both directions? Yes in principle, and it would then be asserting an exact boundary — which is only sound when the boundary is normative. For a parameter whose convention is genuinely ambiguous in the source specification, the honest verification is a cover plus a documented convention, not an assertion.
10. What Would You Measure?
Q. You suspect a timing-convention bug. What do you instrument?
| Field | What it distinguishes |
|---|---|
| The shortfall distribution of every violation | all ones means a convention; a spread means parameters or classification — 28.2 §10 |
| The rule mask per violation, not a rule id | §4 — a report naming one rule can hide a worse one |
| Resource identity of both commands | whether the scope classification was right — 14.6 |
| The applied parameter read back from the register | the provenance chain — 28.2 §11 |
A cover on elapsed == required | whether the boundary was ever exercised — §9 |
| Bandwidth against a model, per rule | a too-strict check, which no violation counter shows |
Row six is the senior answer. A conservative eligibility check produces zero violations and slightly low bandwidth. No violation-based instrument can find it, and the only detector is comparing achieved spacing against the expected minimum — which means logging the actual separation of legal commands, not just the illegal ones.
And row one is the cheapest. If every shortfall is exactly one cycle across every rule, stop looking for nine bugs. There is one, and it is a convention.
11. Common Wrong Answers
“tRCD is RAS-to-CAS delay.” True and insufficient — it is the answer to a question nobody useful asks. §1: the question is when a command may legally issue.
“The read may issue at N + tRCD.” §1, §3. That is one candidate in a maximum. Any other applicable rule can only push it later.
“Only commands to the same bank matter.” §3 Q2. Column spacing is a shared-resource rule — 14.6 owns why per-bank state fails — so a column command to a different bank can bind.
“The answer is 114.” §5. Not without stating the boundary convention, because three readings of the same sentence give 114 or 115.
“A violation report names the rule that was broken.” §4. It names the rule the checker evaluated. The binding rule is the maximum, and several can fail at once.
“Timing is measured from when the request arrived.” §2. From the commit — 17.1 owns the commit point as the only instant architectural state changes.
“Every violation is short by one, so there are several small bugs.” §4, §10. A uniform one-cycle shortfall is one shared convention error.
“The safety property proves the timing logic is correct.” §9. It proves nothing issued early. A one-cycle-too-strict design satisfies it perfectly.
“A timing parameter is a number of clock cycles.” §3 Q3. Some are max(nCK, ns), so the required cycle count depends on the clock period — and which term binds moves with frequency.
“Running the DRAM faster shortens every timing obligation.” §3 Q3. Not one expressed in absolute time; the cycle count grows to span the same nanoseconds. 30.4 is this result applied to CL.
“If it is legal, it will issue.” §3 Q4. Legality is necessary, not sufficient — the bus, a refresh obligation, arbitration or a power state can all defer a perfectly legal command.
“I'll quote the real tRCD value for a DDR4-3200 part.” Do not, and the instinct to avoid it is correct rather than a gap. Parameter values are per-device and per-speed-bin, they belong to a datasheet, and a remembered number is more likely wrong than useful. Saying "symbolically, tRCD; the value comes from the part's datasheet and speed bin" is the stronger answer.
12. Self-Check
-
Given only an
ACTat cyclea, write the earliest legal column-command time as an expression, and state in one sentence why it is a lower bound rather than the answer. -
Add a column command to another bank in the same group and recompute. State which rule binds and the one configuration fact that would remove it.
-
Write the three boundary readings from §5 and the timestamp comparison each implies. Say which two agree.
-
Find the defect in §7 without reading §8. State whether it is too strict or too permissive and which failure mode follows.
-
Explain why §9's safety property cannot detect conservatism, and design the cover plus check that can.
-
A requirement is
max(4 nCK, 5 ns). Give the required cycle count att_CKof 1.25 ns and of 0.5 ns, and say which term binds in each. Then state whyceilrather thanflooris the only safe rounding. -
Name three reasons a command that is legal this cycle nevertheless does not issue, and say which chapter owns each.
-
A violation report shows
tCCD_Sshort by 2. Give the reason this may understate the problem, and name the field that would settle it.
13. Where This Goes
A timing question is a reconstruction, not a lookup. Earliest legal time is a maximum over every applicable rule, so one parameter yields a lower bound; the previous relevant command may be to a different bank; timing is measured between commits; the same timing sentence has three readings differing by one cycle; and a conservative check violates nothing while costing bandwidth.
Three results carry forward. State the convention before the number — it makes the arithmetic uncorrectable. A uniform one-cycle shortfall is one bug, not many. And safety properties cannot detect conservatism, which is the SVA-review pattern 30.9 develops into a method.
Chapter 30.4 takes the neighbouring parameter, and it fails differently. tRCD governs when a command may issue; CL governs when data appears — and the two are constantly conflated. The question that exposes it is whether increasing CL makes the memory slower, which sounds like it has an obvious answer and does not, because CL is measured in clocks and the clock period is the other half of every latency.
Continue learning
Related tutorials
- Related topic
Why Timing Parameters Exist
A DDR command can be perfectly meaningful and target a bank in exactly the right state and still be illegal right now. That third refusal is what timing parameters are, and it is a different question from the first two.
- Related topic
tRCD — RAS-to-CAS Delay
An accepted ACTIVATE constrains the earliest column command to that bank. It is a minimum separation, it is bank-local, and it is published in nanoseconds — three facts that between them explain most tRCD bugs.
- Related topic
Controller-Scheduling Question
Whiteboard a scheduler. The failure is collapsing request, candidate, grant and committed command into one thing — and the interviewer's next three additions expose it. Includes a fairness fix that issues illegal commands.
- Related topic
Device Physics Behind Timing
The array's processes take absolute time and know nothing about any clock. A controller counts cycles. Converting between them is where a physical duration becomes a digital obligation — and where the same device needs more cycles the faster you run it.
Standards & specifications
- Governing standard
- JEDEC JESD79 (DDR SDRAM)(opens JEDEC Solid State Technology Association in a new tab)
Defines the DDR SDRAM device itself — signals, command encoding, mode registers, timing parameters and the initialisation sequence — one document per generation. Memory-controller microarchitecture, address-mapping policy, PHY training algorithms and board-level design are not specified by it.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the DDR curriculum.
