#1. Full adder(전가산기)
논리회로설계실험(VHDL) 2020. 10. 22. 00:04앞으로 이 게시판에서는 논리회로설계실습에서 사용된 알고리즘과 코드에 대해서 설명할 예정입니다.
이용 프로그램은 Xillings를 이용합니다.
1. 배경이론 Full adder
1비트의 2진수를 3개를 더하는 논리회로입니다. 2개의 xy 값을 받고 carrin는 앞자리의 비트에서 carryout이 일어났을때 다음 자리로 자리올림을 하는 역할을 합니다. 일단 먼저 truth table을 통해 논리식을 알아봅시다.
Truth table을 토대로, 논리식을 구성해본다. Sum의 경우, x, y, carryin(ci) 중 1이 1개나 3개가 1이어야 1이 나오고 그외에는 0으로 구성된다. 위 table에서 Sum이 1이 되는 4가지 경우를 논리식으로 나타내어 정리하면
S = x’y’ci + x’yci’ + xy’ci’+xyci = x’(y’ci+yci’)+x(y’ci’+yci) = x’(y ⊕ ci) + x(y ⊕ ci)’ = x ⊕ (y ⊕ ci) = x ⊕ y ⊕ ci = x xor y xor ci
마찬가지 방법으로 Carry out(co)도 나타내면
Co = x’yci + xy’ci + xyci’ + xyci = ci(x’y+xy’)+xy(ci’+ci) = ci(x⊕y) +xy
로 구성된다.
식으로는 이렇게 되지만, 다른 방법으로 생각해보면, Co가 x, y, ci중 1이 2개 이상일 때, 1이 되므로 (x and y) or (x and ci) or (y and ci)로 나타낼 수 있다.
이제, 이것을 4bit adder로 확장시키는 것은 Full adder 4개를 직렬로 연결시켜, 각각의 값을 순서대로 4비트로 나타내면 된다.
2. 4bit Full adder
Full Adder |
Carry in |
Carry out |
Sum |
이제 Full adder을 4개를 직렬로 붙여서 4bit의 계산을 하도록 만들어준다. 자일링스 상에서는 한개의 Fulladder을 구성한뒤 component를 이용하여 4개를 만들어준다. 여기서 한가지 우리는 abstractor도 만들게 되는데, 덧셈과 뺄셈이 모두 가능한 adder을 만들기 위해서 한가지 과정을 더 첨가한다. 바로 1의 보수와 2의 보수를 이용하여 뻴셈을 구현하는 것이다.
3. 1의보수, 2의 보수
위 표는 1의 보수를 나타낸 것입니다. 컴퓨터는 2진연산시 덧셈만 가능하기 때문에 뺄셈을 하기 위해서는 -부호 대신의 다른 방법이 필요하죠 그 방법중 하나가 1의 보수입니다. 1의 보수는 원래 2진수에서 숫자를 반전(0은 1로 1은0으로)시켜서 만드는 음수를 의미합니다 예를들어 -3이라면 +3인 0011에서 반전시켜 1100을 만들어 -3을 가리키는 방식입니다. 하지만 이 방식에는 +0과-0이 두개가 공존한다는 불편함이 존재합니다 이를 막기 위해 고안한 것이 2의 보수입니다.
2의보수는 1의 보수를 만든 상태에서 1비트를 더해서 만들어 줍니다. 예를들어 -3이라면 1의 보수로 1100을 만들고 1을 더한 1101이 됩니다. 이렇게 하면 겹치는 숫자가 존재하지 않고, 모든 숫자를 나타낼 수 있기 때문에 컴퓨터에서는 이런 방식을 통해 연산을 수행합니다.
4. 4비트 Fulladder/abstractor
위 모식도가 4bit로 구현한 덧셈/뻴셈 전가산기 입니다. 앞에 과정하나가 추가됬죠 y값과 m 값을 xor 연산하여 1의 보수로 만들어 주는 과정입니다. 이 연산한 값은 temp라는 배열에 들어가게 되고 fulladder에서 연산이 수행됩니다.
이제 코드로 한번 구현해 봅시다.
5. Fulladder 코드
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity full_adder is
Port ( x, y, ci: in STD_LOGIC; --포트 구성 input : x,y,carryin
s, co : out STD_LOGIC); --포트 구성 output : s, carryout
end full_adder;
architecture Behavioral of full_adder is
begin
s <= x xor y xor ci; --s의 경우 1이 홀수개면 1로, 짝수개면 0으로 나온다.
co <= (x and y) or (x and ci) or (y and ci); --carryout으로, 자리올림을 담당한다
end Behavioral;
이렇게 하면 1비트의 fulladder가 구현됩니다. s와 carryout에 아까보여주었던 논리식을 구현하여 대입하면 됩니다.
그리고 이것을 VHDL모듈을 하나 더 만들어서 4개를 불러옵니다.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity add4_sub is
Port ( x : in STD_LOGIC_VECTOR (3 downto 0); --포트구성 input : x(4bit)
y : in STD_LOGIC_VECTOR (3 downto 0); --포트구성 input : y(4bit)
cin : in STD_LOGIC; --포트구성 input : carryin(cin,1bit)
m : in STD_LOGIC; --포트구성 input : m (모드를 결정하는 인자,1bit)
s : out STD_LOGIC_VECTOR (3 downto 0); --포트구성 output : s(x, y cin의 합이 저장되는 비트, 4bit)
cout : out STD_LOGIC); --포트구성 output : cout(다음자리로 carry가 발생시 1이 되는 비트,1bit)
end add4_sub;
architecture Behavioral of add4_sub is --아키텍쳐부분
component full_adder port(x, y, ci : in STD_LOGIC; s, co : out STD_LOGIC); --만들어두었던, Full_adder을 component로 불러오기
end component; --컴포넌트 선언종료
signal temp : std_LOGIC_VECTOR (3 downto 0); --signal 선언 , y와 m의 xor 연산이 들어갈 temp 선언 ( m=1이면 반전되어 y가 temp에 들어가게 된다, 4bit)
signal c : STD_LOGIC_VECTOR (3 downto 0); --signal 선언 , 연산중간의 carry가 발생시 다음자리로 carry를 입력시킬때 쓰는 인자 c,4bit
begin
c(0) <= m xor cin; --m와 cin 을 xor 연산하여 c(0)값을 만들고 입력
temp(0) <= y(0) xor m; --m와 y를 xor 연산하여, m의 값에 따라, y를 반전시킬지 결정(뻴셈을 위해), 총4번의 adder
temp(1) <= y(1) xor m;
temp(2) <= y(2) xor m;
temp(3) <= y(3) xor m;
s_1 : full_adder port map (x(0), temp(0), c(0), s(0), c(1)); --Full_adder component 포트에 매핑, 순서대로 x, y, ci, s, co에 들어가게 된다.
s_2 : full_adder port map (x(1), temp(1), c(1), s(1), c(2));
s_3 : full_adder port map (x(2), temp(2), c(2), s(2), c(3));
s_4 : full_adder port map (x(3), temp(3), c(3), s(3), cout);
end Behavioral;
중간의 m은 모드로써 0일때는 덧셈, 1일때는 뻴셈을 구현하게 됩니다.(Y와 xor연산하여 음수형태로 만들어줌)
temp는 4비트의 배열로 내부신호로 구성하고
c는 자리올림을 담당합니다 carrout값을 받아서 다음 fulladder으로 넘겨주는 것이지요
가장 중요한것은 component 구문을 이용하여 만들어둔 fulladder 모듈을 불러오고, 그것을 architecture부분에서 4개를 구성하는 겁니다. port map을 이용하면 각 자리에 어떤 값이 들어갈지를 구성할 수 있습니다.
이를 이용하여 Testbench 를 만들어줍니다.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY add4_sub_TB IS
END add4_sub_TB;
ARCHITECTURE behavior OF add4_sub_TB IS
COMPONENT add4_sub
PORT(
x : IN std_logic_vector(3 downto 0);
y : IN std_logic_vector(3 downto 0);
cin : IN std_logic;
m : IN std_logic;
s : OUT std_logic_vector(3 downto 0);
cout : OUT std_logic
);
END COMPONENT;
--Inputs
signal x : std_logic_vector(3 downto 0) := (others => '0');
signal y : std_logic_vector(3 downto 0) := (others => '0');
signal cin : std_logic := '0';
signal m : std_logic := '0';
--Outputs
signal s : std_logic_vector(3 downto 0);
signal cout : std_logic;
BEGIN
uut: add4_sub PORT MAP (
x => x,
y => y,
cin => cin,
m => m,
s => s,
cout => cout
);
stim_proc: process
begin
--clock은 모두 제거하였고, input값인 x, y, cin, m의 값을 대입합니다.
x<="0000";
y<="0000";
cin<='0';
m<='0';
wait for 10ns;
x<="0010";
y<="0011";
cin<='0';
m<='0';
wait for 10ns;
x<="0011";
y<="1101";
cin<='1';
m<='0';
wait for 10ns;
x<="0101";
y<="0010";
cin<='1';
m<='0';
wait for 10ns;
x<="1100";
y<="1111";
cin<='1';
m<='0';
wait for 10ns;
x<="0101";
y<="0001";
cin<='0';
m<='1';
wait for 10ns;
x<="1010";
y<="0011";
cin<='0';
m<='1';
wait for 10ns;
x<="1111";
y<="1100";
cin<='0';
m<='1';
wait for 10ns;
x<="0011";
y<="1011";
cin<='0';
m<='1';
wait for 10ns;
x<="0100";
y<="0110";
cin<='0';
m<='1';
wait for 10ns;
x<="0000";
y<="0000";
cin<='0';
m<='0';
wait;
end process;
END;
클럭을 모두 제거하고
실험값들을 넣어주었습니다
결과 파동입니다. 십진수로 나타내는 방법은 숫자가 있는 부분에서 오른쪽 마우스를 누르고 radix에 들어가면 decimal로 바꾸는게 있을겁니다.
다음글에서는 multiplexer를 구현하는 방법에 대해서 알아보겠습니다.
#5. RAM/ROM (0) | 2021.03.08 |
---|---|
#4.Binary/Gray counter(이진,그레이 카운터) (0) | 2020.12.27 |
#3. FlipFlop(플립플롭)을 이용한 ShiftRegister 구현 (0) | 2020.12.24 |
#2. 8 to 1 Multiplexer (0) | 2020.12.20 |