DRAM 메모리 시스템 구조와 개요

DRAM Memory System Architecture and Overview

 

Introduction

현대 메모리 시스템은 주로 DRAM 이루어져 있으며, 메모리 시스템의 중요성이 날로 커져가고 있다. 이전까지는 연산기 즉, CPU의 성능을 올리는데 다양한 연구들이 진행되어 왔는데, 그 동안 메모리의 성능은 그렇게 발전하지 못했다(정확히는, DRAM의 Capacity & Bandwidth는 계속 발전하는 반면, Latency는 크게 줄어들지 못했다.) 그 결과, 데이터 중심(메모리의 역할이 중요한 순간)으로 발전중인 현대 소프트웨어 구조에서 CPU와 메모리 사이의 성능 차이가 엄청난 Bottle neck 이 되었고 , 최근 컴퓨팅 시스템 연구에서 메모리의 성능 향상이 주 타겟이 되었으며, 또한 DRAM Scailing의 여러 한계로 인해 다양한 메모리 시스템이 고안되고 있다. (e.g., CXL)
 
다양한 시스템이 고안되고 있다고 하더라도, 메인은 DRAM이며 DRAM에 대한 기초 지식은 필수적이다.
이번 글을 통해 DRAM에 대한 전체적인 구조를 이해해보자.
 

Overview

DRAM의 정확한 명칭은 'Dynamic Random Access Memory' 이며 우리가 흔히 부르는 DRAM의 더 정확한 명칭은 DDR SDRAM(Doubld Data Rate Synchronous DRAM) 이다. DDR의 의미는, DRAM 채널을 통한 데이터의 이동이 한 사이클의 Rising edge 와 Falling edge 에서 2번 비트를 전송해 붙여진 이름이다.

삼성 DDR DRAM

시작하전에 맛보기로 DRAM Chip 과 DIMM 이 무엇인지 살펴보자!

 

많이들 DRAM이 위 사진의 초록색 모듈 자체로 알고 있는데, DRAM 은 검은색 각각의 칩 하나씩을 의미하며, 그 칩들을 모아놓은 것을 Memory DIMM Module, 줄여서 DIMM (딤) 이라고 부르곤 한다.

 

이제 칩과 딤이 무엇인지 알았으니, 디램 내부에 대해 알아보도록 하자.

 

