컴퓨터를 만듭시다. 어때요~ 참 쉽죠? (9)

나빌레라의 이미지

#9. 읽기. 쓰기. 찾기

아주 넓은 백지가 있다. 우리에겐 백지에 무언가를 그릴 수 있는 펜이 있고, 내가 그린것을 읽을 수 있는 눈과 지적 능력이 주어져 있다. 그래서 우리는 넓디 넓은 백지에 이것저것 글을 쓰기도 하고 그림을 그리기도 한다. 때로는 필요한 메모나 사랑하는 애인의 전화번호 등을 적어 놓기도 한다. 하지만 문제가 발생했다. 적어 놓기는 했는데 넓은 백지 어느 부분에 적어놨는지 찾을 수가 없다. 어떻게 해야 찾을 수 있을까?

방법을 생각해 보자. 먼저 넓은 백지를 동일한 크기의 면적으로 나눈다. 편의상 사각형 모양으로 생각하자. 그런 다음 각각 사각형에 번호를 매긴다. 역시 편의상 사각형 1000개 만큼의 크기를 가지는 백지라고 하자. 그러면 우리가 찾고자 하는 내용은 사각형 0번 부터 999번 사이 중 어떤 것 위에 있을 것이다. 이제 우리는 필요한 내용이 어디 있는지 백지 위에서 찾으면 된다. 애인의 전화 번호는 사각형 235번에 있다. 사각형 235번으로 가서 번호를 보면 된다.

램에서 데이터를 특정 주소에 쓰거나, 특정 주소에서 읽어오는 방식도 위와 다를 바 없다. 지난 이야기에서 말했던 1비트를 저장할 수 있는 소자(셀(cell)이라고 표현하기도 한다.)를 수 천만개 연달아 붙여 놓고 이들을 몇개씩 묶어서 거기에 번호를 매겨놓은 다음 해당 번호로 접근해서 소자에 0이나 1을 넣는 것이다. 읽어 올 때도 마찬가지로 해당 번호에 접근해서 출력을 읽는 것이 전부다. 이렇게 소자 몇개를 묶어 놓은 것을 보통 메모리 주소라고 부른다. 일반적으로 메모리 주소는 소자 8개를 묶어서 하나로 관리한다. 1비트 8개는 1바이트다. 정말 특별한 용도의 메모리가 아닌 이상 대부분의 매모리는 1바이트 단위로 메모리 주소가 매겨져 있다.

1KB 짜리 메모리는 이 메모리 주소가 0부터 1023까지 있다는 것이고, 1비트를 저장할 수 있는 메모리 소자는 8192개 있다는 말이다.

잠시 지난 번 이야기를 떠 올려 보자. 지난 번에는 8비트짜리 메모리를 만들었다. 그리고 8비트 메모리에 값을 넣기 위해 각 D 플립플롭마다 스위치를 연결해서 개별적으로 값을 입력했다. 지난 번 처럼 만든 다면 16비트짜리 메모리를 만들 경우 16개의 스위치가 필요하다. 그럼 위에서 말한 1KB의 메모리를 만든다면 스위치가 8192개 필요하게 된다. 하지만 위에서처럼 메모리 소자를 8개씩 묶어서 주소를 부여하게 되면 메모리를 8개씩 묶인 주소 단위로 제어할 수 있기 때문에 입력 스위치가 8개만 있어도 8192개의 D 플립플롭에 모두 값을 쓸 수 있다. 그리고 읽는 단위도 1바이트 씩이기 때문에 8개의 램프만 있으면 8192개의 D 플립플롭에 있는 값을 모두 읽을 수 있다. 물론 8192개의 D 플립플롭 값을 한 번에 표시할 순 없고 순서대로 8개씩 읽을 수 있을 뿐이다.

그것이 가능하기 위해서는 D 플립플롭 회로를 조금 수정해야 한다.

위 그림을 보면 기본적인 D 플립플롭 회로에 선택 단자와 입/출력 단자가 추가되었고 Q 출력도 그냥 출력되는 것이 아니라 추가된 신호를 묶어서 3-input-AND 게이트로 연결되어 있다. 그리고 이 회로를 역시 간단하게 네모 하나로 표현해서 오른쪽처럼 표현하겠다.

