Loading [MathJax]/jax/output/HTML-CSS/config.js

#5. RAM/ROM

논리회로설계실험(VHDL) 2021. 3. 8. 01:12
반응형

 

1. 배경이론


1)ROM (read only memory)

전원이 꺼져도, 정보를 저장하는 메모리로, n개의 입력변수에 2n 개의 출력단자를 가지는 decoder로 구성되며, 데이터를 읽어들일수는 있지만, 바꾸지는 못한다. 출력단자로 들어온 입력값을 주소값으로 인식하여, ROM상에 저장된 위치를 주소값으로 찾아 저장된 데이터를 출력으로 내보내는 방식이다. 아래의 그림은 ROM의 모식도를 나타내었다. Enable1이고 Clk이 바뀔때마다, 4bit의 주소값이 들어와, ram안에서 주소값을 이용하여 해당하는 위치의 데이터값을 출력으로 내보내는 회로이다.

Rom의 모식도

 

2)RAM(Random access memory)

전원이 꺼지면, 모든 데이터가 날아가는 방식의 메모리로, 읽고 쓰기가 모두 가능한 메모리이다. ROM과 마찬가지로 주소값을 통해, RAM상에 저장된 위치의 데이터 값을 찾아 출력하는 방식이다. 실습과정에서의 차이점은 ROM의 경우 처음부터 데이터값을 모두 저장하고 시작하지만, RAM의 경우 데이터값의 저장 없이 바로 사용할 수 있다.

RAM

3)배열과 type casting

Type (~) is array (~) of (~) 구문을 이용하여, 배열을 지정하고, 배열안에 들어갈 자료형과 비트수를 지정할 수 있다.  이번 실습에서는 type ram_type is array(15 downto 0) of std_logic_vector(3 downto 0) 이 구문을 활용하여 16개의 값을 갖는 배열안에 각각 4bit의 데이터를 저장할 수 있는 배열을 선언한다.

ram안에 들어있는 정보를 출력하기 위해서는 주소값을 통해 찾아내어야하는데, 입력되는 주소값이 이진수 형태이다 보니, ram안에서 배열안의 값을 가리키기 위해, 주소값을 정수(integer)형식으로 바꿔주어야하는데, 이때, conv_integer(addr) 이런식으로 구문을 써서, 2진수로 받아들여진 값을 정수형식으로 casting 하여 이용한다.

 

4)이번 실습에서 쓰이는 알고리즘

Flipflop을 이용하고, rising edge방식을 채택하며, enable값이 1일 때 동작한다. We값을 통해 ram배열안에서 read/write의 동작 여부를 결정한다. We=0일 때 read가 되어 ram안의 값들을 불러오고, we=1일 때 write가 되어, ram안에 주소 값에 따라 입력 데이터값이 저장된다. Enable0일때는 아무 동작도 실행하지 않는다.

동작표

 

2. RAM VHDL 코드


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;  --type conversion을 쓰기 위한 헤드

entity ram is
    Port ( clk : in  STD_LOGIC;                       --포트구성 input : clk,클럭값(1bit)
           en : in  STD_LOGIC;                        --포트구성 input : en,enable값(1bit)
           we : in  STD_LOGIC;                        --포트구성 input : we,write를 결정하는 값(1bit) we가 0일때 Read, 1일때 write
           addr : in  STD_LOGIC_VECTOR (3 downto 0);  --포트구성 input : addr, ram의 주소지(위치)를 결정하는 값(4bit)
           di : in  STD_LOGIC_VECTOR (3 downto 0);    --포트구성 input : di, 데이터 입력값(4bit)
           do : out  STD_LOGIC_VECTOR (3 downto 0));  --포트구성 output : do, 데이터 출력값(4bit)
end ram;                                              --entity 구문 종료

architecture Behavioral of ram is                     --아키텍쳐시작

	type ram_type is array(15 downto 0) of std_logic_vector(3 downto 0); --배열선언 ram_type은 16개(4bit)의 배열로 되어있고, 각 배열안에는 4bit의 값이 들어갈 수 있다.
	signal ram : ram_type;                              --내부신호 선언 ram, 앞에서 선언한 배열을 가진 신호
	signal read_addr : std_logic_vector(3 downto 0);    --내부신호 read_addr 선언, 주소값을 저장할 변수 