[21`ASPLOS] SIMDRAM

전체적인 DRAM의 구조는 위 그림과 같이 생겼다.
 

  • 먼저 DRAM Module(아래 왼쪽)은 Host Processor(CPU)에 내장되어있는 MC(Memoryt Controller) 와 Channel을 통해 연결되어 있으며, 각 채널은 하나 이상의 Rank로 이루어져 있다.
  • Rank는 Chip 8-16개가 모여 하나의 Rank를 구성하며, 각 Chip은 여러개의 Bank(e.g., 8-16)로 이루어져 있다
  • Bank는 또 다시 여러개의 Subarray(e.g., 64-128)로 이루어져 있으며 각 Subarray속으로 들어가면, 실질적으로 데이터가 저장되어 있는 Memory Cell들이 격자 형태로 존재하고 있다.
  • 이때, 가로 라인을 Wordline(e.g., 512-1024), 세로 라인을 Bitline(e.g., 2-8KB)이라고 하며 원하는 Wordline에 접근하기 위한 Local row decoder 그리고 원하는 데이터를 밖으로 내보내기 위해(혹은 밖에서 온 데이터를 DRAM에 쓰기위해) 값을 저장하는 Local row buffer로 이루어져 있다. 그림엔 없지만 Bank에는 Global row decoder 와 Global row buffer가 존재한다.
  • 또한, Subarray는 그림엔 나와있지 않지만 Mat 이라는 단위로 이루어져 있으며, 보통 512x512크기이다.
  • 각 Memory Cell은 Access Transistor와 실 데이터가 전하형태로 표현되는(저장되어있는) Storage Capacitor로 이루어져 있으며 이를 1T1C(하나의 Cell에 1개의 Transistor 필요, 주로 캐시에 사용되는 SRAM은 6T1C) 구조 라고 한다. Access Transistor의 On/Off를 통해 Bitline과 연결되어 값이 변경된다(=읽힌다, 쓰여진다).
  • Row buffer는 뒤에 자세히 설명하겠지만, DRAM Cell의 작은 전압 값을 읽기 위해 이 값을 증폭시켜야 하며 말 그대로 이 역할을 수행하는 Sense Amplifier 로 이루어져 있다.

 
여기까지 DARM의 구성 요소들을 간단히 살펴보았고, 이제 각 디테일을 살펴보도록 하자.
 

DRAM Achitecture

Memory Controller (MC)

메모리 컨트롤러는 보통의 경우 Host Processor(CPU) 패키지에 포함되어 있지만, 외부에 존재할 수도 있습니다. 어쨌든 위치와 상관없이 컨트롤러는 다음과 같이 작동합니다.

  1. CPU로부터 메모리의 주어진 어드레스에 read/write 요청을 처리한다.
  2. 해당 요청을 메모리 시스템의 커맨드로 변환한다. (e.g., ACT, PRE etc..)
  3. 적절한 타이밍에 적절한 순서대로 (스케쥴링) DRAM 디바이스에 해당 명령들을 실행한다.
  4. 프로세서나 시스템의 I/O 디바이스를 대신하여 데이터를 검색하거나 저장한다.

이외에도, 메모리 컨트롤러는 다양한 업무를 수행하는데, 전체적인 구조를 살펴보는 이 글에서 모든 것을 다룰 수는 없으므로, 다른 컨트롤러의 기능들은 개별적인 글의 주제로 작성할 예정이다.

Channel

메모리 컨트롤러는 DRAM 디바이스와 채널을 통해 통신한다. 이때, 채널 규격은 64Bits wide data bus로 표준화 되어 있으며(즉, 한 번에 64Bits씩 통신한다. ECC(에러정정코드)가 포함된 경우 72Bits) 하나의 컨트롤러는 하나 이상의 채널을 담당할 수 있다. 만약, 하나의 컨트롤러가 듀얼 채널로 구성되어 있다면, 64Bits 씩 두 채널이므로 128Bits 폭의 시스템이 구성된다.
 

하지만 결국 MC의 역할을 생각해보면, 각 명령을 처리하는 역할을 하기 때문에 1MC-2CH 구조보다 위 사진처럼 각 MC가 각 채널을 담당하는 구조가 성능상 더 나을 수 밖에 없다.
 

Rank

메모리 컨트롤러는 채널을 통해 DARM 디바이스와 64Bits(or 72Bits) 씩 통신하는데, 이때 이 64Bits을 주고받는 대상이 랭크입니다. 결국 기본적으로 메모리 컨트롤러는 랭크단위로 작동한다고 말할 수 있으며, 랭크는 여러개의 칩으로 구성이되고, 각 칩은 뱅크로 구성되어 있습니다.
 

source: https://www.cgdirector.com/single-rank-vs-dual-rank-ram/

해당 그림을 통해 살펴봅시다.
 
첫번째 행을 보면 어떤 직사각형 모양 = 8 Bits이라고 쓰여있는데, 여기서 직사각형은 실제 하나의 DRAM 칩을 의미합니다. 한 번에 64Bits을 주고 받으므로, 한 칩이 8Bits을 처리한다면 8개의 칩이 필요합니다. 그리고 이러한 피지컬 메모리 모듈을 DIMM이라고도 표현합니다. (나머지 8Bits은 ECC를 위한 칩이므로 지금은 설명하지 않습니다.) 
 
우선, 64Bits을 8개의 칩이 나눠처리 하는것을 Interleaving 이라고 표현하며, 이 경우 하나의 Rank 안에서 일어나고 있으므로 Bank-Level-Interleaving 이라고 합니다(또한 Channel-Level / Rank-Level 도 모두 활용되고 있습니다). 이게 뭐냐면, 한 번에 8Bits씩 처리한다고 할 때, 64Bits을 한 명이 처리한다면 8 time이 걸릴 겁니다. 하지만 8명이 나눠서 일하면 1 time만에 끝낼 수 있겠죠? 일종의 parallelism processing 이라고 생각할 수 있습니다.
 
그렇다면, 한 번에 8Bits을 처리한다는것은 무엇일까요? 이것은 Burst 라고 합니다. 데이터는 2가지의 Locality를 가지는데(Temporal / Spatial) 데이터를 저장하고 처리하는 경우에, 인접한 데이터는 인접한 위치에 저장되어 있을 확률이 높고 이를 Spatial Locality를 가진다고 합니다. 
 
따라서, 한 번에 1Bits씩 8번 가져오기보다, 메모리는 한 번의 요청으로 8Bits을 처리하는 버스트 모드를 지원하고 있습니다.
 
2번째 행은 Burst Length = 8이 아닌 Burst Lengh=4인 상태이며, 이 경우 한 번에 64Bits을 처리하기 위해 16개의 칩이 필요하고 그림을 보면 뒷 면에도 칩이 있는걸 확인할 수 있습니다. 이 경우 16개의 칩 & 하나의 DIMM이 하나의 랭크(Single Rank)를 구성합니다.
 
3번째 행은 8 Burst 모드 칩이 양면에 부착되어 있습니다. 따라서 하나의 DIMM이 2개의 랭크(Dual Rank)로 구성되어 있으며 이 경우 128Bits wide 를 지원합니다.
 
메모리 컨트롤러와 마찬가지로 Burst / Interleaving 등 다양한 주제에 대해 이야기할 수 있으나, 해당 주제들은 개별적인 글을 통해 정리하도록 하겠습니다.

Bank

[13`MICRO] Rowclone