이제 저 회로는 D 플립플롭도 아니므로 메모리 셀(cell)이라고 표현하겠다. 선택 단자와 입/출력 단자를 제외하면 기본적인 D 플립플롭의 동작을 그대로 수행한다. 다만 선택 단자의 신호가 입력 단자와 함께 3-input-AND 게이트를 통해 RS 플립플롭의 S, R 입력으로 들어가므로 선택 단자가 1일 때만 이 메모리 셀은 값을 입력할 수 있다.

또한 인버터를 통해서 읽기/쓰기 단자의 신호 역시 3-input-AND 게이트로 들어간다. 그래서 쓰기 일 경우 0을 주지만 인버터를 거치므로 3-input-AND 게이트에는 1이 입력되고 선택 단자가 1일 경우 입력 단자의 값이 S와 R에 영향을 준다. 그리고 읽기 일 경우 1을 주지만 인버터를 통하므로 3-input-AND 게이트에는 0이 입력되어 S와 R에는 0이 들어다고 RS 플립플롭의 진리표에 따라 값은 유지된다.

왜 읽기가 1이고 쓰기가 0일까? 세상에 모든 것은 다 이유가 있어서 그렇게 정해진 것이다. 출력 단자 쪽의 3-input-AND 게이트를 보면 답이 나온다. 출력 단자의 3-input-AND 게이트의 세 입력은 선택 단자 신호, Q 출력 신호, 입/출력 단자 신호다. 일단 선택 단자는 1이어야 읽기든 쓰기든 할 수 있다. 그리고 Q 출력은 출력이므로 당연히 출력과 연결되어야 한다. 이제 중요한 것은 입/출력 단자다. 우리가 쓰기 작업을 할 때는 출력 단자에서 아무것도 나올 필요가 없다. 그래서 쓰기가 0이다. 쓰기를 위해 입/출력 단자에 0을 주면 인버터를 거쳐서 S, R입력에는 영향을 주지만 그 값이 그대로 전달 되는 출력 단자 쪽의 3-input-AND 게이트는 Q 출력과 관계 없이 무조건 0이 나오게 된다. 그리고 읽기일 경우는 출력 단자 쪽 3-input-AND 게이트에 1을 주므로 Q 출력의 값이 그대로 출력 단자의 값으로 반영된다. 절묘하지 않은가? 나는 이 회로를 보며 세상엔 참 똑똑한 사람들이 많다는 것을 새삼 느꼈다.

저 그림만 보고도 똑똑한 분들은 전체 램 매트릭스가 어떻게 구성될지 예상이 되는 분도 계실 것이다. 예상이 안된다고 좌절할 필요는 없다. 이제 이야기 할 것이다.

그림에 성의가 없긴 하지만 위 그림은 가로 세로 8개씩 64개의 셀로 구성된 8바이트 램이다. 주소 배정은 일반적인 램과 마찬가지로 1바이트마다 배정했으므로 위 램은 0부터 7번지까지 주소를 가진다. 그래서 주소를 모두 표현하는데는 3비트면 충분하다. 어드래스 디코더(Address decoder) 쪽을 보면 주소 입력 핀이 a0, a1, a2 이렇게 세 개다. 3비트로 0부터 7까지 표현할 수 있기 때문이다. 그리고 입출력은 8비트가 필요하므로 입력을 위한 쓰기 스위치 쪽은 DI0부터 DI7까지 있다. DI는 Data Input을 의미한다. 마찬가지로 출력을 위한 읽기 버퍼 쪽은 DO0부터 DO7까지 있다. 당연히 DO는 Data Output을 의미한다.

어드래스 디코더는 3 input 8 ouput decoder라고 부르는 회로다. 이름 그대로 이진수 3 비트로 어떤 숫자를 입력으로 주면 해당 위치에 1이 출력되는 것이다. 예를 들어 이진수 011을 입력으로 주면 네 번째 출력 핀에 1이 출력된다. 011은 십진수로 3이고 출력은 0부터 계산되므로 0,1,2,3해서 네 번째 출력핀에 1이 출력된다. 구성 방법에 따라 여러가지 디코더 회로가 존재하겠지만 쉽게 찾을 수 있는 3 input 8 output decoder 회로는 아래 그림과 같다.

8개의 3-input-AND 게이트와 3개의 인버터만으로 만들어진 회로다. a0,a1, a2에 모두 0이 입력되는 경우 인버터를 통해 D0 쪽의 3-input-AND 게이트에 입력이 모두 1이 되므로 D0에 1이 출력된다. 같은 원리로 D1~D7까지에 a0부터 a2까지의 입력에 따라 1이 출력된다.

