이번 시간부터는 많은 예제를 통하여 기초적인 회로를 구현해 보도록 하겠습니다. 많은 예제를 통해 자기 자신만의 코딩 스타일을 가지는 것도 중요한 일이지요.

ex1) -- 논리식 library ieee; use ieee.std_logic_1164.all; entity ex1 is port ( a, b, c : in bit; z : out bit); end ex1; architecture rtl of ex1 is begin z <= (a and b) or c; end rtl;	ex2) -- 논리식 library ieee; use ieee.std_logic_1164.all; entity ex1 is port ( a, b, c : in std_logic; z : out std_logic); end ex1; architecture rtl of ex1 is begin z <= (a and b) or c; end rtl;

콜론(;)을 붙이는 것도 상당히 중요합니다. 여기서는 두 가지의 중요한 사항이 있습니다. 눈설미가 있는 분들은 한가지는 찾으셨겠죠. C 언어나 다른 언어의 기초적인 사항만 알면 별로 어려운 문법은 없다고 생각됩니다.

먼저 우리가 할 일을 먼저 생각합시다. 컴파일을 통해 일단 버그(?)를 잡아야 하겠죠.

VHDL의 문법은 상당히 엄격합니다. 그래서 그 규정을 지키지 않으면 제대로 테스트하기가 어렵습니다. 컴파일이 끝나면 시뮬레이션을 통해 그 결과를 확인해야 합니다. 시뮬레이션시 중요한 것은 Delay가 어떻게 되는지 생각해야 합니다. 결과가 제대로 나왔다고 해서 그 결과를 만족해서는 안됩니다. 중요한 것은 Real-time Simulation을 해야 한다는 것입니다. 초기부터 항상 이것을 명심하기를 바랍니다. 시뮬레이션이 끝나면 그 결과를 구현해 보는 것도 중요합니다. 보드가 없는 사람은 시뮬레이션으로 끝나야 하겠지만 여건이 가능하다면 항상 구현해 보는 것도 즐거운 일입니다. 저는 보드에 구현하면 항상 일종의 만족감을 느낍니다. 항상 이렇게 서론이 길군요. 미안합니다.

이 두 예제의 차이점은 bit와 std_logic의 차이입니다. bit는 전기적인 신호 □1□과 □0□을 말합니다. 전자회로의 기초적인 사항이죠.

std_logic 이란 무엇인가요?  이것을 이해하기 전에 이것을 시뮬레이션으로 구현해 보셨나요? 결과가 어떻습니까? 같은 결과를 보여주죠.

디지털 전자회로는 어떻습니까?  □1□과 □0□으로 모든 것을 다 표현할 수 있었습니까? 그렇지는 않죠. K-map을 배웠다면 Don't care도 배웠을 것입니다. 그리고 결과를 표시할 수 없는 Undefined도 배웠을 것입니다. 그러니 □1□과 □0□이 모든 것을 표현할 수는 없습니다. 그래서 IEEE에서는 표준화되어서 나온 것이 Std_logic입니다. Std_logic은 nine values을 가지고 있습니다.

'U',  -- Uninitialized

'X',  -- Forcing  Unknown

'0',  -- Forcing  0

'1',  -- Forcing  1

'Z',  -- High Impedance

'W',  -- Weak     Unknown

'L',  -- Weak     0

'H',  -- Weak     1

'-'   -- Don't care

디지털 전자 회로를 표현하기 위해서는 이것이 정의되어야 합니다. 자연스럽게 알게 되는 내용이니 이런 것이 있구나 정로로 여기로 넘어갑시다. 그리고 VHDL 논리 연산으로는 AND, NAND, OR, NOR, XOR, XNOR, NOT가 있습니다. 위의 예제에서 쓰인 것처럼 연산을 직접하면 됩니다.  예제 처음에 □--□이라는 표시가 있지요. 이것은 C에서처럼 주석을 표시합니다. 한 문장의 끝까지 주석으로 처리합니다. 주석 입력이 한글로 되지 않는 툴이 많습니다. 심지어 한글로 된 디렉토리까지 읽지 못하는 경우도 있으니 되도록 디렉토리나 파일명을 영어로 입력하기를 바랍니다.

다음은 Assign에 대해서 설명하겠습니다.

z <= (a and b) or c;

입력포트로서 signal assign의 소스(source)측 ( Signal일 경우 '<=', Variable일 경우 ':=' 의 오른쪽, R-Value)에만 쓸 수 있습니다. OUT은 출력포트로서 signal asign의 목적지(destination) ('<=' 또는 ':='의 왼쪽, L-Value)에만 쓸 수 있습니다. 위 예제에서 입력은 a, b, c로 정해져 있고 출력은 z로 정해져 있습니다. 아니 우리가 그렇게 입출력을 정했죠. 지금과 같이 입출력 모드가 정해진 경우 할당문(assign statement)에서는 엄격한 규정으로 하드웨어를 다룹니다. 하드웨어를 기술할 때 assign이란 연결관계를 표현한 것(netlist)으로서 프로그래밍 언어에서와 같은 오퍼레이션(move operation)과는 다른 의미입니다.