DRAM에서 독립적으로 작동할 수 있는 가장 작은 단위 뱅크이며 동시에 병렬적으로 작동하는 가장 작은 단위이기도 합니다. 뒤에서 설명하겠지만 데이터를 활성화 시키기 위해 뱅크 내부에 Row 단위로 접근해야하며, Subarray와 무관하게 한 번에 하나의 Row만 뱅크내에서 활성화 될 수 있습니다. 따라서 메모리 명령어들은 독립적인 Bank 단위로 작동한다고 볼 수 있습니다. 
 
하나의 칩 내에서 여러개의 뱅크들은(DDR4-8개 / DDR5-16개) 데이터를 읽고 쓰기 위해 내부 버스를 공유하고 있으며, 각 뱅크는 서브어레이로 구성되어 있습니다.
 
뱅크는 외부에서 온 명렁어를 Global row decoder를 통해 어떤 서브어레이로 명령어를 보낼지 선택하며, 처리된 데이터들은 서브어레이의 Local row buffer와 뱅크의 Global row buffer 사이에서 통신됩니다. 최종 데이터는 뱅크의 Global row buffer와 칩 내부의 Shared Internal Bus 사이에서 통신되며, 이는 메모리 컨트롤러와 채널을 통해 통신됩니다.

Subarray

[12`ISCA] SALP

뱅크는 서브어레이의 모음으로 구성되고, 각 서브어레이는 메모리에서 가장 작은 단위인 메모리 셀의 격자형태로 구성됩니다. 
 
뱅크 내부의 가로x세로 구성은 제조사 마다 다르겠지만, Row가 2^15 이라고 가정하면, 32,768(=32K rows)개가 존재하게 됩니다. 이를 하나의 Global row buffer를 이용하게 될 경우 가장 가까운 Row는 빠르게 접근하겠지만 가장 먼 Row에 접근할 경우 즉, 32,768번째 Row와 Global row buffer사이의 거리 차이로 인해 데이터를 가져오는 시간이 너무 오래걸리게 됩니다.
 
이러한 현상을 극복하고 데이터와 통신하는 시간을 줄이고자 뱅크 내부를 서브어레이 단위로 나누고 각 서브어레이 안에 Local row buffer를 넣고, Local row buffer와 Global row buffer 사이의 통신을 지원하도록 구성되었습니다.
 

In Subarray (Row & Column & Cell)

[13`MICRO] Rowclone

각 서브어레이는 메모리 셀의 어레이 형태로 되어있으며, 각 row를 Wordline, 각 column을 Bitline이라고 지칭합니다. 그리고 메모리 셀은 실제 데이터를 저장하는 Capacitor, Bitline과의 연결을 담당하는 Access Transistor로 구성되어 있으며 이를 1T1C 구조라고 하구요. 
 
