부록 A Logisim_evolution을 이용한 논리회로 실습 A.1 Logisim-Evolution 개요 A.2 Logisim-Evolution 설치 A.3 Logisim-Evolution 사용 방법 A.4 논리게이트 및 논리회로 간소화 실습 A.5 조합회로 실습 A.6 순차회로 실습 A.7 메모리 실습 A.8 조합회로/순차회로/메모리 활용 8-비트 컴퓨터 구현 부록 A Logisim_evolution을 이용한 논리회로 실습 A.1. Logisim-Evolution 개요 Logisim은 GUI 툴을 이용하여 논리회로를 구현하고 검증할 수 있는 교육용 무료 논리회로 시뮬레 이션 프로그램이다. Logisim은 Dr. Carl Burch에 의해 처음 개발되어 2011년까지 수정 및 보완이 이루어지다가 개발자의 개인적인 사정으로 중단되었다. 이후 스위스의 한 교육기관 그룹이 Logisim 의 기능을 확장 개발하여 Logisim-evolution이라는 이름으로 배포를 하였으며 추가된 여러 가지 유용한 기능에 의해 최근에는 evolution 버전이 더 많이 사용되고 있다. 본 부록의 논리회로 설계 및 검증 실습에서는 이 Logisim-evolution을 사용하여 본문에서 다루었던 여러 가지 조합회로 및 순차회로를 구현해 보고 그 동작을 모의실험을 통해서 확인해 보도록 한다. 나아가 본문을 통해 배운 다양한 조합 및 순차 회로들을 활용하여 4개의 명령어를 가지는 8-비트 마이크로프로세서를 설계해 본다. 이 실습 과정을 통해서 논리회로에 대한 이해가 깊어지고 디지털 시스템 설계에 대한 감각과 실무적 능력이 배양될 것으로 기대된다. A.2. Logisim-Evolution 설치 Logisim-evolution의 공식 배포 홈페이지는 github.com/logisim-evolution/logisim-evolution이며 이 사이트에 접속하여 보면 아래와 같은 페이지가 나타난다. 472 •디지털 논리회로 홈페이지를 아래로 스크롤 하면 다운로드 링크가 있으며, 다운로드 링크를 누르면 다양한 플랫폼(Windows, macOS, Linux, ...)에 대한 컴파일된 형태의 실 행 파일을 찾을 수 있다. 공식 홈페이지는 예고 없이 변경될 수 있지만, 홈페이지에 나타난 다운로 드 링크를 잘 찾으면 설치 프로그램 다운로드에 크게 어려움은 없을 것으로 생각된다. 내려받은 설치 프로그램을 실행시키면 아래와 같은 창이 나타나며, 모두 Next 버튼을 누르면 실행 프로그램 설치가 끝난다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 473 A.3. Logisim-Evolution 사용 방법 Logisim-evolution을 설치하고 처음 실행하면 [그림 A.1]과 같은 프로그램 창이 열린다. 그림 A.1 Logisim_evolution의 실행 화면 Logisim-evolution은 크게 개발 영역(explore pane), 속성 테이블(attribute table), 그리고 캔버스의 3부분으로 구분된다. 그리고 그 위로 메뉴바와 툴바가 위치한다. 각 부분에 대한 간단한 설명은 아 래와 같다. Menu Bar : Logisim-evolution의 동작에 대한 메뉴들을 포함하고 있다. Tool Bar : 회로 구현을 위한 기본 게이트들과 선 연결, 시뮬레이션을 위한 입력값 변경 등의 기능을 제공한다. Explore pane : 회로의 생성과 외형 변경 툴을 포함, 현재 구현하고 있는 회로와 부회로들 (subcircuits), 그리고 툴바에 보이지 않는 다양한 내장(builtin) 라이브러리들을 포함한다. Attribute table : 캔버스에서 선택된 컴포넌트에 대한 속성을 보여주고 변경할 수 있다. Canvas : GUI 툴을 이용하여 게이트 및 부회로를 배치하고 회로를 구현하기 위한 편집 창이다. 이번 절에서는 Logisim-evolution을 이용하여 ‘무작정 따라하기’의 관점에서 간단한 예제 논리회로 를 캔버스에 배치하고 선 연결을 수행한 후 입력값을 변화시켜가면서 출력값을 확인하는 과정을 수행해 보도록 한다. A.3.1. 게이트 추가하기 Logisim-evolution을 이용하여 회로를 꾸밀 때 추천하는 방식은 먼저 필요한 게이트 및 입·출력 핀 을 뼈대처럼 캔버스에 적절히 위치시켜 놓은 후에 배선을 진행하는 것이다. 게이트 혹은 입·출력 핀을 불러와서 배치하는 과정을 아래 회로의 예를 들어서 살펴보면 다음과 같다. 474 •디지털 논리회로 ① 툴바에서 AND 툴 ( )을 클릭하고 ( 혹은 Explore pane의 Gate 라이브러리에 서 AND 게이트를 선택) 마우스를 캔버스로 움직이면 선택된 게이트가 외형을 유지한 채로 이 동한다. 적절히 캔버스의 좌/우, 위/아래에 충분한 공간을 두고 마우스를 클릭하여 AND 게이트 를 배치한다. ② 툴바에서 OR 툴 ( )을 클릭해서 AND 게이트 위치 아래에 적당한 간격을 두 고 이동시켜 배치한다. 기본적인 2-입력 OR 게이트를 3-입력으로 변경하고 싶을 때는 OR 게 이트를 클릭하고 속성창에서 Number of Inputs 항목을 2 →3으로 바꾸면 된다. 2 inputs 3 inputs ③ 툴바에서 XOR 툴 을 클릭해 두 게이트 오른쪽에 배치한다. ④ 툴바에서 입력 핀 ( )을 클릭한 후 게이트의 입력이 연결되는 장소에 3개를 각각 배치한 다. ⑤ 툴바에서 출력 핀 ( )을 클릭한 후 게이트의 출력이 연결되는 장소에 1개 배치한다. 특정 게이트나 입력 혹은 출력 핀의 위치를 변경하고 싶으면 선택툴 ( ) 모드에서 원하는 게이트/ 핀을 선택한 상태로 드래그하면 된다. 아래 그림은 배치가 완료된 후의 모습이다. 그리고 Untitled로 되어 있는 프로젝트 이름을 메뉴바의 File ⇒ Save를 클릭해서 ‘LSE_Tutorial’이라는 이름으로 저장한다. 참고로 저장된 프로젝트는 File ⇒ Open을 통해서 다시 불러올 수 있으며 나중에 다른 프로젝트에서 라이브러리 형태로 추가될 수도 있다. 하나의 프로젝트는 개발자가 구현한 여러 개의 논리회로의 집합체인 만큼 프로젝트명은 회로의 이름으로 짓기보다는 집합체의 특성으로 짓는 것이 좋다. 예를 들면 프로젝트명으로는 덧셈기, 부록 A. Logisim_evolution을 이용한 논리회로 실습• 475 곱셈기보다는 조합회로, 순차회로 등이 더 프로젝트 내의 회로들의 성향을 나타낸다고 할 수 있 겠다. ⑥ 배선을 위하여 선택툴( )을 활성화한 후 핀 단자 혹은 게이트의 입력/출력 단자로 커서를 이 동시키면 단자가 위 그림 AND 게이트 입력과 같이 녹색 동그라미로 변하게 된다. 그 상태에서 단자를 클릭하면 선의 한쪽 부분이 연결되며 그 상태로 다른 쪽 연결 단자까지 드래그하여 이동 하면 이동하는 마우스를 따라서 선이 그려진다. 단자 간의 연결선은 여러 조각으로 나누어 생성 될 수 있으며 혹은 한 번에 연결될 수도 있다. 모든 선의 연결이 완성된 형태는 아래와 같다. 연결상태에 따른 선의 색상 선을 연결할 때 [그림 A.2]에 보여지는 선의 색상에 따른 의미는 다음과 같다. 회색 : 현재 선의 양단이 모두 연결되어 있지 않은 상태 파란색 : 현재 선이 한쪽에만 연결되어 있어 선의 상태값이 정해지지 않은 상태 짙은 녹색 : 현재 선이 정상적으로 입력과 출력 단자에 잘 연결되어 있으며 그 값이 0인 상태 밝은 녹색 : 현재 선이 정상적으로 입력과 출력 단자에 잘 연결되어 있으며 그 값이 1인 상태 빨간색: 값을 결정할 수 없는 상태 (혹은 두 출력이 서로 다른 값을 가지고 충돌함) 476 •디지털 논리회로 검정색 : 비트수가 다수일 때(BUS) 하나의 논리값만 색으로 표현할 수 없어서 검정으로 표현 주황색 : 연결된 컴포넌트의 비트 폭이 서로 다른 상태 그림 A.2 Logisim-evolution에서의 선 생상 따라서 회로의 모든 선에 대한 연결이 완료되었을 때 선의 색상은 항상 짙은 녹색, 밝은 녹색, 혹은 검정색의 상태가 되어야 한다. A.3.2. 입출력 핀 이름(label) 정하기 Logisim-evolution으로 회로를 모두 구현하고 나면 그 상태에서 바로 회로의 입력값을 변화시켜가 면서 출력값을 확인할 수 있다. 그러나 이 상태에서는 회로 설계자만이 입력 및 출력에 대한 의미를 알 수 있고 타인에게 회로를 전달하게 되면 입출력의 의미를 전혀 알 수 없게 된다. 이런 이유로 모든 입력 및 출력에 텍스트로 이름(label)을 지어 놓는 것이 바람직하다. ① 툴바에서 텍스트 툴 ( )을 클릭하고 마우스로 이름을 지을 핀 상단 첫 번째 입력 핀을 클릭하 면 핀 이름을 지을 수 있는 EDIT 창이 커서와 함께 나타나며 그 상태에서 이름을 ‘A’로 입력한 후 Enter 키를 누르면 핀 옆에 이름이 나타난다. 또 다른 방법으로는 선택 모드( )에서 핀을 더블 클릭하면 label 창이 팝업되며 여기서 상자 안에 핀 이름을 입력하고 OK 버튼을 누르면 된다. (두 번째 방법을 추천한다.) 부록 A. Logisim_evolution을 이용한 논리회로 실습• 477 ② 나머지 두 개의 입력핀도 ‘B’와 ‘C’로 각각 이름을 입력하고, 출력핀도 ‘F’로 이름을 입력한다. A.3.3. 회로의 테스트 모든 회로의 구성이 완료되면 입력 핀의 값을 변화시켜가면서 회로의 동작을 확인하는 과정이 필요 하다. Logisim-evolution은 사실 회로의 구성이 완료되는 순간 이미 시뮬레이션의 결과를 보여주는 상태가 된다. 모든 입력핀은 회로의 캔버스에 위치시킴과 동시에 입력값을 ‘0’으로 기본 설정하고 있기 때문에 모든 입력 0에 대한 회로의 동작 결과를 출력을 통해서 보여준다. 입력값을 변화시키는 방법은 크게 두 가지 방법이 있다. 툴바에서 poke 툴( 선택툴( )을 클릭한 후 입력핀을 클릭하면 입력값이 변화된다. )모드에서 poke 툴 모드로 전환하지 않고 커서를 핀 위치로 옮긴 후 마우스의 중간 버튼(휠 버튼)을 누르면 입력값이 변화된다. 어느 방법이든 편한 방법을 사용해서 입력을 1로 설정하면 3-입력 OR 게이트의 출력이 1이 되고 ⋅ 이므로 ⊕ 이 되어 출력은 1이 된다. 여기서 살펴볼 것은 OR 게이트의 출력 은 밝은 녹색으로 바뀌고 AND 게이트의 출력은 짙은 녹색을 유지하며 XOR 게이트의 출력은 밝 은 녹색으로 변하게 된 점이다. 즉 선의 색상만으로도 각 게이트의 출력 확인이 가능하다. 478 •디지털 논리회로 따라서 모든 입력 조합이 되도록 입력핀의 값을 변화시켜가면서 출력을 확인해 보면 회로의 특성을 테스트할 수 있게 된다. 실습 사항 ① [A.3.1] 과 [A.3.2] 과정을 따라서 Logisim-evolution의 캔버스에 회로를 배치하고, 입출력 핀을 추가하여 배선을 완료한 후, 입출력 핀 이름을 지정하라. ② [A.3.3] 과정을 따라서 모든 입력 조합에 따른 출력을 확인하고 그로부터 다음과 같이 진리표를 채우도록 하라. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 479 A.3.4. 부회로(subcircuit) 설계하는 회로가 점점 복잡해지고 커지면 작고 반복되는 형태의 일부 회로를 모듈화하여 계층적으 로 사용할 필요성이 생길 수 있다. 이는 마치 프로그램 개발 시 자주 사용하는 기능을 함수 (function) 혹은 서브루틴으로 만들어 놓고 메인 함수에서 함수를 호출하고 그 반환 값을 결과로 받아서 동작하게 하는 것과 같은 개념이다. Logisim-evolution에서는 부품과 같은 의미로 작고 반 복적으로 사용될 수 있는 회로를 부회로(subcircuit)라고 부르며 계층적 구조로 상위계층 회로에서 부회로를 부품으로 불러와서 반복적으로 사용할 수 있는 기능을 제공한다. 그림 A.3 Logisim-evolution에서의 계층적 회로 구현 예 일례로 [그림 A.3]의 아래쪽처럼 2개의 AND 게이트, 한 개의 NOT 게이트, 그리고 한 개의 OR 게이트로 구성된 2x1 멀티플렉서 회로를 구현해 놓았다고 하면, 상위계층 회로에 해당하는 4x1 멀 티플렉서는 2x1 멀티플렉서 모듈 3개를 마치 레고 부품처럼 가져와서 쉽고 간단하게 부품 간의 연 결을 통해서 구현할 수 있다. 부회로 생성 및 사용 방법을 위 그림을 예제로 사용하여 살펴보면 다음과 같다. 부회로 생성 ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 개발창(Explore pane)에서 아이콘을 클릭하 면 [그림 A.4(a)]와 같이 회로 이름을 설정할 수 있는 창이 나온다. 회로 이름을 ‘Mux_2x1’이라 고 입력하고 OK 버튼을 누르면 [그림 A.5(b)]와 같이 개발창에 처음 시작할 때 기본으로 생성 되는 ‘main’ 회로 밑에 추가로 방금 입력한 이름의 새 회로가 생성되며 새로운 캔버스가 열린다. 480 •디지털 논리회로 (a) (b) 그림 A.4 Logisim-evolution에서의 새 회로 생성 ② Mux_2x1의 빈 캔버스 안에 회로를 만드는 방법은 앞에서 main 회로를 만들던 방법과 같다. 즉 원하는 게이트와 입출력 핀을 추가하고 선을 연결하여 완벽하게 동작할 수 있는 회로를 구성 한다. 예를 들면 Mux_2x1회로는 [그림 A.5]와 같이 2개의 AND 게이트, 1개의 OR 게이트, 1개의 NOT 게이트, 3개의 입력핀과 1개의 출력핀을 잘 배치하고 연결하여 만들 수 있다. 그림 A.5 Mux_2x1 부회로의 구현 이렇게 Mux_2x1 캔버스 내에서 설계된 회로는 캔버스 내부에서 동작을 테스트할 수 있다. 즉 입력 값을 수정해 가면서 회로의 동작을 확인하면 된다. [그림 A.5]의 회로는 In0, In1 = 1인 입력 상태 에서 Sel = 0일 때 Mout으로 In0 값이 나가는 상황을 보여준다. 반면에 Sel 값을 0에서 1로 변경하 면 [그림 A.6]과 같이 Mout으로 In1 값이 출력된다. 출력 핀 내에 적혀있는 값을 통해 출력값이 0인지 1인지를 알 수도 있지만 단지 출력핀으로 연결되는 선의 색상으로도 출력 논리값을 알 수 있다고 앞서 언급한 바 있다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 481 그림 A.6 Mux_2x1 회로의 간단한 검증 부회로 사용 위 과정을 통해서 새 회로가 생성되고 정상적인 동작이 검증되었다면 이제 상위 회로(본 예제에서 는 Mux_4x1 회로)에서 이 회로를 블록도 형태의 부회로로 불러서 사용하는 것이 가능하다. ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭해서 새로운 회로를 ‘Mux_4x1’이라는 이름으로 생성한다. (회로를 생성하면 캔버스가 생성된 회로로 자동 이동됨) ② Explore pane 창에 있는 Mux_2x1 회로를 선택한 후 마우스를 캔버스로 이동하여 적당한 위치 에 배치하기를 3번 반복한다. 아래 그림은 블록도 형태로 3개의 부회로 부품이 배치된 모양을 보여준다. (Mux_2x1 회로를 선택하고 Cntl+D를 눌러 복제해서 사용해도 된다.) ③ 4x1 멀티플렉서를 위한 4개의 입력 핀 I0, I1, I2, I3와 선택 입력 핀 Sel0, Sel1을 캔버스 왼쪽에 위치시키고 최종 출력 Mout을 오른쪽에 배치한 후 [그림 A.7]과 같이 연결한다. 482 •디지털 논리회로 그림 A.7 Mux_4x1 부회로의 구현 ④ 필요한 경우 부회로의 부품 자체에도 이름을 붙일 수 있다. 부품의 중앙에 마우스를 위치시키고 더블클릭을 수행하면 [그림 A.8]과 같이 컴포넌트 이름 편집창이 나타난다. 여기에 부품의 이름 을 입력하면 부품 상단부에 [그림 A.7]과 같이 MUX1, MUX2, MUX3 와 같은 식으로 이름이 보인다. 그림 A.8 컴포넌트 이름 편집 창 ⑤ 4x1 멀티플렉서의 동작도 테스트해 보도록 하자. 예를 들어 I0=I2=I3=0, I1=1로 설정한 후 Sel1=0, Sel0=1을 입력값으로 주면 [그림 A.9]와 같이 I1에 해당하는 1 값이 Mout으로 전달되 어 나오는 것을 확인할 수 있다. 그림 A.9 Mux_4x1 부회로의 검증 ⑥ 필요한 경우 회로의 전체적 기능을 요약하여 캔버스의 빈칸에 회로 제목을 텍스트로 넣을 수 부록 A. Logisim_evolution을 이용한 논리회로 실습• 483 있다. 방법은 툴바에서 텍스트 툴 ( )을 클릭하고 마우스로 캔버스의 빈 공간(주로 중앙 상부 에 배치)을 클릭한 후 커서가 나타나면 원하는 제목을 작성하고 Enter 키를 치면 된다. [그림 A.9]의 중앙 상단부에 회로의 기능과는 관계없는 제목 텍스트가 보여지고 있다. 부회로 외형 편집 Logisim-evolution에서 기본으로 제공하는 외형은 [그림 A.10(a)]처럼 직사각형의 형태에 왼쪽에 입력핀, 오른쪽에 출력핀, 사각형 밑면에 검은 영역으로 부회로의 이름이 보이는 블록도 모양을 가 진다. Logisim-evolution에서는 이 기본 외형 외에 [그림 A.11(b)]와 같이 속성창의 Appearance 탭을 통해서 추가로 3개의 외형을 더 지원한다. 그중 하나는 초창기 Logisim에서 사용하던 TTL IC 모습을 가진 [그림 A.11(c)]와 같은 외형으로, 크기가 작은 장점이 있지만 핀 이름 정보가 없어 서 배선과정에서 불편함이 따른다. 두 번째는 [그림 A.11(d)]와 같이 핀 이름과 부회로 이름을 간단 하게 보여주는 Logisim-Holycross 스타일의 외형이다. 마지막으로 custom 외형은 사용자가 직접 외형을 디자인해서 사용하는 방식이다. (a) 기본 외형 (b) 외형 선택 속성 (c) Classic logisim (d) Logisim-Holycross 그림 A.10 Mux_4x1 부회로의 검증 이제 사용자가 원하는 형태의 외형을 직접 디자인할 수 있는 custom 외형을 만드는 방법에 대하여 Mux_2x1 부회로의 외형 수정 예를 통해서 알아보도록 한다. ① Mux_2x1회로의 캔버스가 열려있는 상태(Explore pane 창에서 Mux_2x1 아이콘을 더블클릭) 에서 프로젝트 메뉴의 ‘Edit Circuit Appearance’를 선택하거나 Explore pane의 외형 편집( 아이콘을 선택하여 외형 편집 모드(Layout Editing Interface)로 진입한다. 484 •디지털 논리회로 ) ② 위 외형 편집 캔버스에 나타난 직사각형은 상위계층에서 부회로를 드래그해서 위치시킬 때 차 지하는 외형의 크기와 모양을 나타내고, 외형 왼쪽/오른쪽 면의 파란색 사각형은 입력핀 및 출 력핀 위치를 나타낸다. 그리고 직선이 연결된 작은 녹색 원은 앵커 포인트라고 해서 마우스로 캔버스에 부회로를 위치시킬 때의 상대적 배치 원점이 된다. 외형 편집 창에는 외형과 핀의 위치만 나타나고 핀의 이름과 회로 내부에서의 기능은 보이지 않는다. 따라서 핀들이 많이 있는 부회로에서는 특정 핀이 회로의 어떤 핀에 해당하는지 알 수 없게 되는 불편함이 생긴다. 이 경우 특정 핀을 클릭해 보면 위 그림처럼 편집 창 하부에 부회로 의 회로도와 그 회로에서 선택 핀의 위치를 파란색 하이라이트로 보여준다. 위 예에서는 외형의 왼쪽 상부 첫 번째 핀이 In0에 해당한다는 것을 의미한다. ③ 외형의 핀 위치에 따른 내부 회로와의 관계를 숙지했다면, 외형 도형의 크기나 모양을 사용자 마음대로 변형하고 또한 핀의 위치도 변형된 도형의 임의 위치로 이동할 수 있다. 예를 들어 Mux_2x1의 기본 외형은 [그림 A.11(a)]와 같으며 [그림 A.11(b)]는 기본 외형을 두고 빈 공간 에 추가로 외형을 새로 그린 후 핀을 이동시킨 상황을 보여준다. 외형의 수정은 툴바()의 다양한 기능( )을 사용하여 손쉽게 이루어진다. 외형 수정 시 선 이나 사각형 혹은 원 등을 그릴 때 그리드에서만 움직일 수 있도록 컨트롤키, 시프트키, ALT 키 등의 기능을 함께 제공한다. [그림 A.11(c)]는 최종 외형만 남기고 원래 외형을 제거한 모습 이다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 485 (a) 기본 외형 (b) 추가 외형 및 핀 이동 (c) 최종 외형 그림 A.11 Mux_2x1 외형 편집 과정 ④ Mux_2x1 회로의 외형을 변경했다고 해서 상위계층 회로에서 부회로로 가져다 쓸 때 바뀐 외형 이 적용되지 않는다. 그 이유는 Mux_2x1의 외형이 Logisim-evolution으로 선택되어 있기 때문 이다. 따라서 Mux_2x1 캔버스에서 아무것도 클릭하지 않은 채로 속성에서 외형을 custom으로 변경해 주면 비로소 Mux_4x1 회로에서 Mux_2x1의 외형이 아래 그림과 같이 변경되게 된다. 기본 외형을 사용해도 논리 계층적 회로를 구현하거나 테스트하는 데는 아무런 상관이 없다. 그 러나 회로의 외형을 통해서 회로의 기능을 시각적으로 표현하고자 할 때는 custom으로 외형을 수정해서 사용하는 것도 좋은 방법이다. 그림 A.12 부회로의 외형이 변경된 Mux_4x1 회로 실습 사항 ① A.3.4의 [그림 A.5]와 같이 MUX_2x1이라는 이름의 회로를 새로 생성하여 구현하고, In0 = 0, In1 = 1로 설정한 후, Sel 값에 따른 출력 F의 변화를 확인하라. 그리고 다른 입력 조합에 대해서 도 Sel 값의 변화에 따른 출력값을 확인하라. ② [그림 A.7]과 같이 MUX_4x1이라는 이름의 회로를 새로 생성하고 MUX_2x1 부회로 3개와 입 출력 핀을 사용하여 구현한 후 몇 가지 입력값(I0~I3)에 대해 Sel(1:0)에 따른 출력값을 확인 하라. 486 •디지털 논리회로 ③ [그림 A.12]와 같이 시각적으로 멀티플렉서임을 쉽게 알아볼 수 있도록 MUX_2x1 부회로의 외 형을 수정하여 MUX_4x1 회로에 반영하고 그 동작을 확인하라. A.3.5. 스플리터를 이용한 핀-버스 연결 입력 A(A3, A2, A1, A0)와 B(B3, B2, B1, B0) 중 하나를 선택 신호(Sel)의 값에 따라서 선택적으로 출력 F로 내보내는 4-비트 병렬 Mux_2x1 회로를 부회로로 구현해서 상위계층 회로에서 부품으로 사용하려고 한다. 첫 번째 방법은 [그림 A.13(a)]와 같이 입력 8+1개와 출력 4개 그리고 1-비트 짜리 2x1_Mux 부회로 4개를 사용해서 구현하는 것이다. (a) 비트 입·출력으로 구현된 4-비트 MUX (b) 버스 입·출력으로 구현된 4-비트 MUX 그림 A.13 4-비트 2x1 MUX 의 구현 방법 [그림 A.14]는 ‘Mux_2x1_4Bit_P’이라는 이름으로 구현한 부회로를 보여주고 있다. 그림 A.14 4-비트 2x1 MUX 회로 부록 A. Logisim_evolution을 이용한 논리회로 실습• 487 이 부회로를 상위계층 회로(main)에서 부품으로 캔버스에 가져와 보면 아래 그림과 같이 입·출력핀 이 너무 많아지고 부품의 외형도 모든 핀을 다 표현하기 위해 커진 것을 알 수 있다. 만일 4-비트 2x1 MUX 가 아니고 8-비트 혹은 16, 32-비트 2x1 MUX를 부회로로 사용한다면 그 외형의 크기 를 짐작할 수 있을 것이다. 이러한 이유로 입출력 인터페이스를 간단히 하기 위하여 [그림 A.13(b)]와 같이 버스틀 통한 신호 의 전달 방식을 많이 이용한다. 스플리터(splitter)라고 하는 내장 Wire 라이브러리에 속한 컴포넌트 는 여러 비트 신호선과 하나의 버스선 사이의 신호 연결을 담당한다. 스플리터는 방향성이 없는 모 듈이어서 버스선을 여러 가닥의 개별 선으로 나눌 때도 사용되고 여러 가닥의 선을 하나의 버스선 으로 묶을 때도 사용된다. 이제 [그림 A.14]의 비트 입·출력으로 구성된 부회로와 같은 기능을 수행하도록 버스 입·출력되는 부회로로 변환하는 과정을 살펴본다. ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 개발창에서 아이콘을 클릭해서 새로운 회로 를 ‘Mux_2x1_4Bit_B’라는 이름으로 생성한다. ② 회로 ‘Mux_2x1_4Bit_P’의 캔버스에서 모든 회로를 복사해서 ‘Mux_2x1_4Bit_B’ 캔버스로 붙여 넣는다. ③ 입력핀 두 개를 캔버스에 추가하고 이름을 A와 B로 설정한 후, 입력핀 속성 창에서 Data Bits 값을 각각 4로 변경한다. 입력핀의 외형이 1-비트에서 4-비트로 확장되는 것을 볼 수 있다. ④ 출력핀 한 개를 캔버스에 추가하고 이름을 F로 설정한 후, 출력핀 속성 창에서 Data Bits 값을 4로 변경한다. 출력핀의 외형도 1-비트에서 4-비트로 확장되는 것을 확인한다. 488 •디지털 논리회로 ⑤ Explore pane의 Wire 라이브러리에서 Splitter 컴포넌트를 선택하여 캔버스로 가져온다. 스플리 터는 버스에 연결되기 편한 방향으로 90도씩 위치를 옮길 수 있다. 스플리터 속성 창에서 East, West, North, South 중 하나의 방향을 선택할 수 있는데 기본으로는 [그림 A.15(a)]처럼 West 방향으로 되어 있다. 속성을 East로 바꾸면 위치가 180도 회전되면서 [그림 A.15(b)]와 같이 핀 연결점이 오른쪽으로 향하게 된다. 또한, Appearance 속성값을 Left handed에서 right handed 로 바꾸면 [그림 A.15(c)]와 같이 스플리터 형태가 (b)에서 x 축에 대칭으로 반사되는 형태로 변한다. 그리고 스플리터의 속성 창에서 팬아웃을 4개, 버스의 비트 수를 4로 설정하면 [그림 A.15(d)]와 같이 4-비트를 포함하는 버스가 4갈래의 비트로 나뉘어지게 된다. a) West, Left-handed (b) East, c) East, d) Fanout=4, Left-handed Right-handed BitWidth=4 e) MSB top, LSB bottom 그림 A.15 스플리터 모델의 속성 선택에 따른 방향과 비트 수 ⑥ [그림 A.15d]를 보면 4-비트의 버스 데이터가 비트로 분할될 때 순서가 LSB top /MSB bottom 으로 되어 있다. 이 순서를 MSB top /LSB bottom으로 변경하면 선의 연결 편의성이 좋아질 수 있다. 방법은 스플리터 속성 창에서 비트 순서를 아래 그림과 같이 변경하면 되며, 변경 후의 스플리터 비트 위치는 [그림 A.15(e)]와 같게 된다. (a) LSB top/MSB bottom 형태 (a) MSB top/LSB bottom 형태 부록 A. Logisim_evolution을 이용한 논리회로 실습• 489 ⑦ 이 스플리터를 하나 더 복제(ctrl+D)해서 버스 단자는 버스 입력 A, B에 각각 연결하고 분할된 비트들은 기존 입력핀들을 모두 제거하고 해당하는 A3, A2, A1, A0와 B3, B2, B1, B0에 각각 연결한다. ⑧ 새로 스플리터를 하나 생성하고 4-비트로 변환한 후 방향은 (West, Left-handed)로 설정해서 버스 단자는 버스 출력 F에 연결하고 분할된 비트들은 기존 출력핀을 모두 제거하고 해당하는 F3, F2, F1, F0에 각각 연결한다. 모든 연결이 끝난 4-비트 병렬 2x1 멀티플렉서의 회로는 아래 그림과 같다. 이제 main 회로 캔버스에서 두 개의 부회로(Mux_2x1_4Bit_P, Mux_2x1_4Bit_B)를 각각 불러와서 배치해 보면 아래 그림과 같다. 버스 타입이 한결 간결하고 알아보기 쉬움을 알 수 있다. 490 •디지털 논리회로 A.3.6. 터널을 이용한 연결 매우 큰 회로를 구현하다 보면 여러 선을 지나고 여러 부품을 돌아서 아주 먼 곳까지 선을 연결해야 하는 경우가 있다. 이때 연결선이 너무 많이 꼬이면 정작 이 선이 어느 입력에서 와서 어느 곳으로 들어가는지 알 수 없게 되어 회로의 가독성이 현저히 떨어진다. 이럴 때 연결된 두 선을 절단하여 각각의 절단선에 터널 컴포넌트를 연결하고 터널 이름을 같게 해주면 마치 두 지점이 연결된 것과 같게 되어 회로 설계에 편리할 수 있다. 앞서 구현한 4-비트 2x1 멀티플렉서 회로를 예를 들어 터널을 이용하여 구현하여 보자. ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭해서 새로운 회로를 ‘Mux_2x1_4Bit_Tunnel’이라는 이름으로 생성한다. ② 부회로 ‘Mux_4x1_4Bit_Bus’의 캔버스에서 모든 회로를 복사해서 ‘Mux_4x1_4Bit_Tunnel’ 캔 버스로 복사한다. ③ 버스 입력핀과 스플리터를 잘라내서 왼쪽으로 이동시키고 버스 출력핀과 스플리터를 선택해서 자른 후 오른쪽으로 이동시켜서 터널이 들어갈 공간을 만든다. 그리고 입출력으로 사용되는 스 플리터의 속성창에서 spacing 값을 3으로 수정해서 분할된 비트들의 간격을 넓힌다. ④ Wire 라이브러리에서 터널 컴포넌트를 가져와서 끊어진 선의 양단을 같은 이름으로 연결한다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 491 ⑤ 테스트를 위해서 ‘Tunnel_Test’라는 새 회로를 만들고, 아래 그림과 같이 3개의 4-비트 병렬 2x1 MUX 컴포넌트를 모두 불러와서 4-비트 입력 A, B와 Sel 신호, 그리고 4-비트 출력 F를 각각 연결한다. A=1001, B=0110을 주고 Sel 신호를 변화시켜서 원하는 출력이 선택되는지, 그 리고 세 개의 4-비트 병렬 2x1 Mux가 모두 같은 동작을 하는지 확인한다. 이 터널의 편의성은 회로의 규모가 커지면 커질수록 높아지므로 많은 활용을 권장한다. 참고로 터 널이란 이름은 산에 터널을 뚫어놓으면 위에서 볼 때 길이 끊어진 것처럼 보이지만 실제로는 산 속으로 연결되어 있다는 뜻에서 기인한 듯하다. 492 •디지털 논리회로 실습 요약 간단한 논리회로를 Losigim-evolution을 이용하여 캔버스에 구현하고 입력 조합의 변화에 대한 출력 특성을 확인할 수 있다. 소프트웨어의 함수나 서브루틴과 같이 반복적으로 자주 활용되는 회로를 부회로로 구현하고 이 를 상위 계층 회로에서 부품처럼 가져다 사용함으로써 회로 구현의 효율성을 높일 수 있다. 입·출력 핀이 많이 존재하는 논리회로를 부회로로 구현할 경우 스플리터를 통한 버스 입출력으 로 대체할 수 있으며 이 경우 부회로의 블록도가 간단해 져서 신호의 흐름을 파악하기에 쉽다. 복잡한 회로의 배선을 연결할 때는 터널을 사용하면 쉽고 간단하게 연결이 가능하다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 493 A.4. Losigim-evolution을 이용한 논리게이트 구조 이해 및 논리회로 간소화 이번 실습에서는 [본문 4.4]에서 다루었던 논리게이트의 내부 구조가 트랜지스터로 구성되어 있다 는 내용을 확인하기 위해 Logisim-evolution의 MOS 트랜지스터 모델을 사용하여 여러 가지 논리 게이트를 구현하여 보고 라이브러리에서 제공하는 논리게이트, 그리고 표준 IC 내부에 탑재된 논리 게이트의 특성과도 함께 비교하여 보도록 한다. 또한, [본문 6장]의 내용처럼 부울함수가 카노맵을 이용하여 간소화되었을 때 간소화된 형태와 그 출력이 같은지를 확인해 보고 특정 함수의 SOP 및 POS 표현도 실제로 구현하여 두 회로가 등가임 을 확인하도록 한다. A.4.1. NMOS 트랜지스터를 이용한 논리게이트 구성 및 동작 확인 Logisim-evolution에서는 Wiring 라이브러리 내에 MOS 트랜지스터 모델을 제공한다. 제공되는 모델은 아래와 같이 N 타입과 P 타입이 있다. N 타입은 게이트와 소스 사이에 양 전압 ( ≃ )을 걸어주면 음전하에 의해 채널이 형성되면서 전자가 소스에서 드레인 방향 으로 흐르게 되며 스위치가 연결된 것과 같은 상태가 된다. P 타입은 게이트와 소스 사이에 음 전압 을 걸어줄 때( ≃ ) 양전하에 의해 채널이 형성되면서 양전하(양공)이 소스에서 드래 인 방향으로 흐르게 된다. 요약하면 NMOS는 게이트 전압에 의해 전류가 드레인에서 소스로 흐르 는 스위치로 작동하고 PMOS는 반전 게이트 전압에 의해 전류가 소스에서 드레인으로 흐른다. 이번 절에서는 Logisim-evolution에서 제공하는 NMOS를 이용하여 [본문 4장]에서 소개한 NMOS 트랜지스터를 이용한 논리게이트 회로를 캔버스에 구현하고 그 동작을 검증해 본다. 실습 사항 ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘TR_NotGate’ 라는 이름으로 새 회로를 생성한다. ② 아래 그림 (a)와 같이 내장 Wiring 라이브러리의 Transistor를 가져와서 중앙에 배치하고, 그림 (b)와 같이 속성창의 Type를 ‘N-Type’, 방향과 위치를 ‘North’ & ‘Bottom/Left’로 선택한다. 그림 (c)는 NMOS 외형의 세 가지 단자를 나타낸다. 화살표가 전자의 흐름을 나타낸다고 생각 하면 쉽다. 즉 전류는 드레인에서 소스 쪽으로 흐르고 전자 흐름은 방향이 그 반대이다. (화살표 가 반대 방향이 되도록 회로를 구현하면 동작하지 않음을 유의한다.) 494 •디지털 논리회로 (a) Wiring 라이브러리 내 TR (b) Transistor의 속성 설정 (c) NMOS 모델의 단자 표시 ③ 내장 라이브러리 내의 Pull Register를 가져와서 드레인 단자와 연결하고 속성 창에서 Pull Direction을 One(논리값 1에 해당)으로 설정한다. ④ 아래와 같이 입력핀 및 출력핀을 추가하고 비교를 위해 Gates/NOT Gate를 추가한 후 입력의 변화에 대한 트랜지스터 회로 및 NOT 게이트의 출력을 확인하고 아래 표를 채워라. ⑤ 본문 [그림 4.24]에서 설명한 회로를 다음과 같이 ‘TR_NANDGate’라는 새 회로에 구현하고 입 력에 대한 출력값을 확인하여 아래 표를 채워라. (2-입력 NAND 게이트는 Gates 라이브러리 내의 NAND Gate를 사용하면 되고 2 입력 NAND 게이트 표준 IC는 TTL 라이브러리 내의 7400을 선택하고 속성 창에서 ‘Show the internal structure’를 ‘YES’로 선택한다.) 부록 A. Logisim_evolution을 이용한 논리회로 실습• 495 ⑥ 본문 [그림 4.35]에서 설명한 회로를 다음과 같이 ‘TR_NORGate’라는 새 회로에 구현하고 입력 에 대한 출력값을 확인하여 아래 표를 채워라. (2-입력 NOR 게이트는 Gates 라이브러리 내의 NOR Gate를 사용하면 되고 2 입력 NOR 게이트 표준 IC는 TTL 라이브러리 내의 7402을 선 택하고 속성 창에서 ‘Show the internal structure’를 ‘YES’로 선택한다.) ⑦ 본문에서 AND 게이트는 NAND 게이트와 NOT 게이트의 직렬연결에 해당한다고 언급하였다. 이를 확인하기 위해 다음과 같이 ‘TR_ANDGate’라는 새 회로에 TR_NANDGate 회로와 TR_NOTGate 회로를 복사해서 붙여넣기를 하여 구현하고 입력에 대한 출력값을 확인하도록 하라. (2-입력 AND 게이트는 Gates 라이브러리 내의 AND Gate를 사용하면 되고 2 입력 AND 게이트 표준 IC는 TTL 라이브러리 내의 7408을 선택한 후 속성 창에서 ‘Show the internal structure’를 ‘YES’로 선택한다.) 496 •디지털 논리회로 ⑧ ‘TR_ORGate’라는 이름으로 새 회로를 만들고 TR_NORGate 회로와 TR_NOTGate 회로를 복 사해와서 직렬 연결하여 OR 게이트를 구성한다. 그리고 Gates/OR Gate와 TTL/7432를 가져 와서 연결하고 입력 변화에 대한 세 가지 게이트 출력을 비교하라. A.4.2. CMOS 트랜지스터를 이용한 논리게이트 구성 및 동작 확인 이번 절에서는 [본문 4.4.6]에서 소개한 CMOS 트랜지스터를 이용한 논리게이트 구현 내용을 Logisim-evolution을 통해 검증해 본다. 이를 위해 내장 NMOS 와 PMOS 트랜지스터를 함께 사 용하여 CMOS 회로를 만들고 이를 하나의 트랜지스터 블록으로 간주하여 여러 가지 논리게이트를 구성한 후 그 동작을 논리게이트 및 표준 IC의 출력과 비교해 본다. 실습 사항 ① ‘CMOS_NOTGate’라는 이름으로 새 회로를 생성하고 Wiring 라이브러리의 Transistor를 2개 불러와서 두 TR의 속성을 N-Type, North, Bottom/Left와 P-Type, South, Bottom/Left로 각 각 설정한다. ( PMOS를 배치할 때 화살표 방향에 유의하도록 한다.) 부록 A. Logisim_evolution을 이용한 논리회로 실습• 497 ② 비교를 위해 Gates/NOT Gate와 TTL/7404를 가져와서 배선을 완료하고 입력값에 대한 출력값 을 아래 표와 같이 비교하라. ③ 본문 [그림 4.39]에서 설명한 회로를 다음과 같이 ‘CMOS_NANDGate’라는 새 회로에 구현하 고 입력에 대한 출력값을 확인하여 아래 표를 채워라. ④ 본문 [그림 4.40]에서 설명한 회로를 다음과 같이 ‘CMOS_NORGate’라는 새 회로에 구현하고 입력에 대한 출력값을 확인하여 아래 표를 채워라. 498 •디지털 논리회로 ⑤ 본문 [그림 4.41]에서 설명한 회로를 다음과 같이 ‘CMOS_ANDGate’라는 새 회로에 구현하고 입력에 대한 세 출력값을 확인하라. ⑥ 본문 [그림 4.42]에서 설명한 회로를 다음과 같이 ‘CMOS_ORGate’라는 새 회로에 구현하고 입력에 대한 세 출력값을 확인하라. ⑦ 본문 [예제 4.10]에서 다룬 아래 CMOS 논리회로를 Logisim-evolution으로 구현하고 입력의 변화에 대한 출력을 확인하여 표를 채운 후, 이 회로의 논리적 입출력 관계를 도출하라. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 499 ⑧ 본문 [예제 4.12]에서 다룬 아래 CMOS 논리회로를 Logisim-evolution으로 구현하고 입력의 변화에 대한 출력을 확인하여 표를 채운 후, 이 회로의 논리적 입출력 관계를 도출하라. 500 •디지털 논리회로 A.4.3. 논리회로 간소화 및 SOP/POS 회로의 등가 확인 카노맵을 이용한 논리회로 간소화 실습 이번 실습에서는 3-변수 부울 함수 가 주어졌을 때, 이를 정규화된 표현으로 변환한 후 카노맵으로 간소화하고 그 결과가 간소화하기 이전의 함수와 같은 결과를 보임 을 확인하도록 한다. 실습 사항 ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘Kmap_Test’라 는 이름으로 새 회로를 생성한다. ② 에 대한 카노맵을 작성해 보고 그로부터 간소화된 함수 는 와 같음을 확인한다. ③ Kmap_Test 캔버스에 3-변수 AND 게이트 2개와 2-변수 AND 게이트 2개, 그리고 4-변수 OR 게이트 1개를 사용하여 F를 구현한다. 이때 보수는 입력신호에 NOT 게이트를 통과하여 얻어내도 되고 AND 게이트를 선택하고 속성 창에서 원하는 게이트 입력의 Negate를 ON으로 바꾸어 주어도 된다. 그리고 2-변수 AND 게이트와 2-변수 OR 게이트를 1개씩 사용하여 도 구현한다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 501 ④ 입력 핀값을 000 ~ 111까지 8가지 조합으로 변경하면서 두 회로의 출력 가 모두 같은 값을 출력함을 확인하라. (필요한 경우 진리표를 작성하면 좋음) SOP/POS 표현의 등가 관계 확인 이번 실습에서는 최소항의 합 형태로 표현된 3-변수 부울 함수 를 최대항의 곱 형태로 변환하고 두 형태의 논리회로가 등가임을 확인하도록 한다. 실습 사항 ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘SPCmp_Test’ 라는 이름으로 새 회로를 생성한다. 을 카노맵에 ‘1’로 작성하고 빈 셀을 ‘0’으로 작성한 후 그로부터 POS 과 같음을 확인한다. 형태의 부울함수를 얻어내면 ② (a) SOP 카노맵 (b) POS 카노맵 ③ SPCmp_Test 캔버스에 간소화 없이 를 3-변수 AND 게 이트 4개와 4-변수 OR 게이트 1개를 이용하여 구현한다. 그리고 3-변수 OR 게이트 4개와 4- 502 •디지털 논리회로 변수 AND 게이트 1개를 이용하여 를 아래 그림과 같이 함께 구현한다. ④ 입력 핀 값을 000 ~ 111까지 8가지 조합으로 변경하면서 두 회로의 출력 가 모두 같은 값을 출력함을 확인하라. (필요한 경우 진리표를 작성하면 좋음) 실습 요약 논리게이트의 내부는 트랜지스터로 구성되어 있음을 Losigim-evolution의 트랜지스터 모델을 사용하여 눈으로 확인할 수 있다. AND 및 OR 게이트는 NAND 및 NOR 게이트의 트랜지스터 구현에 인버터를 직렬로 연결한 구조라는 것을 알 수 있다. 카노맵을 이용하여 복잡한 논리회로를 간소화하면 두 회로는 같은 입력에 대한 같은 출력을 내 는 등가 회로가 됨을 테스트를 통해서 검증할 수 있다. 최소항을 이용한 곱의 합 표현과 최대항을 이용한 합의 곱 표현은 같은 회로의 다른 두 표현과 같다는 것을 두 방식의 회로를 직접 구현하여 확인할 수 있다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 503 A.5. Logisim-evolution을 이용한 조합회로 구현 및 테스트 이 장에서는 [본문 7장]에서 다루었던 다양한 조합회로들을 Logisim-evolution으로 구현하는 실습 과정과 테스트하는 내용을 다룬다. A.5.1. 가감산기 모델링 및 동작 검증 이번 실습에서는 반가산기(Half Adder)와 전가산기(Full Adder)를 부회로(sub-circuit)로 구현하고 최종적으로 4-비트 병렬 가감산기를 설계한 후 시뮬레이션을 통해서 그 동작을 확인하도록 한다. 반가산기 회로 설계 [본문 7.2.1]에서 살펴본 반가산기는 2진 1-비트 입력 에 대한 합(Sum)과 올림수(Carry)를 발 생시키는 회로로써 병렬 2진 덧셈기의 최하위 비트 덧셈에 사용되는 회로이며 [그림 A.16(a)]와 같 이 구성된다. 이를 [그림 A.16(b)]와 같이 Logisim-evolution 회로로 구현해 보도록 하자. (a) 반가산기 논리 회로 (b) 반가산기의 Logisim-evolution 구현 그림 A.16 반가산기 회로도 실습 사항 ⑤ Logisim-evolution 프로그램을 실행시키고 앞으로 설계할 모든 회로가 조합회로라는 의미에서 프로젝트를 ‘Combinational_Circuit’이라는 이름으로 저장한다. 저장방법은 메뉴바에서 File → Save As → 프로젝트명을 적어주면 된다. ⑥ 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘HA’라는 이름 으로 새 회로를 생성한다. ⑦ ‘HA’ 회로에서 한 개의 XOR 게이트, 한 개의 AND 게이트를 선택하여 캔버스에 넣고 두 개의 입력 핀과 두 개의 출력 핀을 추가한다. ⑧ 선 연결을 통하여 회로를 그림과 같이 완성하고, 각 입출력 핀에 이름(label)을 붙인다. 504 •디지털 논리회로 ⑨ poke 툴( )을 클릭한 후 입력핀 값을 수정하거나 혹은 마우스의 중간 버튼(휠 버튼)을 눌러서 입력값을 변화시켜가면서 모든 입력 조합에 대한 출력값을 확인하고 진리표를 채우도록 하라. 전가산기 회로 설계 [본문 7.2.2]에서 살펴본 전가산기는 두 입력 비트 그리고 낮은 자리에서 올라온 올림수 입력 을 더하여 합 출력 와 올림수 출력 을 내보내는 회로로써 [그림 A.17]과 같이 3개의 입력과 2개의 출력으로 구성된다. 이를 [그림 A.18]과 같이 앞서 설계한 반가산기를 부회로로 이용하여 구 현하여 보고 동작을 테스트하도록 한다. 그림 A.17 전가산기 회로도 부록 A. Logisim_evolution을 이용한 논리회로 실습• 505 그림 A.18 Logisim-evolution을 이용한 전가산기 구현 실습 사항 ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘FA’라는 이름 으로 새 회로를 생성한다. ② ‘FA’ 회로에서 두 개의 반가산기 회로(HA)와 한 개의 OR 게이트를 선택하여 캔버스에 배치하 고 세 개의 입력 핀(A, B, Ci)과 두 개의 출력 핀(S, Co)을 추가한다. ③ 선 연결을 통하여 회로를 [그림 A.18]과 같이 완성하고, 각 입출력 핀에 이름(label)을 붙인다. ④ 프로젝트 메뉴에서 ‘Edit Circuit Appearance’를 선택하거나 Explore pane에서 아이콘을 선 택하여 외형 수정 창으로 들어간 후, 정사각형으로 외형을 수정하고 입력 A, B는 윗면에, 출력 S는 아랫면에, 그리고 올림수 입력 Ci와 출력 Co는 오른쪽과 왼쪽면에 각각 위치시킨다. ⑤ 텍스트 아이콘‘A’를 선택하여 각 핀에 대한 이름을 아래와 같이 기입한다. 506 •디지털 논리회로 ⑥ 외형 편집 아이콘을 다시 클릭하면 FA 캔버스로 돌아와서 속성창의 Appearance를 Custom으로 설정한다. ⑦ ‘FA_Test’라는 새 회로를 생성하고 아래 그림과 같이 캔버스에 FA 부회로 컴포넌트를 불러와 입·출력핀을 추가하고 배선을 완료한 후 입력값을 변화시켜가면서 모든 입력 조합에 대한 출력 값을 구하라. 4-비트 병렬 가산기 회로 설계 [본문 7.2.3]에서 살펴본 2진 병렬 가산기는 -비트로 구성된 두 개의 2진수 덧셈을 수행하는 디지 털 회로로써 인 경우 [그림 A.19]와 같이 4개의 전가산기 모듈을 사용하여 설계할 수 있다. 이를 [그림 A.20]과 같이 Logisim-evolution에서 앞서 설계한 전가산기를 활용하여 구현해 보고, 그 동작을 테스트하도록 한다. 그림 A.19 4-비트 병렬 가산기 블럭도 부록 A. Logisim_evolution을 이용한 논리회로 실습• 507 그림 A.20 FA 회로를 부회로로 이용한 4-비트 병렬 가산기 구현 실습 사항 ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘Adder4’라는 이름으로 새 회로를 생성한다. ② ‘Adder4’ 회로 캔버스에 Explore pane의 전가산기(FA)를 선택하여 4개 배치하고 4-비트의 입 력 A와 B에 해당하는 8개의 입력핀, 올림수 입력핀 , 4-비트의 출력 S에 해당하는 4개의 출 력핀, 그리고 올림수 출력핀 를 추가한다. ③ 선 연결을 통하여 회로를 [그림 A.20]과 같이 완성하고, 각 입출력 핀에 이름(label)을 붙인다. ④ [그림 A.21]과 같이 ‘Adder4_Test’ 회로를 생성하고 Adder4 회로를 컴포넌트로 불러와 입력 및 출력핀을 추가하고 배선을 완료하라. 그리고 입력값을 변화시켜가면서 아래 표에 주어진 입력 조합에 대한 4 출력값 S와 올림수 출력 Co를 구하라. 그림 A.21 4-비트 병렬 가산기 테스트 508 •디지털 논리회로 버스를 이용한 부회로 인터페이스 간소화 [그림 A.21]과 같이 부회로를 구성하면 입출력 연결선이 너무 많아져서 선 연결하기도 불편하고 입력값을 수정하기도 불편하며 캔버스 상에 공간도 많이 차지한다. 따라서 버스를 이용하여 입력을 로, 입력을 로, 그리고 출력 를 로 스플리터를 이용하여 버스선으로 변경하여 입출력 인터페이스를 구성해 보도록 한다. 그림 A.22 버스 입출력을 가지는 4-비트 병렬 가산기 구현 실습 사항 ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘Adder4_Bus’ 라는 이름으로 새 회로를 생성한다. ② ‘Adder4’ 캔버스의 모든 회로를 선택한 후 복사해서 ‘Adder4_Bus’ 캔버스로 붙여넣기를 수행한 다. ③ ‘Adder4_Bus’ 캔버스 위에서 Wiring/Splitter를 선택해서 캔버스 창으로 이동시켜 놓고 스플리 터의 속성 창에서 Fan Out과 Bit Width in 속성을 모두 4로 변경한다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 509 ④ 스플리터의 버스 연결부에 입력 핀을 하나 A라는 이름으로 추가해서 연결하고 입력핀의 속성 창에서 Data Bits를 4로 설정한다. 비트 길이가 달라서 주황색이던 입력 핀과 스플리터 사이의 연결선이 녹색 선으로 바뀌고 입력 핀도 4개의 2진수 입력값을 가진 버스 입력으로 바뀐다. ⑤ 이제 스플리터의 0, 1, 2, 3 핀을 각각 기존 입력핀 A3, A2, A1, A0를 대체하여 연결한다. ⑥ 같은 방법으로 두 개의 스플리터를 더 추가하고 각 스플리터의 속성을 4-비트로 변경한 후 입력 B3, B2, B1, B0와 출력 S3, S2, S1, S0를 각각 스플리터의 비트 순서에 맞게 연결하고 4-비트 입력 핀 B와 4-비트 출력핀 S를 추가하여 스플리터 버스 부분과 연결한다. 연결이 완료된 후의 모습은 [그림 A.22]와 같다. ⑦ 비교를 위해서 2진 비트 핀들로 입출력이 정의된 Adder4 모듈, 4-비트 Bus로 변환된 510 •디지털 논리회로 Adder4_Bus 모듈, 그리고 Logisim-evolution에서 기본적으로 제공하는 Arithmetic 라이브러리 중 하나인 Adder 모듈을 속성창에서 Data bits = 4로 설정하여 [그림 A.23]과 같이 main 캔버 스에 불러온다. 그리고 4-비트 입력 A, B와 Ci를 공통으로 3개의 모듈에 동시에 연결하고, 4-비 트 출력 S와 Co를 각각의 모듈에 대해 별개의 출력으로 이름 붙여 연결한다. 그림 A.23 핀과 버스 입출력을 가지는 두 개의 4-비트 병렬 가산기 비교 테스트 ⑧ poke 툴( )을 이용해서 4-비트 입력값 A 및 B를 변화시켜가면서 3개 부회로의 동작이 모두 일치함을 확인하도록 하라. (참고로 [그림 A.23]에서는 (1110)+(0111) 의 덧셈에 대하여 0101 의 출력과 올림수 1이 세 컴포넌트 모두 같게 나오는 것을 보여준다.) 앞으로 새로 설계하는 모든 멀티 비트 입·출력 회로는 BUS를 이용하여 구현하도록 하고 회로 이름 은 _BUS를 붙이지 않기로 한다. ⑨ Adder4_Bus 회로를 2개 사용하고 스플리터를 사용하여 8-비트 병렬 가산기 Adder8 회로를 생 성하고 그 동작을 확인하라. A.5.2. 4-비트 병렬 가감산기 회로 설계 [본문 7.2.4]에서 살펴본 2진 병렬 가감산기는 -비트로 구성된 두 개의 2진수 덧셈 혹은 뺄셈을 부록 A. Logisim_evolution을 이용한 논리회로 실습• 511 신호 값에 따라서 선택적으로 수행하는 디지털 회로로써 인 경우 [그림 A.24]와 같이 4개 의 전가산기 모듈과 4개의 XOR 게이트를 사용하여 설계할 수 있다. 이를 앞서 설계한 전가산기를 활용하여 Logisim-evolution을 이용하여 구현하고 동작을 검증해 보도록 한다. 그림 A.24 4-비트 병렬 가감산기 블럭도 그림 A.25 Losigim-evolution을 이용한 4-비트 병렬 가감산기 구현 실습 사항 ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘AddSub4’라는 이름으로 새 회로를 생성한다. ② AddSub4의 부회로 캔버스에 Adder4의 회로를 복사해 온 후, Explore pane의 Gates 라이브러 리에서 XOR 게이트를 복사해 [그림 A.25]와 같이 4개 위치시킨 후, 입·출력 선을 연결한다. 참고로 새로운 1-비트 입력 이 추가된 것을 확인한다. ③ 선 연결을 통하여 회로를 완성하고, 각 입출력 핀에 이름(label)을 붙인다. ⑤ ‘AddSub4_Test’회로를 생성하고 아래 그림과 같이 ‘AddSub4’ 회로를 컴포넌트로 불러와 입력 및 출력핀을 추가한다. 배선을 완료한 후 입력값을 변화시켜가면서 표에 주어진 입력 조합에 대 512 •디지털 논리회로 한 출력값을 구하라. 그리고 M 값에 따라 덧셈기 혹은 뺄셈기로 동작을 하는지 확인하라. ⑥ ‘AddSub4’회로를 수정하여 LSB FA 블록의 가 신호와 연결되는 대신 입력핀으로 연결되도 록 한 후, 수정된 4-비트 가감산기 부회로를 2개 채용하여 8-비트 가감산기로 확장 설계한 후 그 동작을 검증하라. A.5.3. 4-비트 올림수 미리-보기 가산기 회로 설계 [본문 7.2.5]에서 살펴본 2진 병렬 올림수 미리-보기 가산기는 리플 캐리 가산기의 단점인 올림수 (Carry)의 지연시간을 단축하기 위해 부가적인 회로를 추가하여 캐리의 전파 시간을 줄이는 구조를 가진다. 덧셈기의 비트 수 인 경우 [그림 A.26]과 같이 4개의 PG 생성 모듈(HA와 동일)과 올림수 미리-보기 생성기 및 XOR 게이트를 4개 사용하여 구현할 수 있다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 513 그림 A.26 4-비트 올림수 미리-보기 가산기 블록도 이를 [그림 A.27]과 같이 올림수 미리-보기 생성기 회로(CLookAhead)와 만들어진 HA 부회로 및 XOR 게이트를 활용하여 Logisim-evolution에서 구현해 보고 동작을 검증해 보자. 그림 A.27 4-비트 올림수 미리-보기 가산기 핀타입 구현 실습 사항 올림수 미리-보기 가산기를 구현하는 과정을 크게 3단계로 구분하고자 한다. 1단계는 PG 생성기 (PG)를 부회로로 만들고, 2단계는 올림수 미리-보기 생성기(CLookAhead)를 부회로로 만들고 3단 계는 PG 생성기와 올림수 미리보기 생성기를 불러와서 최종적으로 가산기(CLAdder4)를 구현하고 자 한다. ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘PG’라는 이름 으로 회로를 생성하고 PG 캔버스에 ‘HA’ 회로를 복사해서 옮겨온 후 출력핀을 P와 G로 설정한 514 •디지털 논리회로 다. ② 부회로의 외형을 위 오른쪽 그림과 같이 수정하고 회로 속성에서 Custom외형으로 설정한다. ③ 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘CLookAhead’ 라는 이름으로 회로를 생성하고 [본문 그림 7.15]와 같은 형태로 AND 게이트와 OR 게이트를 이용하여 아래와 같이 생성한다. (각 게이트의 크기와 입력 수는 속성 창에서 수정 가능함) ④ 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘CLAdder4’라 는 이름으로 회로를 생성하고 Explore pane에서 4개의 PG와 1개의 CLookAhead를 부회로로 불러와서 아래와 같이 구현한다. 4-비트 입·출력 핀들과 XOR 게이트도 추가됨을 확인하라. ⑤ main 회로에서 ‘Adder4_Bus’와 ‘CLAdder4’ 회로를 컴포넌트로 불러와 입·출력핀을 추가하고 부록 A. Logisim_evolution을 이용한 논리회로 실습• 515 배선을 완료한 후 입력값을 변화시켜가면서 두 가산기의 출력이 모든 입력상황에 대하여 일치함 을 보여라. A.5.4. BCD Adder 10진 가산기(BCD Adder)는 입력이 4-비트의 BCD 코드로 표현된 수라는 전제하에 덧셈을 수행하 는 회로이다. 즉 입력신호는 0부터 9까지의 10진수만을 4-비트로 표현하고 있으므로 1010 ~ 1111 의 입력신호는 존재하지 않는다. 이러한 BCD 코드 입력신호를 일반적인 4-비트 병렬 가산기를 이 용하여 덧셈을 수행할 때는 특별한 보정 과정이 필요하게 되며 그 블록도는 [그림 A.28(a)]와 같다. 516 •디지털 논리회로 (a) BCD Adder 블록도 (b) Logisim-evolution에서 구현한 BCD Adder 회로 그림 A.28 BCD 가산기의 구조 및 Logisim-evolution을 이용한 구현 이를 [그림 A.28(b)]와 같이 4-비트 병렬 가산기 부회로 2개와 AND 게이트 및 OR 게이트를 사용 하여 Logisim-evolution에서 구현해 보고 동작을 검증해 보자. 실습 사항 ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘BCDAdder4’ 라는 이름으로 회로를 생성하고 캔버스에 ‘Add44_Bus’ 부회로를 2개 배치한다. ② 2개의 AND 게이트와 1개의 OR 게이트를 이용하여 6이 추가로 더해져야 하는 상황에 대한 보 정회로를 [그림 A.28(b)]와 같이 구성하고 입·출력 핀을 삽입하여 배선을 완료한다. ⑥ 아래와 같이 ‘BCDAdder_Test’ 회로를 생성하고 BCDAdder4 부회로를 컴포넌트로 불러와 입력 및 출력핀을 추가하고 선을 연결한 후 표에 주어진 입력 조합에 대한 출력값을 구하라. A.5.5. Encoder 와 디코더 인코더 [본문 7.4.2]에서 설명한 인코더는 또는 그 이하의 입력과 개의 출력으로 구성되며 기능은 유 부록 A. Logisim_evolution을 이용한 논리회로 실습• 517 일하게 하나의 입력만을 받아서 그에 대응되는 -비트 2진수를 출력한다. BCD 인코더는 10개의 입력 D(D0부터 D9까지)에 대한 4-비트의 BCD 코드(A,B,C,D)를 출력하는 회로로써 진리표는 [본 문 그림 7.34]와 같고 출력 부울함수를 통해 얻어진 회로도는 [본문 그림 7.35]와 같다. 이를 [그림 A.29]와 같이 2, 4, 5 입력 OR 게이트를 사용하여 Logisim-evolution에서 구현해 보고 동작을 검증해 보자. 그림 A.29 Logisim-evolution을 이용한 BCD Encoder 구현 실습 사항 ① 프로젝트 메뉴에서 ‘add circuit’을 선택하거나 툴바에서 아이콘을 클릭한 후 ‘BCDEncoder’ 회로를 생성한다. ② 입력핀을 Data Bits = 10으로 설정해서 배치하고 핀 이름을 D로 설정한다. 이때 입력핀이 10비트의 값을 모두 표현하려면 매우 길어져야 하므로 8-비트 이상이 되면 16진수로 표현됨을 확인하라. ③ Wiring 라이브러리의 스플리터를 가져와서 Bit Width In = 10, Fan Out = 10으로 설정하고 방향은 South, Left-handed 로 속성을 주고 spacing = 2로 하여 [그림 A.29]와 같이 배치한다. ④ 2-입력 OR 게이트 1개, 4-입력 OR 게이트 2개, 5-입력 OR 게이트 1개를 Gates 라이브러리 에서 가져와서 배치하고 스플리터의 비트 선과 연결한다. (게이트의 입력 개수는 속성창에서 수 정할 수 있음) ⑤ 출력핀을 4비트로 설정하고 이름을 BCD로 부여한 후 4-비트 스플리터를 이용하여 연결을 완료 한다. ⑦ 아래와 같이 main 회로에서 ‘BCDEncoder’ 회로를 컴포넌트로 불러와 10개의 스위치를 의미하 는 입력 및 출력핀을 추가하고 선을 연결한 후 각 스위치를 켰을때의 BCD 출력값을 확인하라. (참고로 아래 그림은 SW9가 1일 때 BCD 출력으로 9에 해당하는 1001이 나옴을 보인다.) 518 •디지털 논리회로 우선순위 인코더 우선순위 인코더는 모든 입력에 우선순위를 부여하는 인코더로써, 2개 이상의 입력이 들어왔을 때 우선순위가 높은 입력신호를 처리하여 출력을 생성한다. 그리고 무 입력인 상태와 인 상태를 구분하기 위하여 1개 이상의 입력신호에 대한 출력임을 나타내는 (valid) 출력을 함께 생성한다. 이번에는 위에서 구현한 바 있는 BCD 인코더에 우선순위를 부여하고 Valid 출력도 함께 생성하는 우선순위 BCD 인코더를 Logisim-evolution에서 구현해 보고 동작을 검증해 보자. 그림 A.30 우선순위 BCD Encoder 진리표 [그림 A.30]은 우선순위 BCD Encoder의 진리표를 나타낸다. 물론 앞의 실습처럼 진리표로부터 각 출력의 논리 함수를 간소화하여 구하고, 직접 필요한 게이트를 추가한 후 연결하여 회로를 구현할 수도 있지만, 이번 구현과정에서는 Logisim-evolution에서 제공하는 진리표를 이용한 논리합성 기 능을 사용하여 회로를 만들어 보는 경험을 해보도록 한다. 실습 사항 부록 A. Logisim_evolution을 이용한 논리회로 실습• 519 ① 개발창에서 아이콘을 클릭한 후 ‘BCDEncoderP’ 회로를 생성한다. ② Project 메뉴 → Analyze Circuit을 선택한 후, 입력변수 추가항목에 D를 입력하고 비트 수를 10으로 선택한다. ③ 출력변수 추가항목에 4-비트의 BCD 변수와 Vaid 변수 V를 추가한 후 Table 탭을 누른다. ④ Table 탭에서는 설계하고자 하는 조합 논리회로의 진리표를 입력할 수 있다. Show All Rows를 누르면 모든 입력 조합(1024가지)에 대한 진리표를 작성할 수 있고 Collapse Duplicated Rows 를 누르면 마치 프로그래밍 언어의 조건 분기문(if ~ else if ~ else)처럼 진리표 작성이 가능하 다. 우선 진리표에서 D9에 해당하는 칸을 클릭한 후 1을 써넣으면 D9이 1인 경우와 0인 경우로 진리표가 분기된다. 520 •디지털 논리회로 ⑤ 분기된 두 행 중에 아래 행에 해당하는 (D9=1) 출력란에 BCD 값에 해당하는 1001을 써넣고 유효한 입력임을 알리는 V 출력도 1로 작성한다. 두 번째 행의 D8~D0 입력이 ‘-’로 표시된 것은 무관항(Don’t Care)으로 처리하겠다는 의미이다. ⑥ 이제 D9=0인 첫 번째 행의 D8항에 1을 써넣으면 아래 그림 (a)와 같이 D8 =0인 경우와 D8=1 인 경우로 진리표가 다시 분기된다. 분기된 두 번째 행(D9:D8=01)의 출력에 BCD=1000과 V=1을 작성한다. 다음으로 D9:D8=00인 첫 번째 행의 D7 칸에 1을 써넣어서 (b)와 같이 분기 시킨 후 D9:D7=001인 행의 출력에 BCD=0111과 V=1을 쓴다. 이 방법을 계속 진행하면서 D9:D6=0001인 행에 BCD=0110과 V=1을 쓰면 (c)와 같고 D9:D5=00001인 행에 BCD=0101 과 V=1을 쓰면 (d)와 같다. (a) D9:D8=01 (b) D9:D7=001 (c) D9:D6=0001 (d)D9:D5=00001 최종적으로 작성된 진리표는 아래와 같다. ⑦ 이제 무관항이 포함된 진리표를 간소화하는 명령은 아래 Optimize minterms 버튼을 누르면 된 다. 간소화 과정에서 최소항의 합 혹은 최대항의 곱으로 표현하고 싶은 상황에 따라 Optimize 부록 A. Logisim_evolution을 이용한 논리회로 실습• 521 maxterms를 누를 수도 있다. 아래 (a)와 같이 최적화 과정에 오랜 시간이 걸릴 수 있다는 경고 문구가 나오는데 ‘Yes’를 누르면 (b)와 같이 터미널 창이 뜨면서 최적화 과정이 보여진다. 최적 화가 끝나면 창 밑쪽에 “Finished optimizing logic function, click here..” 부분이 보이는데 클릭 하면 다시 Analyze Circuit 창으로 돌아온다. (a) Optimize minterms 경고 문구 (b) 최적화 단계과정 ⑧ Build Circuit 버튼을 누르면 아래와 같은 창이 나오며 OK 버튼을 누르면 현재 회로인 ‘BCDEncoderP’ 캔버스에 합성된 회로를 그려준다. 522 •디지털 논리회로 ⑧ 아래와 같이 main 회로에서 ‘BCDEncoderP’ 회로를 컴포넌트로 불러와 입·출력핀 추가 및 배선 을 완료한 후, 각 스위치를 중복해서 켰을 때의 BCD 출력값을 확인하고 아무 SW가 눌리지 않 았을 때의 Valid 출력도 확인하라. 디코더 [본문 7.4.1]에서 다룬 디코더는 인코더의 역기능을 수행하는 것으로 -비트의 2진 입력을 개의 출력 중 하나로 변환해 주는 조합회로이다. 디코더는 임의의 입력신호에 대하여 오직 한 개의 출력 만 1의 값을 가진다. 아래 그림은 [본문 그림 7.21]에 해당하는 2x4 디코더의 logisim-evolution 구현 회로이다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 523 이번에는 Logisim-evolution의 논리회로 합성 기능 중에 진리표를 작성하는 방식이 아니고 직접 부울함수를 입력변수의 논리식으로 표현하는 방식을 사용하여 디코더를 설계하여 보도록 하자. 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘Decoder2x4’ 회로를 생성한다. ② Project 메뉴 → Analyze Circuit을 선택한 후, 입력변수 추가항목에 A, B를 입력하고 출력변수 추가항목에 D0, D1, D2, D3를 각각 입력한다. ③ Expression 탭을 선택 후, ⋅ 에 해당하는 논리식을 직접 작성한다. 즉 ‘D0 = 0’ 표현 식을 더블클릭한 후 D0 = ~A (공백) ~B를 써넣고 Enter 키를 치면 된다. 여기서 ~는 반전(인버 터)의 의미이며 (공백)은 논리곱의 표현이다. (참고로 + 문자는 논리합을 나타낸다.) 524 •디지털 논리회로 ④ ⋅ ⋅ ⋅ 에 해당하는 논리식을 전부 작성한다. ⑤ Build Circuit 버튼을 클릭하여 합성된 논리회로가 ‘Decoder2x4’ 캔버스에 자동으로 배치되도록 한다. ⑥ 자동합성된 Decoder2x4의 회로 캔버스 상에서 입력 조합을 변경시켜 가면서 출력신호가 어떻 게 바뀌어 가는지를 확인하고 디코더의 동작을 이해한다. ⑦ 다음과 같이 Project 메뉴 → Analyze Circuit을 선택한 후, En 입력을 추가해 주고 Expression (혹은 진리표)을 수정한 후 ‘Build Circuit’ 버튼을 클릭해서 인에이블이 추가된 2x4 디코더 회로 로 수정하라. 그리고 인에이블 신호 값에 따른 디코더의 동작을 확인하라. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 525 BCD to 7 세그먼트 디코더 [본문 7.4.1]에서 함께 소개한 BCD to 7 세그먼트 디코더는 [본문 그림 7.30]과 같이 BCD 코드로 표현된 10진수 4-비트( )를 입력받아서 그 입력값에 해당하는 10진수 숫자가 7 세그먼트 에 나타날 수 있도록 세그먼트 제어 신호 7-비트( ∼ )를 생성하는 회로이다. Logisim-evolution으로 이 디코더를 구현하는 방법은 [본문 표7.7]의 진리표를 이용해도 되고 [본 문 그림 7.31]을 통해 얻은 간소화된 부울함수 식을 이용해도 된다. 앞 실습과 같이 부울함수 식을 활용해서 세그먼트 디코더를 구현해 보자. 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘BCD2SEGDecoder’ 회로를 생성한다. ② Project 메뉴 → Analyze Circuit을 선택한 후, 입력변수 추가항목에 A, B, C, D를 입력하고 출 력변수 추가항목에 a, b, c, d, e, f, g를 각각 입력한다. 526 •디지털 논리회로 ③ [본문 7.4.1]에 나와 있는 BCD to 7 Segment Decoder의 각 출력에 대한 부울함수를 Expression 탭에서 직접 작성한다. ④ 하단의 ‘Build Circuit’ 버튼을 누르면 주어진 부울함수 식에 대한 회로가 자동적으로 합성되어 캔버스에 나타난다. 여기서 입력변수 이름과 출력변수 이름이 대소문자만 다르고 A, B, C, D가 같아서 일부 입력과 일부 출력만 나와 있다. 이 경우 아래 오른쪽과 같이 입력을 BCD[3:0]의 버스 형태로 스플리터를 사용하여 변환하고 빠진 출력변수 이름을 채워주면 된다. ( 아니면 처음 부터 입력 및 출력변수 이름이 같은 경우는 입출력 이름을 다르게 가져가면 이런 문제는 발생하 지 않는다. 단지 본문 내용과 변수 이름을 맞추려다 보니 이런 현상이 생긴 것을 알기 바란다.) 부록 A. Logisim_evolution을 이용한 논리회로 실습• 527 ⑤ ‘BCDEncDec_Test’ 회로를 생성하고 BCDEncoderP와 BCD2SEGDecoder를 컴포넌트로 불러 와 아래와 같이 배치한다. 10개의 입력핀 SW0~SW9을 BCDEncoderP로 연결하고 출력 BCD 코드를 BCD2SEGDecoder의 입력으로 연결한다. 그리고 BCD2SEGDecoder의 출력 (a ~ g)를 Explore pane의 Input/Output 라이브러리에 있는 7-Segment Display 모듈과 연결한다. 7-세그먼트는 [본문 그림 7.29]와 같이 (a~g)의 입력신호 조합에 따라 수를 표현하는 장치이며 Logisim-evolution Input/Output 라이브러리 내의 7-세그먼트 입력 핀 순서는 아래와 같다. 비교를 위해서 Input/Output 라이브러리의 ‘Hex Digit Display’ 모듈을 함께 가져와 BCD 코드 4-비트와 연결해 주었다. 16진수 표시장치는 4-비트 데이터 선을 16진수로 변환하여 보여주는 디스플레이 장치라고 생각하면 된다. ⑥ 위 BCDEncDec_Test 회로에서 입력 스위치값을 바꾸어 가면서 BCD Encoding 된 값이 7 세그 528 •디지털 논리회로 먼트 구동을 위한 제어 신호 (a~g)로 디코딩되어 스위치에 해당하는 10진수 값이 잘 표현되고 있는지 확인한다. 또한, 16진수 표시장치가 마치 세그먼트 디코더와 7 세그먼트를 병합한 모듈 과 같은 기능을 수행하는 것인지도 확인토록 한다. 추후 Hex Display는 마치 C-언어의 printf( ) 함수처럼 신호선을 모니터링하기 위해서 많이 사용될 것이다. ⑦ BCD2SEGDecoder는 BCD Encoder의 Valid 신호 V를 사용하지 않고 있다. 이를 확장하여 V = 1인 상태에서만 세그먼트 디코더 출력이 활성화되고 V = 0이면 모든 세그먼트 LED가 꺼지도 록 하는 ‘BCD2SEGDecoderP’ 회로를 생성하고 BCDEncoderP 회로와 결합하여 Valid 신호의 역할을 함께 검증하도록 하라. A.5.6. 멀티플렉서와 디멀티플렉서 멀티플렉서(MUX) 멀티플렉서는 여러 개의 입력신호 중에서 하나를 선택하여 출력 선에 연결하는 조합회로이다. 선택 신호에 따라서 선택된 입력신호가 출력으로 전달되므로 선택기(Selector)라고도 하며 줄여서 먹스 (Mux)라고도 표현한다. [A.3.4]에서 부회로를 이용한 Logisim-evolution의 계층적 회로 설계를 소개하면서 비트 단위의 2x1 MUX 및 4x1 MUX를 예제로 구현해 보았었다. 이번 실습에서는 앞에서 설계한 4-비트 병렬 2x1 MUX가 담겨있는 ‘LSE_Turorial’ 프로젝트 회로들을 라이브러리로 등록하고 부회로로 가져와 8-비트 병렬 2x1 MUX 및 4x1 MUX를 구현해보도록 한다. 실습 사항 : (8비트 병렬 2x1 MUX) ① Project 메뉴 → Load Library →Logisim evolution Library를 클릭한 후, LSE_Tutorial.circ 파 일을 선택하고 OPEN을 클릭한다. 클릭하면 다음과 같은 오류 메시지가 뜬다. 이 의미는 LSE_Tutorial이라는 프로젝트 파일 내에도 main이라는 이름의 회로가 존재해서 현재 프로젝트 내의 main 회로와 이름이 겹친다는 의미이다. 이는 마치 C 프로그램에서 다른 파일에 작성된 함수를 불러와서 컴파일하려 할 때 다른 파일 내에 main 함수가 또 있으면 안 되는 것과 비슷한 맥락이다. 따라서 LSE_Tutorial 프로젝트 파 일을 더블클릭해서 열고 main 회로를 다음과 같이 지워준 후 저장한다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 529 다시 현재 프로젝트(Combinational_Circuit)에서 라이브러리를 로드해 보면 explore pane의 내 장 라이브러리 맨 마지막에 사용자가 추가한 LSE_Tutorial이라는 라이브러리가 보인다. ② 개발창에서 아이콘을 클릭한 후 ‘Mux2in1_8Bit’ 회로를 생성한다. ③ 캔버스에 LSE_Tutorial/Mux2in1_4Bit_B를 부회로로 가져와 2개를 배치하고 8-비트 입력 핀 A, B, 그리로 선택 입력핀 Sel을 추가한 후 아래와 같이 연결한다. 또한, 8-비트 출력핀 F도 연 결해준다. ④ A와 B 입력으로 서로 다른 두 값을 설정하고 Sel 신호를 변화시켜 출력의 멀티플렉스 기능을 확인하라. (위에서는 10101010과 01010101의 입력에 대해 Sel=0 에 의한 10101010이 출력되 고 있음을 보여준다.) 실습 사항 : (8비트 병렬 4x1 MUX) ① 개발창에서 아이콘을 클릭한 후 ‘Mux4in1_8Bit’ 회로를 생성하라. ② Mux2in1_8Bit 부회로를 3개 가져와서 아래와 같이 연결한다. 선택신호 Sel1, Sel0가 각각 어떤 출력을 선택하는지 유념해서 연결하도록 하라. 530 •디지털 논리회로 ③ 외형 편집창을 눌러서 외형이 회로의 기능과 입출력을 모두 표현할 수 있도록 아래 왼쪽과 수정 하고, 편집창을 빠져나온 후 Mux4in1_8Bit의 속성 창에서 기본 외형을 Custom으로 설정한다. ④ ‘Mux4in1_8Bit_Test’ 회로를 생성하고 Mux4in1_8Bit을 부회로로 불러온 후 입·출력 핀을 연결 한다. ⑤ 서로 다른 네 개의 8-비트 데이터를 Din0, Din1, Din2, Din3의 입력값으로 설정하고 Sel1:Sel0 신호를 변화시켜가면서 8-비트 4 in 1 멀티플렉서 기능을 확인하라. 디멀티플렉서(DEMUX) [본문 7.5]에서 설명한 디멀티플렉서는 멀티플렉서와 반대되는 기능의 디지털 회로로써 1개의 입력 을 개의 선택 신호에 따라 중의 한 개 출력으로 내보내는 기능을 수행한다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 531 이번 실습에서는 1-비트의 입력과 2-비트의 선택 신호로 4개 중의 하나의 출력으로 입력이 전달되 는 1x4 디멀티플렉서를 Logisim-evolution의 진리표를 이용한 논리합성 기능을 이용하여 구현해 보도록 한다. 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘DMUX1to4’ 회로를 생성한다. ② Project 메뉴 → Analyze Circuit을 선택한 후, 입력변수 항목에 DMin, SEL(2 Bit)을 추가하고 출력변수 항목에 DMUX의 출력으로 DM0, DM1, DM2, DM3를 각각 추가한다. ③ Table 탭을 선택하여 DMin = 0일 때는 Sel과 관계없이 모든 출력이 0이 되도록 하고 DMin=1 일 때는 Sel[1..0]의 값에 따라 선택된 출력값이 1이 되도록 진리표를 작성한다. ④ 혹은 직접 Expression 탭에서 아래와 같이 각 출력에 대한 논리식을 작성해 줄 수도 있다. 532 •디지털 논리회로 ⑤ Build Circuit 버튼을 누르면 아래와 같은 디먹스 회로가 생성되어 캔버스에 배치된다. ⑥ 외형 편집창을 열고 DMUX1to4의 외형을 아래와 같이 편집한다. 외형 변경이 끝나면 편집창을 빠져나온 후 속성에서 외형을 ‘Custom’으로 설정해준다. ⑦ ‘DMUX_Test’라는 이름으로 새 회로를 생성하고 주어진 ‘DMUX1to4’ 회로를 컴포넌트로 불러 와서 아래와 같이 입·출력 핀을 연결한 후 디멀티플렉서의 동작을 확인하라. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 533 A.5.7. ALU 지금까지 간단한 산술 연산(덧셈, 뺄셈) 및 논리연산(AND, OR, NOT, XOR, XNOR,...)을 수행하 는 조합회로의 설계에 대하여 다루었다. ALU는 Arithmetic and Logical Unit의 준말로 동작 제어 신호에 따라서 2개 혹은 1개의 데이터 입력에 대해 산술 연산 혹은 논리 연산을 수행하고 그 결과를 출력하는 순수 조합회로이다. ALU는 제어 신호의 비트 수에 따라서 수행할 수 있는 연산의 개수가 정해진다. 이번 실습에서는 아래 그림과 같이 2-비트의 제어 신호를 이용하여 4가지 중의 한 가지 기능을 수 행하는 간단한 8-비트 ALU를 Logisim-evolution을 이용하여 구현하여 보고자 한다. 실습 사항 ① ALU에서 사용할 연산기 중에 8-비트 AND 연산기는 지금까지 만들지 않았다. ‘AND8’ 이라는 이름의 새 회로를 생성하고 2-입력 AND 게이트를 8개 가져와서 아래와 같이 8-비트 입력핀 2개와 스플리터, 그리고 8-비트 출력핀을 사용하여 간단히 생성한다. 534 •디지털 논리회로 ② 개발창에서 아이콘을 클릭한 후 ‘ALU8’ 회로를 생성하고 [A.5.1]에서 설계한 8-비트 가산 기(Adder8), ①에서 만든 8-비트 AND 연산기(AND8), 그리고 [A.5.6]에서 설계한 8-비트 4x1 멀티플렉서(Mux4in1_8Bit)를 부회로로 가져와서 캔버스에 배치하고 아래와 같이 연결한다. ③ 여기서 기능 선택을 수행하는 Fn 입력은 00일 때 8-비트 “0000 0000”을 선택하고 01일 때 A 입력을 선택하며 10일 때 A와 B의 덧셈 결과를 그리고 11일 때 A AND B의 결과를 선택한다. MUX의 출력은 OE 제어 신호로 동작하는 3-상태 버퍼를 통과하여 출력 TALUout으로 나가며 모니터링을 위해 MUX 출력도 출력핀 ALUout으로 함께 나가도록 한다. ④ 외형 편집기 창을 열고 일반적인 ALU를 연상하는 외형으로 다음과 같이 수정한다. ⑤ ‘ALU8_Test’ 회로를 생성하고 ALU8을 부회로로 가져온 후 필요한 입·출력 핀을 연결한다. 또 한 모니터링을 위해 16진수 표시장치를 2개 스플리터와 연결하여 3상 버퍼 출력 전/후의 ALU 부록 A. Logisim_evolution을 이용한 논리회로 실습• 535 출력에 각각 연결한다. ⑥ 아래 표에 주어진 RegA 와 RegB 및 Fn 입력에 대한 ALU의 출력값을 작성하고 ALU가 올바른 기능을 수행하는지 확인하라. 이때 OE =1로 설정한다. 실습 요약 다양한 조합회로를 Logisim-evolution 으로 구현해 보면서 본문에서 살펴본 회로의 특성을 실 습으로 직접 확인할 수 있었다. 같은 덧셈 연산을 수행하는 덧셈기라도 올림수 미리보기 같은 조금 더 복잡한 구조를 사용하면 지연시간이 짧아 고속동작이 가능하다는 것을 두 덧셈기의 등가동작을 통해 알아 볼 수 있다. 멀티플렉서/디멀티플렉서의 기능을 이해하고 다양한 방법을 통해서 구현함을 알 수 있었다. 즉 ① 직접 진리표를 작성하고 그로부터 출력의 논리식을 간소화 해서 얻어낸 후 게이트로 구현하 는 방법, ② 프로젝트 메뉴의 Analyze Circuit 항목에서 Table 탭을 선택하고 진리표를 기입한 후 자동합성을 요청하는 방법, ③ Analyze Circuit 항목에서 Expression 탭을 선택하고 간소화 되지 않은 논리식을 직접 적어주고 자동 간소화를 수행하고 합성하도록 요청하는 방법. 4간단한 8-비트 ALU의 구현을 통해 기능 선택 핀에 의해 원하는 출력이 나올 수 있도록 하는 법을 알 수 있고 필요하면 더 많은 기능들을 추가하도록 확장하는 것이 가능함도 알 수 있다. 536 •디지털 논리회로 A.6. Logisim-evolution을 이용한 순차회로 구현 및 테스트 이번 장에서는 본문 8장, 9장에 걸쳐 소개한 다양한 순차회로를 Logisim으로 구현해 보고 그 동작 을 확인하여 보도록 한다. A.6.1. SR 래치 [본문 8.1.2]에서 소개한 SR 래치를 Logisim-evolution(LSE)으로 구현해 보면 아래와 같다. 위 그림에서 보듯이 NOR 게이트의 출력이 Undefined에 해당하는 빨간색으로 표현되어 있다. 실제 게이트라면 전원이 들어오는 순간 ‘NOR1’의 출력 가 0이든 1이든 정해져 있을 것이고, 그 값으 로부터 (logisime-evolution에서는 보수 표현이 안되서 nQ라고 하기로 함) 값이 결정되게 되어 있다. LSE에서는 이런 상황을 지원하지 않아 Undefined로 나타내고 있는 점이 아쉬운 면이다. 이 모호성을 해결하는 한 가지 방법은 S 혹은 R 입력을 1로 설정해서 한쪽 게이트의 출력값을 확실 하게 결정해 주면 된다. 예를 들어 R 값을 1로 변경하면 아래와 같이 모호성이 제거되면서 정상적 인 래치 기능을 수행하게 된다. 이후부터는 임의의 입력에 대해서도 본문에서 언급한 동작을 하게 된다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 537 실습 사항 ① SR 래치 회로를 위 그림처럼 구현하고 아무 입력을 토글시켜 모호성을 제거하라. ② SR = 10을 입력하여 출력 Q가 세트(1) 되는지 확인하라. ③ SR = 00을 입력하여 이전 출력 Q가 그대로 유지 되는지 확인하라. ④ SR = 01을 입력하여 출력 Q가 리셋 (0) 되는지 확인하라. ⑤ SR = 00을 입력하여 이전 출력 Q가 그대로 유지 되는지 확인하라. ⑥ 금지 입력 SR = 11을 입력하여 출력 Q, nQ 의 값을 확인하라. ⑦ [본문의 8.1.3]과 같이 NAND 게이트 2개를 이용하여 SR 래치를 구현하고 Active Low 형태의 SR 입력에 대한 출력값을 확인하라. A.6.2. 인에이블이 추가된 SR 래치 [본문 8.1.4]에서 소개한 인에이블(Enable) 기능이 추가된 SR 래치를 Logisim-evolution으로 구현 해 보면 아래와 같다. SR 래치와 마찬가지로 출력의 모호성 때문에 빨간색으로 두 출력 Q, nQ가 표현되고 있다. 모호성은 어느 특정 게이트의 출력을 확실하게 정해주면 되므로 En =1, S = 1로 설정해 주면 해소된다. 실습 사항 ① En 추가된 SR 래치 회로를 위 그림처럼 구현하고 모호성을 제거하라. ② En = 1일 때 SR = 10을 입력하여 출력 Q가 세트(1) 되는지 확인하라. ③ En = 1일 때 SR = 00을 입력하여 출력 Q가 유지되는지 확인하라. ④ En = 1일 때 SR = 01을 입력하여 출력 Q가 리셋(0) 되는지 확인하라. ⑤ En = 0일 때 SR값과 관계없이 출력 Q는 이전 값을 유지하는지 확인하라. 538 •디지털 논리회로 A.6.3. D 래치 (with Enable) [본문 8.1.5]에서 설명한 D 래치를 Logisim-evolution으로 구현해 보면 아래와 같다. 출력의 모호 성은 En 신호를 1로 잠시 설정하면 해결된다. 실습 사항 ① En 추가된 D 래치 회로를 위 그림처럼 En이 추가된 SR 래치를 부회로로 채용하고 NOT 게이 트를 추가하여 구현하고 En 신호를 토글 시켜 모호성을 제거하라. ② En = 1일 때 D=1을 입력하여 출력 Q가 세트(1) 되는지 확인하라. ③ En = 1일 때 D=0을 입력하여 출력 Q가 리셋(0) 되는지 확인하라. ④ En = 0일 때 D 값과 관계없이 출력 Q는 이전 값을 유지하는지 확인하라. A.6.4. D 플립플롭 [본문 8.2.4]에서 설명한 주종형 D 플립플롭을 Logisim-evolution으로 구현해 보면 아래와 같다. 출력의 모호성은 CLK 펄스를 가하면 사라진다. 실습 사항 ① 주종형 D 플립플롭 회로를 위 그림처럼 인에이블이 추가된 D 래치 2개를 부회로로 채용하고 2개의 NOT 게이트를 사용하여 구현하라. ② 외형 편집기를 사용하여 DFF의 외형을 아래와 같이 편집하고 속성에서 외형을 Custom 타입으 로 변환하여 준다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 539 ③ D = 1로 설정한 상태에서 CLK가 상승 에지일 때 현재 입력 D가 출력 Q로 전달되는지 확인하 고 이후 입력신호가 변해도 출력 Q가 변하지 않는 사실을 확인하라. ④ D = 0으로 설정한 상태에서 CLK가 상승 에지일 때 현재 입력 D가 출력 Q로 전달되는지 확인 하고, 이후 입력신호가 변해도 출력 Q가 변하지 않는 사실을 확인하라. ⑤ 위 회로를 수정해서 하강 에지인 순간에 D 입력이 출력 Q로 전달되는 하강 에지 트리거 주종형 D 플립플롭도 구현하고 그 특성을 확인하라. A.6.5. JK 플립플롭 [본문 8.2.5]의 D 플립플롭을 이용한 JK 플립플롭을 Logisim-evolution으로 구현해 보면 아래와 같다. 출력의 모호성은 CLK 펄스를 가하면 사라진다. 실습 사항 ① JK 플립플롭 회로를 위 그림처럼 주종형 D 플립플롭을 부회로로 채용하고 2개의 AND 게이트 와 1개의 OR 게이트를 사용하여 구현하라. ② JK = 10으로 설정한 상태에서 CLK가 상승 에지일 때 출력 Q가 세트(1) 되는지 확인하라. 이후 JK 입력값이 변해도 출력 Q가 변하지 않는 사실을 확인하라. ③ JK = 01로 설정한 상태에서 CLK가 상승 에지일 때 출력 Q가 리셋(0) 되는지 확인하라. 이후 JK 입력값이 변해도 출력 Q가 변하지 않는 사실을 확인하라. ④ JK = 11로 설정한 상태에서 CLK가 상승 에지일 때 출력 Q가 토글되는지 확인하라. 이후 JK 입력값이 변해도 출력 Q가 변하지 않는 사실을 확인하라. 540 •디지털 논리회로 ⑤ 주종형 SR 플립플롭을 인에이블 기능이 있는 SR 래치를 2개의 부회로로 사용하여 구현해 보고 이어 JK 플립플롭을 SR 플립플롭을 부회로로 채용하여 구현한 후 그 특성을 확인하라. A.6.6. 내장 D 플립플롭(Builtin D-Flipflop) SR 래치부터 D 플립플롭에 이르기까지 게이트 출력를 피드백해서 지금까지 구현한 회로는 Logisim- evolution 프로그램 성격상 초기 undefined 출력 상태를 피할 수가 없다. 반면에 Explore pane의 메모리(Memory) 라이브러리에 있는 내장 D 플립플롭은 Java 언어를 이용하여 소프트웨어 로 구현되어서 초기 상태가 지정된 특징이 있다. 따라서 우리가 구현한 D 플립플롭과 내장 라이브 러리 D 플립플롭의 동작을 함께 비교하여 살펴보고, 그 특성이 같은지를 확인한 후에 이후 내장 라이브러리 D 플립플롭을 대신 사용하여 출력의 모호성을 없애고 나머지 실습을 진행하도록 하자. 실습 사항 ① 앞선 실습에서 구현한 D 플립플롭과 내장 메모리 라이브러리 내에 있는 ‘D Flip-Flop’ 컴포넌트 를 테스트를 위해 위 그림처럼 main 회로 캔버스에 배치한 후, 입력 D를 공통으로 인가하고 출력을 각각 연결한다. 그리고 Wiring 라이브러리에 Clock 컴포넌트를 캔버스로 가져와서 두 플립플롭의 클록 입력에 공통으로 연결하여 비교 테스트 환경을 만들도록 하라. ② 메뉴바의 Simulation 탭을 선택한 후 Auto-Tick Enabled를 활성화하면 주기적으로 클록 펄스 가 발생한다. 물론 입력핀을 연결하고 입력핀의 값을 마우스 클릭으로 변화시켜도 되지만 여러 개의 클록을 손으로 발생시키기에는 불편함이 따를 수 있다. 이럴 때 Auto-Tick을 사용하면 매 부록 A. Logisim_evolution을 이용한 논리회로 실습• 541 우 편리하다. Auto-Tick의 주파수는 Auto-Tick Frequency를 통해서 선택할 수 있다. 우선 몇 가지 주파수를 (1H, 2Hz, 16Hz, 64Hz)정도 변화시켜가면서 Auto-Tick의 동작을 눈으로 확인 하도록 하라. ③ Auto-Tick 이 동작하는 상황 속에서 D 입력을 변화시키면서 두 플립플롭의 출력 변화를 확인 하고 이를 통해서 두 플립플롭의 특성이 일치하는지를 판단하라. ④ [A.5.5]의 D 플립플롭을 이용한 JK 플립플롭의 구현에서 [A5.4]의 자체 설계 D 플립플롭 대신 에 내장 D 플립플롭을 대체 사용하여 그 특성을 확인해 보고 모호성에 관하여 확인하라. ⑤ 내장 D 플립플롭을 이용하여 T 플립플롭을 다음과 같이 구현하여 보고 외형도 편집한 후, 그 특성을 확인하라. A.6.7. 비동기식 카운터(Asynchronous Counter) 상승 에지형 비동기식 풀 카운터 [본문 9.3.6]의 내용을 참고하여 위에서 내장 D 플립플롭으로 만든 상승 에지형 T 플립플롭 4개를 사용하여 4-비트 리플 카운터를 다음과 같이 구현하여 보고 그 동작을 확인해 보도록 한다. 542 •디지털 논리회로 실습 사항 ① ‘ACounter16’이라는 이름으로 새 회로를 생성하고 [A.6.7]의 ⑤단계에서 만든 T 플립플롭을 4 개 가져와서 배치하고 첫 번째 플립플롭에 클록 입력핀을 연결, 이후는 플립플롭의 반전 출력을 다음 플립플롭의 클록으로 연결한다. ② Input/Output 라이브러리에서 16진수 표시장치를 가져와서 4-비트의 플립플롭 출력에 연결해 주고 4개의 출력핀을 연결한다. ③ F9을 이용하여 클록을 인가하면서 카운터가 0~15까지 증가하면서 계수하는지를 확인하라. ④ T 입력으로 논리 ‘1’이 연결되어 있던 것을 En 입력핀으로 대체한 후, En = 0 일때와 En = 1일 때의 카운터의 동작을 살펴보고 En 입력이 카운터의 인에이블 신호로 쓰일 수 있는지 검토 하라. 비동기식 MOD-N 카운터 [본문 9.3.8]의 내용을 참고하여 T 플립플롭 4개를 사용하여 MOD-10(BCD) 리플 카운터를 다음 과 같이 구현하여 보고 그 동작을 확인해 보도록 한다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 543 실습 사항 ① ‘ACounter10’이라는 이름으로 새 회로를 생성하고 Acounter16 회로를 캔버스에 복사해 온 후, [본문 그림 9.23]과 같이 의 출력을 AND 하여 플립플롭의 CLR 신호로 넣어준다. (T-플 립플롭의 CLR 입력이 Active-High임이 본문과 차이) ② En 핀을 모든 T 입력으로 연결하여 En = 1인 경우에만 카운터가 동작하도록 한다. ③ En = 1로 설정하고 F9을 눌러 클록을 인가하면서 카운터가 MOD-10 기능을 수행하는지 확인 하라. ④ UpDn 핀을 새로 추가하고 [본문 그림 9.8]을 참고하여 MOD-10 업/다운 카운터로 회로를 수 정하고 UpDn 값의 변화에 대한 카운터의 동작을 확인하라. A.6.8. 동기식 카운터 동기식 풀 카운터 [본문 9.4.2]의 내용을 참고하여 T 플립플롭 4개를 사용하여 동기식 4-비트 풀 카운터를 다음과 같이 구현하여 보고 그 동작을 확인해 보도록 한다. 실습 사항 ① ‘Scounter16’이라는 이름으로 새 회로를 생성하고 T 플립플롭 4개와 AND 게이트, 그리고 Wire 라이브러리의 Constant 모듈을 사용하여 4-비트 업 카운터를 구현하라. ② 메뉴→ Simulator의 Auto-Tick을 활성화해서 CLK 입력에 자동으로 클록을 공급하면서 4-비트 의 결과가 업 카운팅을 수행하는지 확인하라. ③ ‘Scounter16E’라는 이름으로 새 회로를 생성하고 Scount8회로를 복사해서 붙여넣기를 한 후, T 플립플롭의 T 입력이 0이면 상태를 유지하는 특성을 활용해서 En 핀을 추가된 4-비트 풀카운 터를 아래와 같이 구현하고 En 입력 신호에 따른 카운터의 동작을 검증하라. (참고로 T1, T0의 입력에 En 신호를 AND 하지 않아도 되는 이유에 대해서도 고민해보도록 한다.) 544 •디지털 논리회로 ④ [본문 9.4.5] 내용을 참고하여 동기식 4-비트 다운 카운터 회로를 구현하고 그 결과를 확인하라. ⑤ [본문 9.4.6]의 내용을 참고하여 동기식 4-비트 업/다운 카운터 회로를 새로운 핀 UpDn을 추가 하여 구현하고 Auto-Tick으로 자동 클록을 공급하면서 UpDn 핀의 값의 변화에 대한 카운터의 특성을 확인하라. ⑥ 인에이블 기능이 있는 4-비트 업/다운 카운터로 회로를 수정하고 En = 1일 때와 En = 0일 때의 동작을 비교하라. 동기식 MOD-N 카운터 [본문 9.4.7]의 내용을 참고하여 D 플립플롭 3개를 사용하여 동기식 MOD-6 카운터를 Logisim– evolution을 사용하여 구현하고자 한다. 다음 제시된 단계에 따라서 실습을 진행하라. 실습 사항 ① MOD-6 카운터의 상태도를 작성하라. ② 상태도를 통해서 본문의 [표9.6]과 같은 형식의 T 플립플롭 상태 여기표를 작성하라. ③ 카노맵을 활용하여 각 T 플립플롭의 최소화된 입력식 을 구하라. ④ 입력식을 기반으로 ‘SCounter6’ 라는 이름의 회로를 생성한 후 3개의 T 플립플롭과 입력식을 이용하여 배선을 아래와 같이 수행하고 F9으로 클록을 인가하면서 카운터의 특성을 확인하라. ⑤ ‘SCounter6E’ 라는 이름으로 새 회로를 생성하고 인에이블 기능이 있는 MOD-6 카운터를 버 부록 A. Logisim_evolution을 이용한 논리회로 실습• 545 스 출력핀으로 구현한 후, En =0과 En =1일 때의 클록 입력에 대한 카운터의 동작을 확인하라. A.6.9. 병렬 레지스터 [본문 9.6.2]와 같이 적재 기능이 있는 1-비트의 저장 공간을 생성하고, 이 모듈을 여러 개 이어붙 여서 멀티-비트 레지스터를 구현하려고 한다. 또한, 여러 개의 레지스터 출력이 하나의 버스에 연결 되는 상황에서 각 레지스터 간의 출력값이 충돌을 일으키지 않도록 3-상태 버퍼(Tri-State Buffer) 를 각 레지스터의 출력에 부착하고 출력 활성화(OE: Output Enable) 제어선을 통해서 선택받은 레지스터만 값을 버스에 출력하도록 하고자 한다. 다음 제시된 단계에 따라서 병렬 레지스터를 구 현하고 그 동작을 확인하도록 하자. 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘Rcell’이라는 이름으로 새 회로를 생성한다. ② [본문 그림 9.54]에 보인 로드 기능이 있는 DFF 구조를 참고하여 내장 D 플립플롭, [A.3.4]에서 만들었던 MUX_2x1 부회로, 그리고 내장 Gates 라이브러리에 있는 Controlled Buffer를 사용하 여 아래과 같이 구현하도록 한다. (MUX_2x1 회로를 사용하기 위해서는 이 회로를 포함하고 있는 LSE_Tutorial 프로젝트를 라이브러리로 추가해 주어야 한다.) ③ D =1, WE = 0, OE = 0으로 설정한 후, CLK를 인가해서 상승 에지에 D 입력이 플립플롭 546 •디지털 논리회로 Q로 저장되는지 확인하라. ④ D =1, WE = 1, OE = 0으로 설정한 후, CLK를 인가해서 상승 에지에 D 입력이 플립플롭 Q로 저장되는지 확인하라. 또한, Tout(Tri-state Output)과 Dout(D Flipflop Output)의 값을 각각 확인하라. ⑤ CLK와 상관없이 OE의 값이 0과 1일 때의 Tout과 Dout의 차이를 확인하라. ⑥ 개발창에서 아이콘을 클릭한 후 4-비트 레지스터를 나타내는 ‘Register4’ 회로를 생성하고 4개의 Rcell과 4-비트 입·출력 핀, 그리고 제어 신호(WE. OE) 입력핀을 이용하여 4-비트 레지 스터를 다음과 같이 구현한 후, Din에 1010과 WE = OE = 1로 설정하고 클록을 인가해서 TDout과 Dout에 출력이 전달되는지 확인하라. ⑦ 위의 4-비트 레지스터를 수정해서 8-비트 레지스터로 확장 구현하고 Din에 ‘0101 1010’을 입 력하고 WE = 0인 상태에서 클록 펄스에 대한 출력과 WE = 1인 상태에서의 클록 펄스에 대한 출력값을 비교 확인하라. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 547 ⑧ OE = 1로 변경하였을 때의 Tout, Dout 값과 OE = 0일 때의 Tout, Dout 값을 통해 OE의 기능을 다시 한번 확인하라. A.6.10. 레지스터 간 데이터 전달 입력의 저장을 제어하는 WE 신호와 출력을 활성화하는 OE 신호가 함께 있는 레지스터는 하나의 버스에 여러 개 동시에 연결되어 상호 간에 데이터를 이동시키는 것이 가능하다. 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘RegisterTransferTest’ 회로를 생성한다. ② [A.6.9]에서 설계한 8-비트 레지스터를 4개 배치하고 8-비트 입력 핀을 3-상태 버퍼를 거쳐서 모든 레지스터의 입력으로 버스선을 통해서 연결한다. 이 입력 포트는 외부에서 버스로 데이터 를 전달하는 의미로 생각하면 된다. 또한, 각 레지스터의 출력도 버스에 함께 연결한다. 각 레지 스터의 제어선 WE와 OE은 모두 다른 이름의 입력핀으로 연결한다. ③ 내부 라이브러리인 Input/Output에 속한 ‘Hex Digit Display’ 모듈을 가져와서 2개씩 레지스터 밑에 배치한다. 그리고 각 레지스터의 8-비트 데이터(Dout)를 스플리터를 사용하여 2개의 4-비 트 데이터로 나눈 후, 각각 Hex Digit Display에 연결한다. 앞서 언급했듯이 이 Display 장치는 멀티 비트 혹은 버스의 값을 관찰할 때 매우 유용하다. ④ 입력포트의 값을 “0000 0001”로 설정하고 Din_OE = 1로 설정해서 입력값이 버스에 연결되도 록 하고 첫 번째 8-비트 레지스터인 A_Register의 WE = 1로 설정하여 Din => RA로의 전달을 위한 환경을 구축한다. 이후 CLK를 인가하여 데이터 전달이 잘 되는지 확인한다. ⑤ 입력값을 16진수로 0x03, 0x07, 0x0F로 각각 설정하고 이 값을 RB, RC, RD에 매 클록에 전달 이 되도록 B, C, D 레지스터의 WE를 잘 설정하고 클록을 인가하여 데이터 전달이 잘 되었는지 확인한다. 548 •디지털 논리회로 ⑥ 이제 RD => RA로 데이터 이동을 위한 D 레지스터의 제어 신호와 A 레지스터의 제어 신호를 적절하게 설정하고 입력 포트의 3-상태 버퍼를 닫은 후(Din_OE=0), 클록 펄스를 가하여 RA에 데이터 0x0F가 잘 전달되었는지 확인한다. ⑦ RC => RB로 데이터 이동을 위한 C 레지스터의 제어 신호와 B 레지스터의 제어 신호를 적절 하게 설정하고 클록 펄스를 가하여 RC의 데이터 0x07이 B 레지스터에 잘 전달되었는지 확인 한다. ⑧ 이상의 레지스터 전달과정을 통해서 Rx -> Ry 로 데이터 전달을 위한 규칙적인 제어 신호 설정 방법을 터득하고 실제적인 전달은 다음번 상승 에지 클록인 순간에 이루어짐을 확인하라. A.6.11. 레지스터 파일과 데이터 버스 [A.6.10]을 통해서 병렬 레지스터의 구조와 레지스터 간의 데이터 전송에 관하여 실습을 수행하였 다. 이번 실습에서 다루어 볼 내용은 [본문 9.6]과 [본문 9.7.3]에서 소개한 여러 개의 레지스터가 병합되어 작은 메모리를 구성하는 형태를 가지는 레지스터 파일의 구성과 동작 특성이다. 이 레지 스터 파일은 컴퓨터의 중앙 처리 장치(CPU: Central Processing Unit)를 구성하는 중요한 요소이며 레지스터 파일의 비트 수가 바로 N-비트 CPU의 N 값에 해당한다. 그림 A.31 컴퓨터 중앙 처리 장치의 내부 구조 [그림 A.31]에서 보듯이 레지스터 파일은 두 개의 출력부를 가진다. 예를 들어 4개의 레지스터로 구성된 레지스터 파일이 있다면 첫 번째 그리고 두 번째의 출력부는 각각 독립적으로 4개 중의 한 부록 A. Logisim_evolution을 이용한 논리회로 실습• 549 개의 레지스터 값을 출력한다. 이 두 개의 출력은 ALU를 통하여 산술/논리 연산을 수행하게 되고 그 결과는 다시 레지스터 파일의 입력으로 피드백되어 지정하는 레지스터에 저장된다. 이번 실습에서는 8-비트 레지스터 4개로 구성된 레지스터 파일을 Logisim-evolution을 통하여 구 현해 보고 레지스터 간의 데이터 이동 및 [A.5.8]에서 설계한 간단한 ALU를 연결하여 두 레지스터 값의 간단한 연산 과정 및 결과의 저장과정을 살펴보도록 한다. 레지스터 파일의 구현 및 동작 테스트 실습 사항 ① 개발창(Explore pane)에서 아이콘을 클릭한 후 ‘RegisterFile’ 회로를 생성한다. ② [A.6.9]에서 설계한 8-비트 레지스터 4개를 아래 그림과 같이 캔버스에 배치하고 클록 입력 핀 을 추가해서 모든 레지스터에 연결하며 8-비트 입력 데이터 핀(Rin)도 모든 레지스터의 Din에 연결한다. WE (Load의 의미)핀을 추가하고 [A.5.7]에서 설계한 1x4 디멀티플렉서(DMUX)를 연결한 후 4개의 DMUX 출력을 각각의 레지스터 WE 입력으로 연결한다. 이때 선택 신호를 위한 2-비트 입력핀(ASel)도 추가해서 DMUX의 Sel 입력에 연결하는 것을 잊지 말도록 한다. ③ 4개의 레지스터에 입력 데이터가 잘 적재(저장)되는 것을 확인하기 위해 출력에 2개의 16진수 표시장치를 각각 연결한 후, WE = 1, Rin = 0x01, ASel = 00을 설정하고 클록을 인가하여 R0 에 0x01이 잘 저장되는지 확인한다. 마찬가지로 Rin = 0x03, 0x07, 0x0F, ASel = 01, 10, 11로 같이 변화시키면서 클록을 인가하여 R1, R2, R3에 0x03, 0x07, 0x0F 가 저장되는지 확인한다. ④ [A.5.7]의 ⑤에서 설계한 MUX4x1_8Bit 부회로를 2개 가져와서 아래 그림과 같이 MUX 입력 을 4개의 레지스터의 3-상태 버퍼를 거치지 않은 출력과 연결한다1). 두 MUX의 출력 Aout과 1) [그림 A.32]와 같이 레지스터 파일의 두 출력은 ALU의 입력으로 직접 들어가고 ALU 출력이 버스에 연결되는 구조이므로 ALU 출력에만 3-상태 버퍼를 두어 버스와 연결하면 된다. 550 •디지털 논리회로 Bout은 ASel과 BSel 입력신호에 의해서 선택되는 독립적인 레지스터 파일 내의 특정 레지스터 출력이 된다. 내부 레지스터값을 관찰하기 위해서 각 레지스터 출력을 MonR0부터 MonR3까지 출력핀으로 뽑아두면 후에 레지스터 동작을 확인하기에 편하다. 위 회로에서 ASel 신호는 출력신호를 선택하는 데 사용됨과 동시에 저장할 레지스터를 선택하는 데도 사용되도록 연결되었다. 물론 레지스터 파일로 입력되는 데이터를 저장할 레지스터를 선택 하는 신호도 독립적으로 만들 수 있지만, 그 경우 선택 신호가 너무 많아져서 사용하기 불편하 다. 따라서 레지스터 파일의 동작은 A 레지스터와 B 레지스터의 내용을 가져와서 적절한 연산 (산술 혹은 논리 등)을 수행한 후에 다시 같은 A 레지스터에 저장되는 것으로 이해하도록 하자. (예를 들면 A← A+B, B← B AND C, ...) ⑤ 완성된 레지스터 파일 회로의 동작을 살펴보기 위해 실습 사항 ③과 같이 4개의 레지스터에 0x01, 0x03, 0x07, 0x0F 데이터를 저장해 놓은 후 ASel과 BSel 신호를 변화시켜가면서 각각 Aout과 Bout으로부터 선택된 레지스터값이 올바로 추출되는지 확인하라. 레지스터 파일과 ALU의 조합 테스트 실습 사항 ① 개발창(Explore pane)에서 아이콘을 클릭한 후 ‘RegFileTest’ 회로를 생성한 후 RegisterFile 과 ALU8 부회로를 컴포넌트로 가져와 캔버스에 배치시키고 아래와 같이 연결하라. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 551 ② 우선 레지스터 파일 내의 4개의 레지스터에 0x01, 0x03, 0x07, 0x0F의 데이터를 채우기 위해 앞의 실습 ⑤번 과정과 같이 Din 값을 주면서 Din_OE = 1, RegFile_WE = 1, ASel = 00, 01, 02, 03과 같이 설정한 후 클록을 인가하고 저장된 결과를 16진수 표시 장치를 통하여 확인하라. ③ 레지스터 파일에 데이터가 다 채워졌다고 가정하고, 이번에는 ALU 연산을 수행하여 그 결과를 레지스터에 다시 저장하는 과정을 확인하라. ASel = 00, BSel = 01로 설정하여 레지스터 R0와 R1을 ALU의 두 입력 A, B로 연결 ALU_Fn = 10으로 설정하여 덧셈 연산이 수행되도록 함 ALU 출력이 버스로 연결되도록 ALU_OE = 1로 세팅 이 때 버스에 물려있는 Din_OE = 0 이 되어야 입력핀 데이터와 ALU 출력 간의 충돌이 발 생하지 않음 ALU가 R0 + R1 = 0x01 + 0x03 = 0x04의 결과를 내서 버스에 담음을 확인 RegFile_WE = 1로 설정하고 클록을 인가 버스에 담겨있던 0x04의 데이터가 ASel에서 설정한 00에 의해 다시 R0로 저장이 되는 것을 확인 ④ 위 상태에서 R2← R2 + R3의 연산이 이루어지도록 제어 신호를 적절히 제공하고 클록을 인가 552 •디지털 논리회로 하여 R3에 원하는 값이 저장되었는지 확인하라. (0x07+0x0F = 0x16) ⑤ 위 상태에서 R2← R2 AND R3의 연산이 이루어지도록 제어 신호를 적절히 제공하고 클록을 인가하여 R3에 원하는 값이 저장되었는지 확인하라. (0x16 AND 0x0F = 0x06) A.6.12. 시프트 레지스터를 이용한 직렬 가산기 구현 4-비트 시프트 레지스터 실습 사항 ① ‘ShiftRegister4’라는 이름으로 새 회로를 생성한 후 인에이블 기능이 있는 4-비트 시프트 레지 스터를 본문 [그림 9.82]를 참고하여 아래와 같이 구현한다. 참고로 MUX_2x1은 LSE_Tutorial 프로젝트에 있는 부회로를 사용하고 D 플립플롭은 내장 Memory 라이브러리를 사용하면 된다. ② En = 1로 활성화하고 Serial_In = 1로 설정한 후에 F9을 4번 눌러 클록을 인가하면서 각 플립플 롭의 출력을 확인하라. ③ Serial_In = 0으로 설정한 후에 다시 F9을 4번 눌러 클록을 인가하면서 각 플립플롭의 출력을 확인하라. ④ En = 0으로 설정하면 시프트 레지스터의 동작이 어떻게 되는지 설명하라. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 553 4-비트 직렬 가산기 실습 사항 ① ‘SerialAdder4’ 회로를 새로 생성한 후 [본문 그림 9.83]과 같이 4-비트 직렬 가산기를 아래와 같이 구현한다. 이를 위해 ShiftRegister4 부회로 2개, 6장에서 설계한 전가산기 FA 1개, 그리고 내장 D 플립플롭 1개를 사용한다. 추가로 시프트 레지스터 내의 레지스터값을 모니터하기 위해 Wiring 라이브러리의 Probe를 A, B 시프트 레지스터 병렬 출력에 각각 연결해 준다. ② A 레지스터에 저장할 “0101”을 위해 En = 1로 설정한 후, LSB부터 SADD_In 값을 1로 세팅하 고 클록을 입력해서 B 레지스터값이 1000이 되는지 확인한다. 이후 SADD_In 값을 0,1,0으로 바꾸면서 클록을 3번 더 인가해서 B 레지스터에 1010이 저장되는 것을 확인하라. ③ B 레지스터에 저장할 “1010”을 LSB부터 0,1,0,1 의 순서로 SADD_In에 입력하고 클록을 인가 해서 4 클록 후에 B 레지스터에 1010이 저장되는지 확인하고 아울러 A 레지스터에 0101이 시 프트되어 저장되었는지도 함께 확인하라. ④ A 레지스터에 0101, B 레지스터에 1010이 채워져 있는 상태에서 추가로 클록을 4개 더 인가하 면 전가산기를 통과한 각 비트의 합이 다시 A 레지스터로 피드백되어 저장됨을 확인하라. 554 •디지털 논리회로 실습 요약 NOR 게이트 혹은 NAND 게이트로 SR 래치를 구현할 수 있다. 래치를 이용하여 다양한 형태(JK, D, T)의 주-종 플립플롭을 설계할 수 있다. 플립플롭을 이용하여 동기식 및 비동기식 업 혹은 다운 카운터를 설계할 수 있다. 카운터에 인에이블 기능을 추가할 수 있다. 플립플롭을 여러 개 이용하여 병렬 레지스터를 구현할 수 있다. 레지스터 파일을 설계하고 임의의 입력을 원하는 레지스터에 저장할 수 있다. 레지스터 파일의 출력을 ALU의 두 입력으로 연결하고 ALU에 연산의 종류를 Fn 값을 설정하여 원하는 두 레지스터의 값을 꺼내어 연산을 수행한 후 원하는 레지스터에 저장할 수 있다. 시프트 레지스터를 만들고 이를 이용하여 직렬 가산기를 구현할 수 있다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 555 A.7. 메모리 Logisim-evolution에서는 내장 메모리 라이브러리에 ROM과 RAM 컴포넌트를 제공한다. 이번 실 습에서는 ROM과 RAM 메모리의 동작을 간단한 주소 생성 회로를 통해서 확인하도록 한다. 그리 고 [A.6.11]의 데이터 버스에 메모리를 부착하고 특정 레지스터의 데이터를 메모리에 쓰기, 메모리 의 내용을 특정 레지스터에 옮기기 등을 테스트해 보도록 한다. A.7.1. ROM 테스트 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘ROMTest’ 회로를 생성한다. ② [A.6.8]에서 설계한 3-비트 카운터(SCounter8)와 내장 메모리 내의 ROM 컴포넌트를 불러와서 ROMTest 회로 캔버스에 배치하고 아래 그림과 같이 연결하도록 한다. ROM은 아래 그림 (a)와 같이 내장 메모리 라이브러리 안에 존재한다. 옮겨진 ROM의 외형은 간단하지 않게 보이므로 아래 그림 (b)처럼 ROM 속성 창에서 Appearance를 ‘Classic Logisim’ 으로 선택한다. (a) 내장 Memory 라이브러리 컴포넌트들 (b) ROM 컴포넌트의 속성 또한, ROM 속성에서 데이터 비트(Data Bit Width)는 8-비트로 설정하고 주소 비트(Address Bit Width)는 3-비트로 설정한다. 그러면 8x8 ROM에 해당하는 값이 ROM 사각형 안에 보이 게 된다. (b)의 Contents 속성에서 (click to edit)를 클릭하면 아래와 같은 ROM 데이터 편집창 이 열린다(혹은 ROM 위치에 커서를 이동하고 오른쪽 마우스 버튼을 눌러 Edit Contents를 선 556 •디지털 논리회로 택해도 된다). 여기서 원하는 값을 작성해 주고 파일로 저장하고 싶으면 SAVE를, 그냥 이번만 데이터를 설정하고 싶으면 Close Window를 누른다. 우리는 테스트를 위해 0번지부터 07, 06, 05, 04, 03, 02, 01, 00을 적어주도록 한다. 그리고 모니터링을 위해 카운터 출력을 스플리터를 사용하여 MSB = 0으로 1-비트 확장한 후 16진수 표시장치에 연결하고 ROM 출력 8-비트는 4비트씩 스플리터로 나누어 2개의 16진수 표시장치에 연결한다. ③ ROM은 주소를 주면 바로 데이터가 나오는 조합회로이다(진리표의 구현과 같음). 즉 클록 입력 이 필요하지 않다. 현재 카운터 값 3-비트에 해당하는 ROM 주소의 데이터가 바로 출력으로 나옴을 클록을 인가하면서 확인하라. 참고로 한 클록을 인가하는 기능은 F9이다. A.7.2. RAM 테스트 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘ROMRAMTest’ 회로를 생성한다. ② ‘ROMTest’ 캔버스 내의 모든 회로를 선택(Cntl+A)해서 복사(Cntl+C)한 후 ‘ROMRAMTest’ 캔버스에 붙여넣기(Cntl+V)를 수행하고, RAM 컴포넌트를 내장 메모리 라이브러리에서 불러와 배치한 후 아래 그림과 같이 연결하도록 한다. 여기서 RAM의 외형은 ROM의 경우처럼 속성 창에서 ‘Classic Logisim’으로 선택하고 데이터 비트는 8-비트 주소 비트는 3-비트로 아래와 같이 설정한다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 557 RAM은 마치 레지스터가 쌓여있는 레지스터 파일의 구조라고 생각하면 된다. 즉 주소는 여러 개의 레지스터 중에 특정 레지스터를 선택하는 기능을 수행하므로, 주소와 데이터를 주고 WE = 1로 설정하면 다음 클록이 입력될 때 데이터가 저장되는 방식으로 동작한다. 그리고 RAM에서 데이터를 읽는 것은 2가지 방식이 있다. 비동기식 읽기 방식: 마치 ROM처럼 주소를 주면 바로 데이터가 나오는 방식 동기식 읽기 방식 : 주소를 주고 클록이 인가되어야 데이터가 나오는 방식 우리는 ROM과의 데이터 읽기 방식을 통일하기 위하여 비동기 방식으로 데이터를 읽기로 한다. 따라서 속성 창에서 Asynchronous Read = YES로 선택해준다. 또한, RAM의 OE = 1로 설정 하고 RAM의 출력에 3-상태 버퍼를 달아서 RAM의 출력을 제어하도록 한다. ③ 아무런 제어 신호도 인가하지 않은 상태 (모든 제어 신호는 0)에서 F9을 눌러 클록을 인가하면 서 앞서 ROM 테스트할 때와 같이 ROM 출력이 16진수 표시장치로 잘 나오는지 확인하라. ④ 이번에는 ROM의 데이터를 RAM으로 옮기려고 한다. 3-비트 카운터를 어드레스 생성기라고 간주하고 출력인 3-비트 주소를 ROM과 RAM에 동시에 연결되어 있음을 확인하자. 이제 ROM_OE =1로 설정해서 ROM 데이터가 RAM의 입력 데이터로 연결되도록 하고, RAM의 WE = 1로 설정한 후 F9을 눌러서 클록을 인가하면서 어떤 현상이 벌어지는지 판단하라. ⑤ RAM의 OE = 1, WE = 0으로 설정하면 RAM의 출력이 3-상태 버퍼를 통과해 16진수 표시장 치에 보이게 된다. 즉 WE = 0인 설정은 RAM을 ROM처럼 동작하게 한다. 이제 클록을 인가해 가면서 RAM의 출력을 16진수 표시장치를 통해 확인해 보도록 하라. A.7.3. 메모리와 데이터 버스 테스트 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘MEMBusTest’ 회로를 생성한다. ② 실습 [A.6.10]의 테스트 회로에 [A.7.2]의 RAM 테스트 회로를 MEMBusTest 캔버스에 복사해 와서 병합하여 아래와 같이 회로를 구현한다. 558 •디지털 논리회로 ③ ROM의 데이터 8-바이트를 RAM으로 이동하여 쓰도록 하라. 이 과정은 ROM_OE = 1과 RAM_WE = 1로 설정하고 그 이외에 데이터 버스에 연결되어 있는 모든 레지스터의 제어 신호 가 0이면 ROM과 RAM 테스트 환경과 동일하다. 편의를 위해서 F9을 8번 누르면 된다. 이동이 끝나면 RAM에도 ROM과 동일한 데이터가 쓰여 있는 것을 확인하라. ④ 이번에는 RAM의 (0~3)번지 데이터를 A, B, C, D 레지스터에 순서대로 쓰는 방법을 강구하 라. 방법은 ROM과 버스 연결 경로를 차단(ROM_OE = 0)하고 RAM 입력으로 연결된 버스의 데이터가 RAM에 쓰여지는 것을 막기 위해 RAM_WE = 0으로 설정한 후 RAM 출력과 A 레 지스터의 이동 경로를 열어주면 된다. 즉 RAM_OE = 1, A_WE = 1인 상태에서 클록이 인가되 면 0번지 RAM 데이터가 A 레지스터로 이동할 것이다. 실습 요약 ROM은 읽기만 가능한 메모리이며 주소를 입력하면 정해진 주소의 데이터가 출력되는 특성을 확인할 수 있다. RAM은 읽기/쓰기가 모두 가능한 메모리이며 주소와 데이터를 모두 인가하고 WE=1로 준 후 클록을 입력하면 마치 레지스터에 데이터가 저장되듯이 RAM의 지정 주소에 데이터가 저장됨 을 알 수 있다. 또한, WE = 0인 상태에서 주소만 인가하면 마치 ROM처럼 지정된 주소의 데이 터를 읽을 수 있음도 확인할 수 있다. 데이터 버스에 ROM, RAM. 그리고 다양한 레지스터들이 함께 연결되어 있을 때도 3-상태 버 퍼를 잘 제어하면 메모리-레지스터 혹은 레지스터-레지스터 사이의 데이터 전달도 원활히 이루 어질 수 있음을 알 수 있다. 버스에 여러 장치가 연결되어 있더라도 A 장치에서 B 장치로의 데이터 이동은 A 장치의 OE = 1로 설정해서 버스에 데이터가 담기게 하고 B 장치의 WE = 1로 설정하면 다음번 클록에 동기되어 쉽게 이루어진다는 사실을 알 수 있다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 559 A.8. Logisim-evolution을 이용한 간단한 8-비트 컴퓨터 구현 및 테스트 지금까지 본문에서 배운 순차회로 및 조합회로 내용을 토대로 다양한 회로들을 Logisim-evolution 을 이용하여 구현해 보고 그 동작과 특성을 확인하였다. 몇 가지 주요한 회로를 열거해 보면 다음과 같다. 병렬 가산기 / 감산기 병렬 논리 연산기 (AND / OR) 산술 및 논리 연산기 (ALU) 멀티플렉서 / 디멀티플렉서 인에이블이 있는 카운터 / MOD-N 카운터 병렬 레지스터 / OE 과 WE 입력이 있는 병렬 레지스터 레지스터 파일과 메모리 액세스 본 실습에서는 위 회로들을 부품으로 사용하여 아주 간단한 명령을 수행하는 8-비트 컴퓨터를 만들 어 보고자 한다. 수행할 명령은 다음과 같이 4가지이다. 메모리에서 데이터를 가져와서 레지스터 파일의 특정 레지스터에 저장하기 (LOAD) 레지스터 파일의 특정 레지스터에 담겨있는 데이터를 메모리에 저장하기(STORE) 레지스터 파일 내의 2개의 레지스터 값을 덧셈 연산 후 레지스터에 다시 저장하기(ADD) 레지스터 파일 내의 2개의 레지스터 값을 AND 연산 후 레지스터에 저장하기(AND) 물론 더 많은 명령어를 수행할 수 있게 할 수도 있지만 한 개의 8-비트 명령어 내에 명령의 종류뿐 만 아니고 데이터를 저장하거나 가져올 메모리 주소까지 포함해야 해서 4가지로 국한했다. 물론 더 긴 명령어 비트(16-비트, 32-비트, 64-비트 등)를 사용하면 보다 많은 명령어를 수행하는 복잡하 고 성능 좋은 CPU를 설계할 수 있지만 이런 내용은 이 책의 범주를 벗어나고 전산기 구조 (Computer Architecture) 교과목에서 다루는 내용이 된다. 우리는 8-비트 컴퓨터를 다음과 같이 단계별 나누어 구현하고자 한다. ① 모든 명령어를 수행하는데 공통으로 필요한 명령어 인출과정 ② LOAD 명령에 해당하는 메모리의 주소에 담긴 데이터를 가져와 레지스터 저장하는 과정 ③ STORE 명령에 해당하는 특정 레지스터 값을 메모리 주소로 지정한 곳에 저장하는 과정 ④ ADD/AND 명령에 해당하는 두 레지스터 값을 가져와 연산을 수행하고 결과를 레지스터에 저 장하는 과정 ⑤ ①~④ 과정 전반에 필요한 제어 신호를 자동으로 생성하여 적용하는 과정 560 •디지털 논리회로 A.8.1. 프로그램 카운터(PC: Program Counter)를 이용한 명령어 인출 과정 그림 A.32 명령어 인출 과정 블록도 [그림 A.32]와 같이 CPU 외부에 프로그램이 담겨있는 메모리가 있다고 가정해 보자. 첫 번째 해야 할 일은 외부 메모리로부터 명령어 하나를 가져와서 내부 명령어 레지스터에 저장하는 일이다. 이 를 위하여 관련 있는 CPU 내부 요소만 언급해보면 다음과 같다. 프로그램 카운터(PC) : 명령어가 담긴 메모리의 주소를 생성하는 카운터이다. 외부 메모리가 총 16바이트라고 하면 주소를 위한 카운터는 4-비트이면 충분하다. 입력에 En 단자가 필요한 이유 는 명령어를 인출하는데 여러 클록이 소요될 수 있어서 매 클록 카운터를 증가시켜서는 안 되기 때문이다. 즉 하나의 명령어 인출 시마다 한 번만 En = 1을 주어 카운터를 증가시키면 된다. 메모리 주소 레지스터(MAR) : 액세스(Access)할 메모리의 주소를 담는 레지스터이다. 물론 PC 에서 직접 주소를 메모리로 연결해도 된다. 그러나 메모리 주소를 생성하는 곳이 PC뿐 아니고 여러 곳이라면 단일 창구로 MAR를 사용하는 것이 바람직하다. 메모리 버퍼 레지스터(MBR) : 메모리에 쓸 데이터를 저장하거나 메모리로부터 읽은 데이터를 일차적으로 저장하는 곳이다. MAR과 마찬가지로 외부와 연결되는 데이터 버스 창구를 일원화 했다고 생각하면 된다. 명령 레지스터(IR) : 프로그램이 저장된 메모리로부터 명령어를 하나 꺼내와서 저장하는 공간이 다. 이 명령 레지스터에 담긴 명령어가 바로 CPU에게 어떤 데이터를 어떻게 가공해서 어디에 저장하는지를 알려주는 정보가 된다. 그러면 Logisim을 이용해서 [그림 A.33]과 같은 기능의 회로를 구현하고 그 동작을 확인해 보도록 하자. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 561 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘CPU8Bit_Step1’ 회로를 새로 생성한다. ② 다음과 같은 회로 부품을 가져와서 캔버스에 배치한다. 인에이블이 있는 4-비트 카운터(Sequential_Circuit/SCounter16) : PC로 사용 WE와 OE이 있는 4-비트 병렬 레지스터(Sequential_Circuit/Register4) :MAR로 사용 내장 메모리 라이브러리 내의 메모리 (주소 비트: 4-비트, 데이터 비트: 8-비트, 비동기 읽 기 속성 적용) WE와 OE이 있는 8-비트 병렬 레지스터(Sequential_Circuit/Register8) :MBR 및 IR로 사용 3-상태 버퍼 (Gates/Controlled Buffer) : 하나의 버스에 여러 출력 충돌없이 연결 목적 스플리터와 16-진수 표시장치들 : 레지스터 출력 및 버스 상의 데이터 모니터링 목적 ③ 배치된 컴포넌트 사이를 다음과 같이 배선하여 연결한다. PC 카운터의 출력을 3-상태 버퍼를 거쳐서 4-비트 MAR 레지스터에 연결한다. MAR 출력 은 메모리의 주소 입력으로 연결한다. 메모리의 데이터 출력은 3-상태 버퍼를 거쳐 MBR 레지스터의 입력으로 연결하고 MBR의 출력은 다시 3-상태 버퍼를 거쳐서 IR의 입력으로 연결한다. 모든 레지스터 그리고 메모리에는 적재 기능과 버스에 연결을 위한 WE 및 OE 제어 신호를 일단 입력 핀으로 연결한다. (입력 핀을 통해 손으로 제어할 수 있게 됨을 확인한 후 나중에 자동으로 제어 신호가 생성되도록 할 예정) 각 카운터와 레지스터의 내부 저장 값 그리고 3-상태 버스값을 관찰하는 데 필요한 모든 곳에 스플리터와 16진수 표시장치를 부착한다. 562 •디지털 논리회로 ④ 메모리를 클릭하고 오른쪽 마우스 버튼을 눌러 RAM의 초깃값 설정 창을 연 후, 아래 (a)와 같 이 임의의 데이터로 채운다. Close Window 버튼을 누르면 (b)와 같이 메모리에 데이터가 모듈 안 사각 상자 안에 보이게 된다. (a) RAM 메모리의 초기값 설정 (b) 초기화된 RAM 모듈 ⑤ 단계 1(상태 0): MAR ⇐ PC : PC의 현재 카운터 값을 MAR에 전달하기 위한 제어 신호를 생성한다. 즉 PC의 OE=1로 설정 해서 PC값이 MAR의 데이터 입력에 연결되도록 하고 MAR의 WE=1로 설정한다. 이 제어 신 호는 다음번 클록이 입력될 때 PC값이 MAR로 저장되도록 한다. 이 과정을 다음과 같이 제어 신호 표로 나타내었다. 표에서 색칠해진 부분만이 활성화된다는 의미이다. 이 상태에서 클록을 인가하면 PC의 값이 MAR에 저장되게 되며 다음 단계(단계 2)로 넘어간다. ⑥ 단계 2(상태 1): MBR ⇐ RAM(MAR) 단계 2에서는 MAR이 가리키는 메모리 주소에 내장된 데이터를 가져와서 MBR 레지스터에 저 장하기 위한 제어 신호를 생성한다. 즉 [그림 A.33]과 같이 OE_MAR = 1로 설정해서 MAR값 이 메모리 주소에 연결되도록 하고 주소가 가리키는 메모리의 데이터가 버스에 실리도록 OE_RAM = 1로 설정한다. 한편 버스는 MBR의 입력에 연결되어 있으므로 MBR의 WE=1 로 설정하면 다음번 클록이 입력될 때 RAM(MAR) 값이 MBR로 저장되게 된다. 이 데이터 전달 과정을 위한 제어 신호를 요약하면 아래 표와 같다. 참고로 프로그램 카운터의 인에이블 신호도 함께 주어서 PC가 다음번 명령어 위치를 가리키도록 하였다. [그림 A.34]는 클록이 공급되어 메모리의 0번지에 담겨있던 0x07의 데이터가 MBR 레지스터에 부록 A. Logisim_evolution을 이용한 논리회로 실습• 563 잘 저장된 모습을 보여준다. 또한, 프로그램 카운터의 값이 1 증가한 것을 알 수 있다. 그림 A.33 단계 2에서 MBR ⇐ RAM(MAR)를 위한 클록 인가 전 제어신호들 그림 A.34 단계 2에서 클록인가 직후 MBR에 저장된 데이터 및 증가된 PC ⑦ 3 단계(상태 2) IR ⇐ MBR 단계 3에서는 MBR에 저장된 데이터를 IR 레지스터에 저장하기 위한 제어 신호를 생성한다. 여기서 눈여겨볼 것은 MBR의 3-상태 출력(TDout)은 메모리쪽으로 연결되어 쓰기 동작에 사 용할 수 있고 버퍼 거치지 않은 Dout은 새로운 3-상태 버퍼를 거쳐서 내부 레지스터에 연결되 어 있다는 것이다. 이렇게 MBR에서 내부로 들어오는 경로에 OE_IBUS로 제어되는 3-상태 버 퍼를 추가한 이유는 내부 버스와 외부 버스를 분리시켜 주기 위함이다. 따라서 MBR 데이터가 IR 레지스터와 연결된 내부 버스로 들어올 수 있도록 OE_IBUS =1로 설정하고 IR 레지스터의 WE=1로 설정하면 다음번 클록이 입력될 때 MBR 값이 IR로 저장되도록 한다. 이 데이터 전달 과정을 위한 제어 신호를 요약하면 아래 표와 같다. 564 •디지털 논리회로 [그림 A.35]는 3단계에서의 제어 신호가 공급된 상태를 보여주고 있고 [그림 A.36]은 클록이 공급되어 MBR에 담겨있던 0x07의 데이터가 IR 레지스터에 잘 이동된 모습을 보여준다. 그림 A.35 단계 3에서 (IR ⇐ MBR)을 위한 클록 인가전 제어신호들 그림 A.36 단계 3에서 클록 인가 후 MBR에서 IR로의 데이터 이동 ⑧ 실습 ⑤, ⑥, ⑦에 나타낸 단계 1~단계 3 과정을 하나의 세트로 묶으면 다음 표와 같으며 이 한 세트의 과정을 명령어 인출과정이라고 부른다. 그림 A.37 명령어 인출을 위한 3단계 과정 한 세트가 진행될 때마다 메모리에 있는 명령어를 명령어 레지스터 IR에 가져오게 된다. 매 세 트 손으로 제어 신호를 인가하면서 메모리에 명령어라고 저장된 데이터들(0x07, 0x06, ...)이 명 령어 레지스터에 잘 인출됨을 확인하라. 그리고 제어 신호가 세트마다 반복되고 있음을 인지하 부록 A. Logisim_evolution을 이용한 논리회로 실습• 565 고 자동화에 대한 가능성에 대해서 고민해보도록 하라. 단계 1의 제어 신호를 설정하고 클록을 인가 : MAR ⇐ PC 단계 2의 제어 신호를 설정하고 클록을 인가 : MBR ⇐ RAM(MAR) 단계 3의 제어 신호를 설정하고 클록을 인가 : IR ⇐ MBR A.8.2. LOAD 명령어 인출 및 메모리 데이터의 레지스터 저장 과정 [A.8.1]에서는 메모리에 명령어가 담겨있다고 가정하고 PC를 이용하여 명령어를 인출하여 명령어 레지스터 IR에 저장하는 과정을 살펴보았다. 이번 실습에서는 실제로 명령어를 정의하고 가장 기본 적인 LOAD 명령어를 실행하는 법에 대하여 살펴보도록 하자. 우선 8-비트로 구성되는 명령어의 형식을 [그림 A.38(a)]와 같이 상위 2-비트의 명령어 코드(OP Code)와 다음 2-비트의 레지스터 주소, 그리고 하위 4-비트의 메모리 주소로 정의하도록 한다. 수 행할 명령어는 OP 코드의 값에 따라서 [그림 A.38(b)]와 같이 4가지로 정의한다. (a) 8-비트 명령어 형식 (b) 명령어 코드에 따른 명령어 기능 그림 A.38 8-비트 컴퓨터의 명령어 형식 및 종류 다른 명령어들에 대한 기능과 동작은 뒤에서 다루도록 하고 우선 여기서는 첫 번째 명령어인 LOAD 명령어에 대해서만 살펴보자. 8 비트 명령어가 00-00-1000으로 구성되었다면 첫 번째 2비트는 LOAD를 나타내고 두 번째 2-비트는 R0를 나타내며 세 번째 4-비트는 메모리의 주소 0x8 번지를 나타낸다. 따라서 8-비트 명령어가 0x08이라면 MEM(0x8)의 데이터를 레지스터 파일 내 의 R0에 저장하라는 의미가 된다. 다음은 로드 명령어의 몇 가지 예이다. 명령어가 0x19(00-01-1001)라면 R1⇐ RAM(0x9) 명령어가 0x2A(00-10-1010)라면 R2⇐ RAM(0xA) 명령어가 0x3B(00-11-1011)라면 R3⇐ RAM(0xB) 명령어 인출 및 명령어 분석을 통한 추가 데이터 가져오기를 수행하기 위한 CPU의 내부요소를 블 록도로 간단히 나타내면 [그림 A.39]와 같다. [그림 A.32]와의 차이를 보면 :① 명령어 레지스터의 하위 4-비트가 3-상 버퍼를 통하여 MAR로 연결되었고 ② MBR에 담긴 데이터를 저장하기 위한 레지스터 파일이 새로 추가되었다. 566 •디지털 논리회로 그림 A.39 명령어 인출 및 디코드를 통한 데이터 가져오기 블록도 이제 Logisim을 이용해서 [그림 A.39]와 같은 기능의 회로를 구현하고 LOAD 명령어 수행과정을 확인해 보도록 하자. 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘CPU8Bit_Step2’ 회로를 새로 생성한다. ② CPU8Bit_Step1 회로를 복사해서 CPU8Bit_Step2 캔버스에 복사한 후 추가로 아래 그림의 점선 사각형과 같이 [A.6.13]의 레지스터 파일을 부회로로 불러와 배치한다. ③ 그리고 그림 위쪽 점선처럼 3-상태 버퍼를 거친 IR의 출력(TDout)을 스플리터를 통해 하위 4비트만 취하여 PC와 MAR 사이의 데이터 선에 연결하여 준다. 그리고 IR 레지스터의 출력 (Dout)을 터널을 이용하여 Instruction으로 지정한 후 스플리터를 통하여 상위 2-비트는 부록 A. Logisim_evolution을 이용한 논리회로 실습• 567 OPcode, 다음 상위 2-비트는 ASel, 그다음 2-비트는 BSel로 지정한다. LOAD 나 STORE 명령 어에서는 BSel은 사용될 일은 없으나 추후 ALU 연산에서 사용되므로 미리 지정하여 놓는다. ④ MBR에서 IBUS 버퍼를 거쳐 온 내부 데이터 버스를 레지스터 파일의 Rin으로 연결한다. ⑤ 메모리의 데이터 편집창을 열고 아래와 같이 4개의 LOAD 명령어를 0번지부터 3번지까지 써 넣고 또한 8번지~11번지까지 0xFF, 0x77, 0x33, 0x11의 데이터로 채워 놓는다. 이로써 인출한 명령어를 분석하여 하위 4-비트에 해당하는 주소의 데이터를 가져다가 레지스터 파일에 저장할 환경은 모두 갖추었다. ⑥ [A.8.1]의 실습과정 ⑤, ⑥, ⑦에 나타낸 단계 1~단계 3을 수행하면 명령어 레지스터에 첫 번째 명령이 저장된다. 초기 상태를 0이라고 하고 클록이 인가될 때마다 바뀌는 상태를 1, 2라고 하면 각 상태에 대한 제어 신호는 아래 표와 같음을 앞에서도 언급했다. 이 표에서 새로운 제어 신호 WE_RF가 추가되었다. 이 신호는 데이터 버스에 있는 값을 레지스 터 파일에 저장하는 제어 신호이다. ⑦ 첫 번째 명령어(LOAD R0, *(0x8))가 IR 레지스터에 저장된 상태에서 우선으로 할 일은 명령 어의 하위 4-비트를 주소로 삼아서 MAR에 저장하는 것이다. 이를 위해서 OE_IR =1로 설정하 고 WE_MAR = 1로 설정하면 된다. 아래 표는 상태 0~2가 모두 수행되고 상태 3에서 IR 4-비 트를 MAR에 저장하기 위한 제어 신호를 나타낸다. [그림 A.40]에서 보면, ㉠ 0x08이 저장된 IR 레지스터의 하위 4-비트 주솟값 0x8이 OE_IR=1 제어 신호로 IR 내부의 3-상태 버퍼를 지나서 MAR로 연결된 버스에 적재된 것을 보여준다. 또한, ㉡WE_MAR =1로 설정해서 다음 클록에 0x8값을 MAR에 저장할 준비를 마친 상태가 된다. ㉢이 상태에서 클록이 인가되면 MAR에 0x8값이 저장되며 다음 상태로 천이한다. 568 •디지털 논리회로 그림 A.40 MAR ⇐ IR(3:0) 데이터 이동을 위한 제어신호와 클록에 의한 데이터 이동 ⑧ 두 번째로 할 일은 명령어의 하위 4-비트가 담긴 MAR의 주소를 메모리에 전달하고 메모리의 데이터값을 MBR에 저장하는 것이다. 이를 위해서 OE_MAR =1로 설정하고 OE_RAM = 1로 설정하며 WE_MBR = 1로 설정하면 된다. 아래 표는 상태 0~3가 모두 수행되고 상태 4에서 MBR ⇐ RAM(MAR)을 위한 제어 신호를 나타낸다. [그림 A.41]은 클록을 인가하기 전의 제어 신호 인가된 상황(㉠㉡㉢)과 클록 인가 후 메모리 내 의 0xFF 데이터가 MBR 레지스터에 저장된 결과(㉣)를 보여준다. 그림 A.41 MBR ⇐ RAM(MAR)을 위한 제어 신호와 클록에 의한 데이터 이동 부록 A. Logisim_evolution을 이용한 논리회로 실습• 569 ⑨ 마지막으로 할 일은 MBR에 저장된 데이터를 레지스터 파일 내의 R0에 저장하는 것이다. 이를 위해서는 OE_IBUS =1로 설정하고 WE_RF = 1로 설정하면 된다. 레지스터 파일 내의 여러 레 지스터(R0 ~ R3) 중에 R0에 저장되게 하기 위해서는 ASel 값이 00이 되어야 하는데 이 값은 이미 명령어 레지스터의 두 비트(C5:C4)를 따로 스플리터로 분리해서 ASel에 연결해 주었기 때문에 특별하게 ASel을 위한 제어 신호는 필요하지 않다. 아래 표는 상태 0~4가 모두 수행되고 상태 5에서 RegFile(R0) ⇐ MBR을 위한 제어 신호를 나타낸다. [그림 A.42]는 클록을 인가하기 전의 제어 신호 인가된 상황(㉠㉡)과 클록 인가 후 MBR의 0xFF 데이터가 레지스터 파일 내의 R0에 저장된 결과(㉢)를 보여준다. 그림 A.42 RF(R0) ⇐ MBR을 위한 제어 신호와 클록에 의한 데이터 이동 ⑩ [A.8.2]의 실습과정 ⑤, ⑥, ⑦과 [A.8.3]의 실습과정 ⑦, ⑧, ⑨를 연이어 수행하면 메모리로부터 LOAD 명령어를 받아들여 명령어 내에 존재하는 하위 4-비트의 주소를 찾아가 메모리로부터 데이터를 가져다가 레지스터 파일 내의 정해진 레지스터에 저장하게 된다. 즉 명령어 하나를 인 출해서 수행하는데 총 6개의 사이클이 필요하게 된다. [그림 A.43]은 이 6단계 과정에 대한 제어 신호들을 요약하여 나타낸 표이다. 570 •디지털 논리회로 그림 A.43 LOAD 명령을 위한 6단계 제어신호들 이 6단계의 과정을 하나의 세트로 보고 다시 한번 한 세트를 수행하게 되면 PC = 1인 상태에서 시작하므로 0x19의 명령어를 가져오게 될 것이고 이를 분석해서 9번지에 있는 데이터 0x77을 MBR로 가져와 R1에 저장하는 일을 수행하게 될 것이다. 한 세트를 또 수행하면 PC = 2이므로 0x2A 명령어를 인출해서 A 번지에 있는 메모리의 데이터 0x33을 MBR로 가져온 후 R2에 저 장하게 될 것이다. 초기화부터 시작해서 RAM에 데이터를 채운 후 6단계의 한 세트 과정을 총 4번 수행하면서 R0 ~ R3에 0xFF, 0x77, 0x33, 0x11 데이터가 메모리로부터 잘 로드되어 저장되는지 확인하라. A.8.3. STORE 명령어 인출 및 레지스터의 데이터 메모리 저장 과정 이번 실습에서는 두 번째 명령어인 STORE 명령어에 대해서 알아보자. 8 비트 명령어가 01-00-1000으로 구성되었다면 첫 번째 2-비트는 STORE를 나타내고 두 번째 2-비트는 R0를 나 타내며 세 번째 4-비트는 메모리의 주소 0x8번지를 나타낸다. 따라서 8-비트 명령어가 0x48이라 면 레지스터 파일 내의 R0 데이터를 MEM(0x8)에 저장하라는 의미가 된다. 다음은 STORE 명령 어의 몇 가지 예이다. 명령어가 0x59(01-01-1001)라면 RAM(0x9) ⇐ R1 명령어가 0x6A(01-10-1010)라면 RAM(0xA) ⇐ R2 명령어가 0x7B(01-11-1011)라면 RAM(0xB) ⇐ R3 이제 Logisim을 이용해서 STORE 명령어 수행과정을 확인해 보도록 하자. 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘CPU8Bit_Step3’ 회로를 새로 생성한다. ② CPU8Bit_Step2 회로를 복사해서 CPU8Bit_Step3 캔버스에 복사한 후 추가로 아래 그림과 같이 [A.5.8]의 ALU를 부회로로 불러와 아래와 같이 배치한다. ③ 레지스터 파일의 Aout과 Bout을 [A.6.13]에서 사용했던 것과 같이 ALU의 두 입력 A, B로 연결 하고 ALU의 기능을 정해주는 Fn_ALU와 3-상태 출력을 제어하는 OE_ALU를 입력핀으로 연 결한다. 또한, ALU의 출력 F는 내부 데이터 버스(레지스터 파일의 입력 데이터 버스)에 연결하 부록 A. Logisim_evolution을 이용한 논리회로 실습• 571 고 올림수 값은 Cout_ALU 출력 핀으로 연결한다. ④ 메모리의 데이터 편집창을 열고 아래와 같이 2개의 LOAD 명령어(0x08, 0x19)와 2개의 STORE 명령어(0x4c, 0x5d)를 0번지부터 3번지까지 써넣고 또한 8번지~11번지까지 0xFF, 0x77, 0x33, 0x11의 데이터로 채워 놓는다. ⑤ [A.8.2]의 실습과정 ⑤, ⑥, ⑦과 [A.8.3]의 실습과정 ⑦, ⑧, ⑨를 [그림 A.43]에 정리된 제어신 호을 이용하여 두 세트(6단계 2회) 수행하면 PC는 2를 가리키고 있고, A 및 B 레지스터에는 0xFF와 ox77이 저장되어 있는 상태가 된다. ⑥ STORE 명령을 수행하기 위한 첫 번째 단계는 LOAD 명령어 때와 마찬가지로 명령어를 메모리 로부터 가져와 IR 레지스터에 저장하는 것으로 [그림 A.43]의 단계 1~3을 수행한다. 명령어 로 572 •디지털 논리회로 드는 명령어의 타입과 관계없이 같은 순서임을 상기하고 3단계 제어 신호 후 클록이 인가되었을 때 IR에 0x4c 명령어가 담겨있음을 확인하라. 1단계 : MAR ⇐ PC (PC = 2) 2단계 : MBR ⇐ MEM(MAR = 2) , PC ⇐ PC + 1 3단계 : IR ⇐ MBR (MBR = 0x4c) ⑦ 세 번째 명령어(STORE *(0xC), R0)가 IR 레지스터에 저장된 상태에서 우선으로 할 일은 명령 어의 하위 4-비트를 주소로 삼아서 MAR에 저장하는 것이다. 이를 위해서 OE_IR =1, WE_MAR = 1로 설정하면 된다. 또한 동시에 R0의 레지스터값이 ALU를 관통(Bypass)하여 MBR 레지스터에 저장될 수 있도록 Fn_ALU = 01로 선택하고 OE_ALU =1, WE_MBR= 1로 설정한다. 아래 표는 STORE 상태 3의 제어 신호를 나타내고 그림은 상태 3에서 인가된 제어신 호들(㉠㉡㉢㉣)과 클록이 인가된 후의 결과로 IR 명령어 0x4C의 하위 4-비트가 MAR에 저장 된 것(㉤)과 R0의 값 0xFF가 ALU를 통과(bypass)하고 3상 버퍼를 거쳐 MBR에 저장된 것(㉥) 을 보여준다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 573 ⑧ 저장 명령어(STORE *(0xC), R0)의 다음 할 일은 MBR에 저장된 데이터를 MAR이 가리키는 메모리에 저장하는 것이다. 이를 위하여 OE_MBR = 1, OE_MAR = 1로 설정하고 WE_RAM =1로 세팅한다. 그러면 클록이 입력될 때 MBR의 데이터가 0xC 번지에 저장된다. 아래 표는 STORE 명령어 수행 상태 4의 제어 신호를 나타내고 그림은 상태 4에서의 제어 신호들(㉠㉡㉢) 과 클록이 인가된 후의 결과로 0xC번지의 메모리에 MBR의 데이터 0xFF가 저장된 것(㉣)을 보여준다. 574 •디지털 논리회로 ⑨ 지금까지 살펴본 STORE 명령어의 수행단계는 총 5단계(상태 0 ~ 상태 4)임을 확인하였고 아 래 표는 각 상태에서의 제어 신호를 정리하여 요약한 것이다. 아래 5단계를 STORE 명령을 위 한 제어 신호 한 세트라고 할 때 ⑧ 과정에 이어서 한 세트의 과정을 더 수행하여 레지스터 R1 에 있는 0x77 데이터가 메모리의 주소 0xD 번지에 잘 저장되는지를 확인하라. A.8.4. ALU 연산 명령 (ADD, AND) 이번 실습에서는 ALU 명령어인 ADD 및 AND 명령어에 대해서 알아보자. 8 비트 명령어가 10-00-01xx로 구성되었다면 첫 번째 2-비트는 ADD를 나타내고 두 번째 2-비트는 R0를 나타내 며 세 번째 2-비트는 R1을 나타내며 R0 ⇐R0 + R1의 의미가 된다. 마지막 2-비트는 사용되지 않는다. 다음은 ADD 명령어의 몇 가지 예이다. 명령어가 0x98(10-01-10xx) : R1 ⇐ R1+R2 명령어가 0xAC(10-10-11xx) : R2 ⇐ R2+R3 명령어가 0xB0(10-11-00xx) : R3 ⇐ R3+R0 또한, 8-비트 명령어가 11-00-01xx(0xC4)로 구성되었다면 첫 번째 2-비트는 AND를 나타내고 두 번째와 세 번째 2-비트는 각각 R0, R1을 나타내며 R1 ⇐R1 AND R2의 의미가 된다. 마지막 부록 A. Logisim_evolution을 이용한 논리회로 실습• 575 2-비트는 사용되지 않는다. 다음은 AND 명령어의 몇 가지 예이다. 명령어가 0xD8(11-01-10xx) : R1 ⇐ R1 AND R2 명령어가 0xEC(11-10-11xx) : R2 ⇐ R2 AND R3 명령어가 0xF0(11-11-00xx) : R3 ⇐ R3 AND R0 이제 Logisim을 이용해서 ADD/AND 명령어 수행과정을 확인해 보도록 하자. 실습 사항 ① 두 명령어의 수행을 위해서 추가적인 부회로는 필요치 않으므로 ‘CPU8Bit_Step3’ 회로에서 리 셋을 수행하고 RAM 메모리를 다음과 같이 채워 넣는다. 참고로 0번지부터 3번지까지의 내용은 R0에 8번지에 있는 0xFF를 로드하고(0x08) R1에 9번지에 있는 0x77을 로드한 후(0x19), R0 와 R1의 데이터를 ADD 해서 R0에 저장하고(0x84), 다시 R0 와 R1의 내용을 더해서 R0에 저장(0xC4)하라는 명령어들이다. ② [그림 A.43]에 나타낸 LOAD 명령을 위한 6단계 과정을 두 번 수행하라. 그리고 R0와 R1에 0xFF와 0x77이 저장되어 있음과 PC = 2를 가리킴을 확인하라. ③ 이제 3번째 명령어를 IR로 가져오기 위해 [그림 A.38]의 명령어 인출과정 3단계를 한 세트 수행 하라. 그리고 3번지에 있는 0x84의 명령어가 IR 레지스터에 잘 이동했음과 PC는 3을 가리키고 있음을 확인하라. ④ 앞에서 명령어 레지스터에 저장된 0x84 명령어를 다음과 같이 비트별로 나누어 터널 신호로 구 분하였다. 즉 상위 2-비트는 OPcode라고 하였고, 다음 2-비트는 Asel, 다음 2-비트는 BSel로 이름지어 Asel과 Bsel을 각각 레지스터 파일에 연결하여 주었었다. 576 •디지털 논리회로 이제 ALU 연산을 정의하는 Fn_ALU 입력 핀 대신에 Opcode 2-비트를 연결하도록 하자. 이 연결은 ALU의 연산이 자동적으로 명령어의 상위 두 비트값에 의해 결정지도록 해 준다. 현재 명령어 레지스터의 값의 상위 2-비트는 10이므로 ALU는 ADD 연산으로 지정된다. 위 그림에서 보듯이 ALU는 이미 ASel에 의해서 정해진 R0값(0xFF)과 BSel에 의해서 정해진 R1값(0x77)을 더해서 0x76을 결과로 가지고 있음을 알 수 있다. ⑤ 이제 인출된 명령어에 의해 자동으로 결정된 ALU의 기능과 그 연산 결과를 다시 Asel에 의해서 지정되는 R0에 저장하기 위한 제어 신호를 생성해 보자. 우선 ALU의 3-상태 버퍼가 열려야 하므로 OE_ALU = 1로 설정한다. 그리고 ASel 값은 이미 명령어 비트 C5:C4에 의해서 R0가 지정되어 있으므로 WE_RF = 1로만 설정하면 된다. 이를 요약하면 다음 표와 같고 클록을 인가 하면 아래 그림처럼 R0 ⇐ R0+R1 연산 결과 저장이 수행된다. ⑥ ALU 연산의 단계를 살펴보면 명령어 인출에 3 단계 (3클록) 및 명령어 수행에 1단계 (1클록)사 용되어 총 4단계로 충분함을 알 수 있다. 다음 표는 ALU 명령어 수행을 위한 4단계 과정을 나타 낸다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 577 위 상태 0부터 상태 3까지의 과정(제어 신호 설정과 클록 인가)을 한 번 더 수행해서 메모리로부 터 0xC4에 해당하는 명령어를 인출하여 IR에 저장한 후 명령어에 내재된 OPcode = 11, Asel = 00, Bsel = 01을 통해 R0 ⇐ R0 AND R1의 연산을 수행되는지 확인하고 그 결과로 R0에 어떤 값이 저장되는지를 단계별로 확인하라. 578 •디지털 논리회로 A.8.5. 제어 신호 자동화를 통한 최종 8-비트 컴퓨터 구현 이번 실습에서는 지금까지 다루었던 4개의 명령어에 대한 단계별 제어 신호를 정리하도록 한다. 그 리고 이 제어 신호들을 MOD-6 카운터를 이용하여 명령어에 따른 자동으로 생성할 수 있도록 자동 제어 신호 생성기 (Control Unit)를 ROM을 이용하여 만들어 본다. 나아가 이를 적용하여 메 모리에 적절하게 프로그램과 데이터가 내장되어 있다고 하면 클록이 인가될 때마다 자동적으로 명 령을 인출해서 디코드하고 명령어에 담긴 기능을 수행하는 것을 확인해 보도록 한다. 제어신호 생성기 구현 다음 표는 4가지 명령에 대한 CPU 내부 및 메모리의 데이터 전달을 위한 모든 제어 신호를 나타낸 것이다. 참고로 LOAD 명령어는 6단계, STORE 명령어는 5단계 그리고 ALU 명령어는 4단계로 구성되나 편의상 모두 6단계로 표현하고 필요 없는 단계들은 모두 제어 신호를 0으로 표기하였다. 그림 A.44 각 명령어에 따른 상태별 제어신호들 정리표 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘CU_CPU8’ 회로를 새로 생성한다. ② CU_CPU8 캔버스에 2-비트의 입력 핀 OPcode와 Clock을 추가하고, [실습 A.6.8]에서 설계한 MOD-6 카운터 회로(Sequential_Circuit/Scounter6)를 부회로로 불러와서 Clock 입력을 연결한다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 579 ③ 내장 메모리 라이브러리의 ROM을 불러와 주소 비트는 5, 데이터 비트는 13으로 설정한 후 OPcode 2-비트와 SCounter6의 출력 3-비트를 스플리터를 통해 5-비트로 병합하여 ROM 주 소 입력에 연결하여 준다. ④ ROM의 데이터 편집창을 열어서 5비트 입력에 대한 출력 13-비트의 값을 [그림 A.44]의 마지 막 열을 참고하여 아래와 같이 생성해 준다. 참고로 ROM 데이터의 7번째와 8번째 값(각 명령 어에 대한 상태 6과 상태 7의 제어신호)은 모두 0으로 채웠음을 확인하라. ⑤ OPcode = 00인 상태에서 F9을 눌러 클록을 인가하면서 LOAD 명령에 해당하는 제어 신호 13-비트가 잘 출력되는지 확인하라. (00C0⇒ 12C0⇒ 0018⇒ 0404⇒ 02C0⇒ 0012⇒ 00C0 ...) ⑥ OPcode = 01인 상태에서 F9을 눌러 클록을 인가하면서 STORE 명령에 해당하는 제어 신호 13-비트가 잘 출력되는지 확인하라. (00C0⇒ 12C0⇒ 0018⇒ 0445⇒ 0320⇒ 0000⇒ 00C0 ...) ⑦ OPcode = 10/11인 상태에서 F9을 눌러 클록을 인가하면서 ALU 명령에 해당하는 제어 신호 13-비트가 잘 출력되는지 확인하라. (00C0⇒ 12C0⇒ 0018⇒ 0003⇒ 0000⇒ 0000⇒ 00C0 ...) 자동 제어 생성기가 추가된 8-비트 컴퓨터 구현 이번 실습에서는 마지막으로 자동 제어 생성기를 추가하여 앞선 실습 [A.8.1] ~ [A.8.4]에서 수작업 으로 공급해 주었던 제어 신호들이 자동으로 공급되도록 하여 완전한 8-비트 컴퓨터로써의 구조를 가질 수 있도록 구현해 본다. 실습 사항 ① 개발창에서 아이콘을 클릭한 후 ‘CPU8Bit_Final’ 회로를 새로 생성한다. ② CPU8Bit_Step3 회로를 모두 복사하여 CPU8Bit_Final 캔버스에 붙여넣기를 한다. 580 •디지털 논리회로 ③ CU_CPU8 회로를 가져와서 CPU8Bit_Final 캔버스 빈공간에 배치하고 스플리터를 이용하여 다 음과 같이 13-비트의 버스 신호를 비트별 13개의 제어 신호로 나누고 각 제어 신호에 터널을 이용하여 원래 사용되던 입력핀의 이름과 같도록 지정해준다. CU_CPU8의 state 3-비트 출력은 스플리터를 이용하여 0을 추가한 후 16진수 표시장치에 연결하여 상태를 볼 수 있도록 한다. ④ CPU8Bit_Final 캔버스 내에 있던 13개의 입력 제어 핀을 삭제하고 그 대신에 같은 이름의 터널 을 사용하여 아래와 같이 연결해 준다. ⑤ RAM의 속성창을 열고 다음과 같은 프로그램과 데이터를 채워넣는다. 참고로 메뉴창의 Simulate ⇒ Reset Simulation을 클릭하면 모든 레지스터 및 RAM 데이터가 초기화된다. 따라서 RAM의 데이터를 초기화 후에 다시 수정하는 것이 번거로울 수 있으니 RAM Image를 부록 A. Logisim_evolution을 이용한 논리회로 실습• 581 저장해 놓으면 편리하다. 위 RAM 데이터의 의미는 다음과 같이 8-비트의 프로그램과 8-비트 의 데이터 영역을 나타낸다. 실제 CPU에서는 프로그램 메모리와 데이터 메모리를 구분하여 사용하기도 한다. 이 경우 프로 그램 명령어와 그에 관련된 메모리의 데이터를 함께 가져올 수 있어서 실행단계를 줄일 수 있고 그 결과로 빠른 동작 속도를 얻을 수 있다. 우리는 개념을 익히는 만큼 16개 주소의 메모리를 반으로 나누어 각각 프로그램과 데이터에 사용하였음을 기억하기 바란다. ⑥ 초기화되고 메모리에 프로그램과 데이터가 로드되고 나면 자동 제어 신호 발생을 통한 명령어 수행 준비가 다 되었다. 아무런 클록을 인가하기 전인 상태에서 CU_CPU8의 두 출력 OE_PC와 WE_MAR이 활성화 된 것을 확인한다. 그리고 F9을 눌러서 클록을 인가하면서 올바른 제어 신 호가 공급되어 6단계를 통한 로드 명령어가 잘 수행되었는지 F9을 6번 누르면서 확인하라. ⑦ 6개의 클록을 하나의 세트라고 할 때 매 세트를 진행해 가면서 R1, R2, R3에도 데이터가 잘 로드되는지 확인한다. (F9 18번 누르기) ⑧ 두 세트의 클록을 통해 ADD 연산과 AND 연산이 잘 수행되어 각각 R0와 R2에 저장되는지 확인한다. (F9 12번 누르기) ⑨ 두 세트의 클록을 통해 R0와 R2가 각각 0xC번지와 0xD번지에 잘 저장되는지 확인한다. (F9 12번 누르기) 실습 요약 마이크로 컨트롤러 혹은 중앙 처리 장치(CPU)는 외부 메모리와 MAR 및 MBR 레지스터를 통 해서 주소를 인가하고 데이터를 주고 받는다. 메모리에 프로그램 및 데이터를 저장해 놓고 프로그램 카운터가 가리키는 곳의 명령어를 MBR 을 거처 명령어 레지스터에 가져올 수 있다. LOAD 명령어 내부에 포함된 주소를 사용하여 메모리에 저장된 데이터를 레지스터 파일 내부 로 가져올 수 있다. 582 •디지털 논리회로 STORE 명령어 내부에 함된 주소를 사용하여 레지스터 파일 내부의 특정 레지스터값을 메모리 에 저장할 수 있다. ADD/AND 명령어를 디코드 하여 두 레지스터에 담긴 데이터에 대해 산술/논리 연산을 수행하 고 결과를 다시 레지스터에 저장할 수 있다. 명령어들의 시퀀스를 통해 원하는 기능을 수행하는 프로그램을 작성할 수 있다. 8-비트 마이크로 컨트롤러/프로세서의 내부 및 외부 데이터 이동 동작을 이해할 수 있다. 맺음말 이상을 통해 간단하나마 8-비트 마이크로프로세서를 위한 최소한의 회로를 구성하고 그 동작을 살 펴보았다. 논리 회로에서 응용 분야로 간단한 자동판매기 혹은 신호등 제어 등의 과제를 삼을 수도 있었지만 그 경우 배운 내용(조합회로, 순차회로, 카운터, 레지스터 등)을 종합적으로 사용하기에는 한계가 있었다. 물론 논리 회로 교재에서 컴퓨터 구조를 실습하는 것은 무리가 있다고 평가할 수도 있다. 그러나 정작 실습하면서 느낄 수 있었듯이 사용된 모든 부품이 본 교재에서 다룬 내용의 범주 를 벗어나지 않았다. 모쪼록 모든 실습을 충실히 수행하면서 논리 회로에 대한 기본 이해 및 활용에 대한 역량이 키워지기를 바라고 나아가 논리 회로를 활용하여 만들어지는 다양한 IT 제품 내의 디 지털 시스템과 컴퓨터 구조 설계에 대한 불안의 벽도 함께 허물 수 있기를 기대한다. 부록 A. Logisim_evolution을 이용한 논리회로 실습• 583