Skip to content

Latest commit

 

History

History
300 lines (243 loc) · 11 KB

File metadata and controls

300 lines (243 loc) · 11 KB

DRAM Controller Architecture Document

System Architecture

Overview

The DRAM controller implements a hierarchical, modular architecture that separates concerns into distinct functional units. Each module has a well-defined interface and single responsibility.

Architectural Patterns

1. Layered Architecture

┌─────────────────────────────────────────────┐
│         CPU Interface Layer                 │
│  (External communication with processor)    │
└─────────────────────────────────────────────┘
                    ▼
┌─────────────────────────────────────────────┐
│       Control Layer (FSM)                   │
│  (Operation sequencing and coordination)    │
└─────────────────────────────────────────────┘
                    ▼
┌─────────────────────────────────────────────┐
│     Utility Layer                           │
│  (Address decode, timing, refresh)          │
└─────────────────────────────────────────────┘
                    ▼
┌─────────────────────────────────────────────┐
│      DRAM Interface Layer                   │
│  (Physical signal generation)               │
└─────────────────────────────────────────────┘

2. Component Interaction Diagram

                    ┌──────────────┐
                    │   CPU        │
                    └──────┬───────┘
                           │
                ┌──────────▼──────────┐
                │  dram_controller    │
                │      _top           │
                └──────────┬──────────┘
                           │
         ┌─────────────────┼─────────────────┐
         │                 │                 │
    ┌────▼────┐      ┌─────▼─────┐    ┌─────▼─────┐
    │ Address │      │ Refresh   │    │  Timing   │
    │ Decoder │      │Controller │    │ Generator │
    └─────────┘      └───────────┘    └─────┬─────┘
                                             │
                           ┌─────────────────┘
                           │
                      ┌────▼────┐
                      │  DRAM   │
                      │   FSM   │
                      └────┬────┘
                           │
                    ┌──────▼────────┐
                    │   Command     │
                    │  Generator    │
                    └───────┬───────┘
                            │
                    ┌───────▼───────┐
                    │     DRAM      │
                    └───────────────┘

Data Flow

Read Operation Flow

  1. CPU asserts cpu_read_req with address
  2. Address Decoder splits address into row/column
  3. FSM latches address and operation type
  4. FSM transitions: IDLE → ACTIVATE → RCD_WAIT → READ_CAS → READ_WAIT → READ_DATA
  5. Command Generator asserts RAS, then CAS signals
  6. Timing Generator enforces tRCD and tCAS delays
  7. Data captured from DRAM and presented to CPU
  8. FSM → PRECHARGE → IDLE

Write Operation Flow

  1. CPU asserts cpu_write_req with address and data
  2. Address Decoder splits address
  3. FSM latches address, data, and operation type
  4. FSM transitions: IDLE → ACTIVATE → RCD_WAIT → WRITE_CAS → WRITE_DATA
  5. Command Generator asserts RAS, then CAS+WE signals
  6. Data driven onto DRAM bus
  7. Timing Generator enforces write hold time
  8. FSM → PRECHARGE → IDLE

Refresh Operation Flow

  1. Refresh Controller generates periodic refresh request
  2. FSM detects refresh_pending (higher priority than CPU requests)
  3. FSM transitions: IDLE → REFRESH
  4. Command Generator asserts RAS+CAS (auto-refresh command)
  5. Timing Generator enforces tREF delay
  6. FSM acknowledges refresh completion
  7. Refresh Controller increments row counter
  8. FSM → IDLE

Timing Diagram

Read Cycle Timing

CLK     ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
        ┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─

RAS_N   ──┐     ┌───────────────────────────
          └─────┘

CAS_N   ────────────┐     ┌───────────────
                    └─────┘

ADDR    ──<ROW>──────<COL>────────────────

DQ      ────────────────────────<DATA>────

State   IDLE ACT WAIT R_CAS R_WAT R_DAT PRE

Write Cycle Timing

CLK     ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
        ┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─

RAS_N   ──┐     ┌───────────────────────
          └─────┘

CAS_N   ────────────┐     ┌───────────
                    └─────┘

WE_N    ────────────┐     ┌───────────
                    └─────┘

ADDR    ──<ROW>──────<COL>────────────

DQ      ────────────────────<DATA>────

State   IDLE ACT WAIT W_CAS W_DAT PRE

State Machine Details

State Transition Table