실제 작동방식은 메모리 셀의 전압을 Bitline이 읽는 구조로 작동하며, 이때 셀이 미치는 전압 영향이 매우 작기 때문에 이를 증폭시켜는 것이 필요합니다. 이는 Sense Amplifier가 담당하며, Bitline에 인가되는 아주 미세한 전압 차이를 인지하고 1 또는 0으로 증폭시키는 역할을 수행합니다.
 
간단히 메모리 작동방식에 대해 설명하자면, CPU 에서 보낸 명령을 메모리 컨트롤러가 메모리 명령어로 재해석하여 지정된 주소의 Bank / Subarray로 보냅니다. Global / Local row decoder를 통하여 Subarray / Row가 지정되며, 해당 Row는 활성화가 됩니다. 그 Row의 전체 데이터는 Sense Amplifier를 통해 Local row buffer로 이동하며, 그 후 원하는 데이터의 Column Address를 통하여 해당 데이터를 READ / WRITE 하게 됩니다. 
 
대부분의 경우에 Sense Amplifier는 간단하게 위 그림처럼 그려지지만, 실제 Sense Amplifier는 이렇게 구성되어 있지 않습니다.
 

Sense Amplifier

현대 메모리 시스템에 적용된 구조를 Open Bitline Array Architecture라고 하며 다음 그림처럼 구성됩니다.

[16`HPCA] LISA

실제 Sense Amplifer는 하나의 메모리 셀 보다 큰 면적을 차지하기 때문에 하나의 Sense Amplifier가 1개의 Bitline이 아닌, 2개의 Bitline을 담당하고 있습니다. 또한, 바로 아래 위로 2개의 Bitline이 아닌, 엇갈려진 형태로 Bitline을 담당하고 있습니다. Bitline을 2개씩 끊어서 생각하면 왼쪽은 위쪽으로, 오른쪽은 아래쪽으로 연결되는 구조입니다.
 
즉, 하나의 서브어레이는 여태 그림들처럼 하나의 Local row buffer를 가지는 것이 아닌, 아래 위로 2개의 Local row buffer를 가지게 되는 것입니다. (Local row buffer가 Sense Amplifier 입니다.)

[17`MICRO] Ambit

위 그림은 Sense Amplifier의 간략한 회로도를 보여주고 있습니다. 만약 Bitline에서 읽힌 값이 0.6(=0.5 + delta)이라고 하면, 2개의 NOT 게이트를 반복적으로 돌며 실제 연결된 BItline은 1로, 반대편 Bitline은 0으로 증폭이 되게 됩니다.
 
값을 이렇게 설정한 이유는, Bitline은 기본적으로 프리차지 과정을 통해 0.5 * VDD 의 값으로 초기화 되어 있기 때문입니다.
 

[17`MICRO] Ambit

이건 심화과정 내용이므로, 건너뛰실 분들은 건너 뛰셔도 됩니다.
 
연산은 기본적으로 CPU가 처리하지만, Memory Bottelneck 으로 인해 현대 컴퓨팅에서는 메모리 내에서 연산을 하려는 다양한 시도들이 제시되고 있습니다. 그중 하나로, 위 그림은 NOT 연산을 처리하기 위한 구조를 보여주고 있습니다. (제시된 다양한 연구들 중 하나일 뿐, 무조건 NOT 연산을 위처럼 수행할 것이라는 것은 아닙니다.)
 
위 그림을 보면, Bitline의 반대편은 반대 값으로 설정되는 특성을 이용하여, 메모리 셀을 1T1C가 아닌, 2T1C 구조로 만들어 반대편 Bitline 과 연결된 Transistor를 하나 더 두었습니다. 이를 통해 NOT이 적용된 값을 읽을 수 있습니다. 이러한 구조를 Dual contact cell (DCC)라고 합니다.
 

여기까지 DRAM의 전체적인 구조에 대해 살펴보았고, 이제는 어떻게 DRAM이 데이터를 처리하는지 살펴보도록 하겠습니다.
 

How DRAM works?

Overview

특정한 Row / Column address 를 가진 메모리 요청이 처리되는 방식에 대해 간단히 살펴보겠습니다.
 
우선, CPU는 LOAD/STORE 명령을 통해 메모리 컨트롤러와 통신하게 됩니다. LOAD는 메모리로부터 데이터를 캐시로 적재하는 것이고, WRITE은 캐시의 데이터를 메모리로 쓰는것을 의미합니다. 각각은 메모리 컨트롤러에서 READ/WRITE으로 치환됩니다.
 
이 과정을 수행하기 위해 메모리 컨트롤러는 순서대로 3개의 명령어를 발행합니다.

  1. ACTIVATE: 해당 주소의 Row 전체 데이터를 Sense Amplifier를 통해 Local row buffer로 읽습니다.
  2. READ/WRITE: Row buffer에서 해당 주소의 Column에 접근하여 데이터를 읽거나 씁니다.
  3. PRECHARGE: 활성화된 Row를 제거하고, 모든 Bitline의 전압을 0.5 * VDD로 설정합니다.

이러한 일련의 과정을 통해 메모리가 작동하는데,

  • 각 명령어는 바로바로 처리될 수 없고, 지정된 시간만큼 지나야만 하는 다양한 Timing Constraint 도 존재하고
  • 뱅크에서는 한 번에 하나의 Row만 ACTIVATE 될 수 있으며
  • 모든 Row는 ACTIAVTE되기 이전에 해당 뱅크가 PRECHARGE 상태여야 합니다.

이 밖에도 다양한 내용들이 있으나, 이 정도의 내용만 알고 있으면 DRAM 작동 방식을 이해하기 충분하며, Timing Constraint 관련 내용들은 추후에 다른 글에서 정리하도록 하겠습니다.
 

[17`MICRO] Ambit