두 예제를 분석하는 데에도 상당히 장난이 아니죠.

위 그림처럼 두 개의 게이트와 3개의 입력 패드 와 한 개의 출력 패드만 있으면 되는데 말이죠.

다음 예제 3가지 모두 같은 기능을 가지는 4×1 Mux입니다. 예제 3과 4는 Concurrent하게 설계되었고 나머지 하나는 Process 문안에서 Sequential하게 설계되었습니다.

ex3) library ieee; use ieee.std_logic_1164.all; entity mux41 is port ( a, b, c, d : in std_logic; sel : in std_logic(1 downto 0); y : out std_logic); end mux41; architecture rtl of mux41 is begin y <= a when ( sel = "00" ) else b when ( sel = "01" ) else c when ( sel = "10" ) else d when ( sel = "11"); end rtl;	ex4) library ieee; use ieee.std_logic_1164.all; entity mux41 is port ( a, b, c, d : in std_logic; sel : in std_logic(1 downto 0); y : out std_logic); end mux41; architecture rtl of mux41 is begin with sel select y <= a when "00", b when "01", c when "10", d when "11"; end rtl;

ex5)

library ieee;

use ieee.std_logic_1164.all;

entity mux41 is

port ( a, b, c, d : in std_logic;

sel     : in std_logic_vector(1 downto 0);

y     : out std_logic);

end mux41;

architecture rtl of mux41 is

begin

process(sel, a, b, c, d)

begin

case sel is

when "00" => y <= a;

when "01" => y <= b;

when "10" => y <= c;

when others => y <= d;

end case;

end process;

end rtl;

예제 3, 4, 5 모두가 1-way 4 ×1 Mutiplexer를 설계한 것이다. 이제부터의 예제에서는 사용되는 문법을 익히기 바란다. 예제 3, 4와 예제 5가 다른 점은 Process문이 없다는 것이다. 앞에서도 설명했듯이 Concurrent와 Sequential 문이 차이지만 기능은 같다. 여기서 자기 스타일에 맞는 예제를 선택해 자기 자신의 코딩 스타일을 갖는 것은 중요하다. 그 전에 Delay 문제와 Gate Counter를 통해 어떤 것이 가장 잘 설계되었는지 확인하는 것이 중요하다. 대부분의 Vendor Tool에는 Gate Counter가 내장되어 있다. (없는 것도 있지만)

가장 체적화 되어있는 방식을 책택하는 것이 좋겠다. 이것은 가르쳐 줄 수 있는 문제가 아니라 자기 자신이 직접 경험으로 아는 것이 중요하다.

문법(?)적인 설명을 하자면 예제3의 When-else 문은 Process 문에서는 사용될 수 있는 코딩이다. 마찬가지로 Case-when 문은 Process문 밖에서는 사용될 수 없다. 지금 현재는 모든 코딩을 Signal Assign으로 가고 있다. Signal 뿐만아니라 Variable 이라는 것도 있다는 것을 알고 있기를 바란다. (Variable Assign은 □ := □ 이다.) Signal 과 Varlable을 지금 동시에 설명한다면 현재로서는 이해하기 어려울 것이다. 그래서 그 부분은 잠시 미루기로 하겠다.

Case-when은 범용적으로 잘 사용되는 스타일이므로 잘 기억하기 바랍니다.!!

std_logic은 1비트를 설명하는 것이며 1비트 이상에서는 std_logic_vector(n downto 0) 사용합니다. std_logic_vector(n downto 0)은 n비트를 표시하는 것이며, 여기서 n은 MSB를 나타내는 것입니다. 또한 std_logic_vector(0 to n)은 0이 LSB를 표시합니다.

또, 1비트에서는 □0□ 또는 □1□를 표시하고 1비트 이상에서는 □00□ 큰 따옴표를 사용해요.

그럼 2-way 4×1 Multiplexer를 한 번 설계해 보세요. 그러니까 입력 4개가 각각 2비트이고, 출력이 2비트를 설계하는 것입니다. 그리고 4-way 4×1 Multiplexer를 한 번 스스로 설계해 보세요. (숙제)

그리고 참조로 말씀드리면 대부분의 고급 설계 툴은 Unix 환경에서 작동하는 것이 많습니다. 그러니 당연히 Unix의 기본은 알고 있어야 하겠죠. Unix 환경을 구하기 힘들다면 Linux를 한 번 시도해 보는 것도 좋습니다. vi 에디터 정도는 기본적으로 알고 있어야 합니다. 잔소리!!!