Current State Condition Next State
IDLE refresh_pending REFRESH
IDLE cpu_read_req ACTIVATE
IDLE cpu_write_req ACTIVATE
ACTIVATE timing_done RCD_WAIT
RCD_WAIT timing_done & read READ_CAS
RCD_WAIT timing_done & write WRITE_CAS
READ_CAS timing_done READ_WAIT
READ_WAIT timing_done READ_DATA
READ_DATA always PRECHARGE
WRITE_CAS timing_done WRITE_DATA
WRITE_DATA timing_done PRECHARGE
PRECHARGE timing_done IDLE
REFRESH timing_done IDLE

Module Interfaces

address_decoder

Inputs:
  - cpu_addr[ROW+COL-1:0]  // Full address
  - latch_enable           // Latch signal

Outputs:
  - row_addr[ROW-1:0]      // Decomposed row
  - col_addr[COL-1:0]      // Decomposed column
  - row_addr_reg[ROW-1:0]  // Latched row
  - col_addr_reg[COL-1:0]  // Latched column

refresh_controller

Inputs:
  - refresh_ack            // Completion signal

Outputs:
  - refresh_pending        // Request flag
  - refresh_row[ROW-1:0]   // Row to refresh

timing_generator

Inputs:
  - timing_select[2:0]     // Which timing to load
  - load_timing            // Load trigger
  - count_enable           // Enable counting

Outputs:
  - timing_done            // Counter reached zero
  - counter_value[7:0]     // Current count

dram_fsm

Inputs:
  - cpu_read_req, cpu_write_req
  - refresh_pending
  - timing_done

Outputs:
  - cpu_ready, cpu_busy, cpu_data_valid
  - refresh_active, refresh_ack
  - timing_select, load_timing, count_enable
  - cmd_activate, cmd_read, cmd_write, etc.
  - latch_address, capture_read_data

dram_command_generator

Inputs:
  - fsm_state[3:0]
  - cmd_activate, cmd_read, cmd_write, etc.
  - row_addr, col_addr
  - write_data

Outputs:
  - dram_addr, dram_ras_n, dram_cas_n, etc.
  - dq_output_enable, dq_out

Design Decisions

1. Why Separate Address Decoder?

  • Reason: Address decomposition is a distinct function
  • Benefit: Can easily change address mapping scheme
  • Trade-off: Additional module complexity vs. clarity

2. Why Dedicated Refresh Controller?

  • Reason: Refresh is independent of read/write operations
  • Benefit: Easy to modify refresh algorithm
  • Trade-off: More modules vs. better separation of concerns

3. Why Timing Generator Module?

  • Reason: Timing is used by multiple operations
  • Benefit: Centralized timing management
  • Trade-off: Interface complexity vs. code reuse

4. Why Separate Command Generator?

  • Reason: DRAM signal generation is complex
  • Benefit: Isolates low-level DRAM protocol
  • Trade-off: More inter-module wiring vs. maintainability

Performance Characteristics

Latency Analysis

  • Read Latency: 1 (ACTIVATE) + tRCD + 1 (READ_CAS) + tCAS + 1 (READ_DATA) + tRP cycles

    • With defaults: 1 + 3 + 1 + 2 + 1 + 3 = 11 cycles
  • Write Latency: 1 (ACTIVATE) + tRCD + 1 (WRITE_CAS) + 2 (WRITE_DATA) + tRP cycles

    • With defaults: 1 + 3 + 1 + 2 + 3 = 10 cycles
  • Refresh Overhead: tREF cycles every REFRESH_INTERVAL cycles

    • With defaults: 8 cycles every 500 cycles = 1.6% overhead

Throughput

  • Maximum sustained read throughput: Clock_Freq / Read_Latency
  • Maximum sustained write throughput: Clock_Freq / Write_Latency

Verification Strategy

Unit Testing

Each module can be tested independently:

  • address_decoder: Verify address split correctness
  • refresh_controller: Verify periodic requests and row cycling
  • timing_generator: Verify countdown and timing accuracy
  • dram_fsm: Verify state transitions and outputs
  • dram_command_generator: Verify signal generation

Integration Testing

  • Full system test with behavioral DRAM model
  • Verify read/write data integrity
  • Verify refresh doesn't corrupt operations
  • Timing verification with waveform analysis

Scalability Considerations

Easy to Extend

  1. Multiple Banks: Add bank selection logic to address decoder
  2. Burst Mode: Extend FSM with burst states
  3. DDR Support: Modify command generator for DDR timing
  4. Power Management: Add power-down states to FSM

Configuration Flexibility

All key parameters are exposed at top level:

  • Address widths
  • Data width
  • All timing parameters
  • Refresh configuration

Document Version: 1.0
Last Updated: 2025-11-24