그러면, 위 그림의 순서대로 어떻게 작동하는지 살펴보겠습니다.
 

  1. 먼저 해당 뱅크는 PRECHARGE 상태여야 합니다. 그 말인 즉슨, 모든 Bitline의 전압은 0.5*VDD 인 상태이며 모든 Worline은 전압이 0인 상태임을 의미합니다.
  2. ACTIVATE: 해당 주소의 Wordline이 활성화되어 메모리 셀이 Bitline과 연결됩니다,
  3. 메모리 셀의 전압이 Bitline에 미세한 영향을 주며 0.5 +- delta 의 전압이 됩니다. 동시에 메모리 셀은 전하가 방출되며 (즉, 정보를 잃습니다.) 이를 Charge Sharing 이라고 합니다.
  4. Bitline의 미세한 전압 변화를 Sense Amplifier가 증폭시켜 0 또는 1로 전압을 이끌어냅니다.
  5. 전압의 상대적인 크기로 인해 메모리 셀의 전압을 Bitline의 전압을 따라가게 되는데, 증폭된 0 또는 1로 메모리 셀의 값 또한 복구됩니다.(이를 restore 라고 합니다.) 하지만 거의 동시에 Restore가 되는 것은 아니며, 일정 시간이 필요합니다. 따라서 Sensing 이후에 너무 빨리 다른 Row에 접근하면 메모리 셀의 데이터를 잃을 수 있습니다. (그래서 다양한 이유로DRAM Timing Constraint이 존재하며, 다른 글에서 설명드리도록 하겠습니다.)
  6. 이제 Local row buffer로 값을 읽어냈기 때문에 해당 Column으로 READ/WRITE 명령을 수행할 수 있으며, 새로운 명령어가 들어와 새로운 Row를 ACTIVATE 해야 할 경우 PRECHARGE 과정을 통해 1번 상태로 돌아가야 합니다.

Refresh

DRAM 내부의 메모리 셀의 캐패시터는 시간이 지남에 따라 내부 전하를 조금씩 잃게되는 특징이 있습니다. 그에 따라 메모리 컨트롤러는 주기적으로 REFRESH 명령을 통해 해당 셀의 전하를 복원시켜주어 Sense Amplifier가 정확한 값을 읽도록 해야합니다.
 
이러한 특성으로 인해 Dynamic RAM 이라는 이름이 붙여졌습니다.
 

Conclusion

이번 글에서는 DRAM Architecture에 대해 살펴보았으며, 이 글을 통해 DRAM의 기초를 다질 수 있을 것이라 생각합니다.
 
하지만 이 밖에도 Interleaving, Physical address space, Timing Constraint 등 하지 못한 다양한 내용들이 존재하며, 차차 하나씩 글을 써보도록 하겠습니다.