다시 8 바이트 램을 보자. 어드래스 디코더의 8개 출력 핀에 각각 8개씩 묶은 메모리 셀의 선택 단자가 연결된다. 그리고 입력 스위치의 선과 출력 버퍼의 선은 모든 메모리 셀에 연결된다. 마찬가지로 입/출력을 선택하는 RW 선도 모든 메모리 셀에 연결된다. 이것으로 메모리 주소로 접근이 가능한 입출력이 모두 되는 충분히 사용가능한 8 바이트 램이 완성되었다. 믿기지 않는가? 믿어라.

못 믿는 분들을 위해 동작을 시켜 보자. 위의 성의없는 그림 안에서 표현 가능하도록 0x2 번지에 숫자 6을 입력해 보겠다. 숫자 6은 이진수로 00000110이다. 그리고 0x2 번지는 이진수로 010 번지다.

우선 주소를 선택한다. 어드래스 디코더에 010 번지를 입력한다. a1에만 1을 입력한다. 그러면 3 input 8 output decode는 D2번 핀에 1을 출력한다. D2는 8개의 메모리 셀에 연결되어 있다. D2에 연결된 8개 메모리 셀은 선택 단자에 1이 입력된 상태다. 그리고 입력 스위치의 DI1과 DI2에 1을 입력한다. 이러면 00000110을 입력한 것이 된다. 입력 스위치의 각 비트 신호선도 해당 열의 모든 메모리 셀에 연결되어 있어서 한 줄로 8개씩 모든 메모리 셀의 D 입력에 입력이 들어가긴 하지만 선택 단자에 1이 입력된 메모리 셀에만 값이 반영된다. 쓰기는 RW 신호가 0이므로 출력에는 영향을 주지 않는다.

램에 값을 썻으니 이제 값을 읽어보자. 값을 읽는 방법도 쓰는 법과 별반 다르지 않다. 어드래스 디코더에 주소를 입력하고 RW 신호에 1을 준다. 그러면 출력으로 값이 나온다. 정말일까? 정말이다.

아까 0x2번지에 6을 입력했으므로 다시 0x2번지를 읽어보자. 어드래스 디코더에 010을 입력한다. 그러면 쓰기 동작을 할 때와 마찬가지로 D2 핀에 1이 출력되어 해당 라인에 있는 8개의 메모리 셀의 선택 단자에 1이 입력된다. 그리고 RW 입력에 1을 입력한다. RW 입력 역시 모든 메모리 셀에 다 연결되어 있다. 하지만 선택 단자가 1로 입력되는 메모리 셀은 같은 주소를 배정받은 8개 뿐이므로 해당 주소에 있는 메모리 셀의 값이 출력 버퍼로 들어간다. 위 그림에서 파란색으로 표시한 것은 값이 출력되긴 하지만 아까 0을 입력했기 때문에 0이 출력된다는 의미로 구분한 것이다. 만약 아까 6이 아니라 255를 입력했다면 8개 출력 모두에 1이 나갈 것이다. 다시 한 번 강조하지만 D 플립플롭게 저장되어 있는 값이 출력으로 나간다.

스위치로 개별 메모리 셀에 값을 입력하는 방식에서 좀 더 실제 컴퓨터에서 사용하는 방법에 가까운 메모리 주소를 이용한 메모리를 만들었다. 사실 여러분의 컴퓨터에 꼽혀 있는 램 칩도 위에서 내가 이야기한 램의 규모를 아주 많이 키웠을 뿐 기본 동작 원리는 같다. 물론 메모리 셀을 구성하는 소자가 다르긴 하지만 그것은 논외로 치자.

전자석과 스위치로 릴레이 스위치로 트랜지스터를 만들고 트랜지스터로 논리 게이트를 만들고 논리 게이트로 플립플롭을 만들고 플립플롭으로 램을 만들었다. 좀 수고스러울지 몰라도 위에서 이야기한 8바이트짜리 램도 맘만 먹는다면 전자석과 스위치를 이용해서 충분히 만들 수 있다. 그 크기가 아주 커지고 전기를 많이 먹고 전선이 꽤 복잡하게 연결될지라도 말이다. 그리고 앞으로 계속 이야기 해 나갈 모든 것들 역시 전자석과 스위치로 만들 수 있다. 그것이 CPU라고 할지라도....