begin
	do<=ram(conv_integer(read_addr));                   --출력을 process 바깥에서 정의한다, ram안의 주소에 따라 저장된 데이터가 do로 출력된다. 
	process(clk)                                        --process 시작
		begin                                            
			if(clk = '1' and clk'event)then               --rising edge 방식으로 작동하는 clk 설정
				if (en = '1') then                         --en=1일때의 조건문 시작
					if(we='0') then                         --en=1이고, we=0일때의 조건문 시작(read address, data)
						read_addr <= addr;                   --내부신호 read_addr에 입력값 addr을 대입
					else                                    --en=1이고, we=1일때의 조건문(write address, data)
						read_addr <= addr;                   --내부신호 read_addr에 입력값 addr을 대입
						ram(conv_integer(addr)) <= di;       --addr값을 integer로 바꿔준 후, 입력값 di를 ram에서 해당하는 addr의 정수값의 위치에 대입(write data)
					end if;                                 --we값에 의한 조건문 종료
				end if;                                    --en값에 의한 조건문 종료
			end if;                                       --clk값에 의한 조건문 종료
		end process;                                     --process종료
	
end Behavioral;

 

 

3. Test Bench 코드


LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

 
ENTITY ram_TB IS
END ram_TB;
 
ARCHITECTURE behavior OF ram_TB IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT ram
    PORT(
         clk : IN  std_logic;                     --포트구성 input : clk(1bit), 클럭값
         en : IN  std_logic;                      --포트구성 input : en(1bit), enable 값
         we : IN  std_logic;                      --포트구성 input : we(1bit), write 동작 결정값 
         addr : IN  std_logic_vector(3 downto 0); --포트구성 input : addr(4bit), 입력 주소값
         di : IN  std_logic_vector(3 downto 0);   --포트구성 input : di(4bit), 입력데이터값
         do : OUT  std_logic_vector(3 downto 0)   --포트구성 output : do(4bit), 출력데이터값
        );
    END COMPONENT;
    

   --Inputs
   signal clk : std_logic := '0';                                  --입력signal 선언 clk,en,we,addr(4bit),di(4bit) 모두 0으로 초기화됩니다.
   signal en : std_logic := '0';
   signal we : std_logic := '0';
   signal addr : std_logic_vector(3 downto 0) := (others => '0');
   signal di : std_logic_vector(3 downto 0) := (others => '0');

 	--Outputs
   signal do : std_logic_vector(3 downto 0);                      --출력signal 선언 do(4bit)
 
   -- Clock period definitions
   constant clk_period : time := 10 ns;                           --clk, 클럭설정 10ns주기
 
BEGIN
 
	-- Instantiate the Unit Under Test (UUT)
   uut: ram PORT MAP (                       --유닛테스트
          clk => clk,
          en => en,
          we => we,
          addr => addr,
          di => di,
          do => do
        );

   -- Clock process definitions
   clk_process :process            --clk, 클럭 process 시작
   begin
		clk <= '0';                  --clk가 0으로 바뀐후 5ns대기
		wait for clk_period/2;
		clk <= '1';                  --clk가 1으로 바뀐후 5ns대기
		wait for clk_period/2;
   end process;                    
 

   -- Stimulus process
   stim_proc: process
	--여기서부터 실습에 주어진 조건과 값들이 대입됩니다.
   begin		
	
      wait for 53 ns;  --53ns 대기, 누적 53ns
		
		addr <= "0000";  --addr=0000, di=1111, we=1대입
		di <= "1111";
		we <= '1';
		wait for 10 ns;  --10ns대기, 누적 63ns
		
		en <= '1';       --en=1대입
		wait for 10 ns;  --10ns대기, 누적 73ns
		
		addr <= "0001";  --addr=0001, di=1110대입
		di <= "1110";
		wait for 10 ns;  --10ns대기, 누적 83ns
		
		addr <= "0010";  --addr=0010, di=1101대입
		di <= "1101";
		wait for 10 ns;  --10ns대기, 누적 93ns
		
		addr <= "0011";  --addr=0011, di=1100대입
		di <= "1100";
		wait for 10 ns;  --10ns대기, 누적 103ns
		
		addr <= "0100";  --addr=0100, di=1011대입
		di <= "1011";
		wait for 10 ns;  --10ns대기, 누적 113ns
		
		addr <= "1100";  --addr=1100, di=0011대입
		di <= "0011";
		wait for 10 ns;  --10ns대기, 누적 123ns
		
		addr <= "1111";  --addr=1111, di=0000대입
		di <= "0000";
		wait for 10 ns;  --10ns대기, 누적 133ns
		
		en <= '0';       --en=0, addr=0000, di=1111대입
		addr <= "1101";
		di <= "0010";
		wait for 10 ns;  --10ns대기, 누적 143ns
		
		we <= '0';       --we=0대입
		wait for 10 ns;  --10ns대기, 누적 153ns
		
		addr <= "0010";  --addr=0010대입
		wait for 10 ns;  --10ns대기, 누적 163ns
		
		en <= '1';       --en=1대입
		wait for 10 ns;  --10ns대기, 누적 173ns
		
		addr <= "0100";  --addr=0100대입
		wait for 10 ns;  --10ns대기, 누적 183ns
		
		addr <= "0011";  --addr=0011대입
		wait for 10 ns;  --10ns대기, 누적 193ns
		
		addr <= "1101";  --addr=1101대입
		wait for 10 ns;  --10ns대기, 누적 203ns
		
		report "Simulation end";  --simulation end 출력
		wait;
		
      -- insert stimulus here 

   end process;                 --process 종료

END;

 

결과 wave

반응형