댓글

Lein의 이미지

잘 보고 있습니다:)
사실 컴퓨터 논리회로를 지금 수강중인 학생인데, 중간고사 바로 전까지 배운 내용들을 복습 하는 것 같아 좋네요:)

jo1413의 이미지

잠 시 지난 번 이야기를 떠 올려 보자. 지난 번에는 8비트짜리 메모리를 만들었다. 그리고 8비트 메모리에 값을 넣기 위해 각 D 플립플롭마다 스위치를 연결해서 개별적으로 값을 입력했다. 지난 번 처럼 만든 다면 16비트짜리 메모리를 만들 경우 16개의 스위치가 필요하다. 그럼 위에서 말한 1KB의 메모리를 만든다면 스위치가 8192개 필요하게 된다. 하지만 위에서처럼 메모리 소자를 8개씩 묶어서 주소를 부여하게 되면 메모리를 8개씩 묶인 주소 단위로 제어할 수 있기 때문에 입력 스위치가 8개만 있어도 8192개의 D 플립플롭에 모두 값을 쓸 수 있다. 그리고 읽는 단위도 1바이트 씩이기 때문에 8개의 램프만 있으면 8192개의 D 플립플롭에 있는 값을 모두 읽을 수 있다. 물론 8192개의 D 플립플롭 값을 한 번에 표시할 순 없고 순서대로 8개씩 읽을 수 있을 뿐이다.

여기에서 8개씩 묶인 주소 단위로 제어할 수 있기 때문에 입력 스위치가 8개가 아니고 10개 아닌가요?
8192 / 8 = 1024 니까
1024개를 가리키려면 2^10 이므로 입력 스위치가 10개가 아닌지요?
제가 잘못 생각하고 있다면 가르침 부탁 드립니다.

------------------------------------------------------------
Get busy living, or get busy dying.

yaru22의 이미지

이미 답을 알아 내셨는지 모르겠지만 제가 생각하는 답을 달자면 이렇습니다.

입력 스위치 (그림에서 Write Switch)와 address decoder에 들어가는 address bits랑 혼동하신 것 같습니다.
입력 스위치는 여전히 8개구요 그러므로 한번에 한 바이트씩 (8bit 씩) 쓸 수 있는거죠.
그리고 님이 말씀하신데로 8192 / 8 = 1024 바이트가 있으니깐, 예를들어 1kb 전체를 다 읽으려면 1024번을 해야하는거죠.
그러니깐 입력 스위치가 10개가 되는게 아니라 address decoder에 들어가는 a0, a1, a2 ... 가 10개 있는거죠.
그래야 각각 메모리 바이트의 주소를 구분할 수 있으니깐요.

예를 들자면,
첫번째 바이트에 10010011을 쓰시려면 입력 스위치에 10010011 (8자리)을 넣고 address decoder에 0000000000 (10자리)을 넣고 쓰시고
두번째 바이트에 10101010을 쓰시려면 입력 스위치에 10101010 (8자리)을 넣고 address decoder에 0000000001 (10자리)을 넣고 쓰시고
세번째 바이트에 11111111을 쓰시려면 입력 스위치에 11111111 (8자리)을 넣고 address decoder에 0000000010 (10자리)을 넣고 쓰시고
...

이렇게 입력 스위치는 여전히 8개구요. Address decoder에 들어가는 스위치가 더 많아지는거죠.

하나 더 말씀 드리자면, 32-bit 컴퓨터 보시면 램이 4gb 밖에 인식을 못하는 이유가 저기에 있습니다.
Addreess decoder에 들어가는 스위치가 32개가 되는 셈이니깐 2^32 바이트까지 밖에 표현을 못하는거죠.

2^32 = 4294967296 byte = 4194304KB = 4096MB = 4GB

설명이 이해가 되시는지요.

qkrtjswn93의 이미지

제가 지금 플립플롭을 이용해서 메모리를 만드는 방법에 대해 마침 고민하고 있었는데
이 글을 읽고 정말 유용하다고 생각했습니다.
혹시 플립플롭을 이용해서 메모리를 만드는 c언어 소스가 있으시다면 그것도 올려주실 수 있으신가요?

정규혁의 이미지

정말 이해가 잘되요

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.