계산기 설계1. Introduction1)LCD를 이용하여 계산기를 설계 할 수 있다.2)LCD출력 특성에 대해 알 수 있다.3)FPGA 보드에 있는 다양한 스위치들을 다뤄 볼 수 있다.4)여러 개의 entity가 어떤 구조로 실행되는지 생각해봄으로써 VHDL 프로그램의 구조를 좀 더 폭넓게 이해 할 수 있다.2. Problem Statement① Describe what is the problem.이번 실습에서 우리에게 주어진 entity는 세 개이지만, 우리가 소스코드를 완성시켜야 할 entity는 data_gen entity이다. data_gen entity는 다음과 같다.entity data_gen isPort ( FPGA_RSTB : in STD_LOGIC;FPGA_CLK : in STD_LOGIC;w_enable : in STD_LOGIC;data_out : out STD_LOGIC;addr : out STD_LOGIC_VECTOR (4 downto 0);data : out STD_LOGIC_VECTOR (7 downto 0);load_operand1 : in STD_LOGIC;load_operand2 : in STD_LOGIC;load_plus : in STD_LOGIC;load_minus : in STD_LOGIC;calculate : in STD_LOGIC;operand : in STD_LOGIC_VECTOR (3 downto 0));end data_gen;표 data_gen entityㄱ)실습해야할 내용☞ 4비트 덧셈/뺄셈기 설계☞ 4비트로 표현되는 16진수 2개의 덧셈 또는 뺄셈을 실시한 후 결과를 LCD를 통해서 출력한다.☞ 덧셈과 뺄셈은 unsigned로 한다.☞ 연산을 위한 숫자 두 개는 DIP 스위치를 통해서 설정하고 PUSH 스위치를 통해서 각각 입력한다.☞ 연산자는 두 개의 PUSH 스위치를 이용하여 각각 입력한다.☞ 연산을 수행하는 PUSH 스위치를 이용하여 연산을 하고 결과를 출력한다.ㄴ)연산과정① DIP 스위치로 16진수 설정② OPERAND1 PUSH 스위치 누르면 register file에 데이터 저장③ DIP 스위치로 16진수 설정④ OPERAND2 PUSH 스위치 누르면 register file에 데이터 저장⑤ + 또는 - PUSH 스위치를 누르면 register file에 데이터 저장⑥ CALCULATE PUSH 스위치를 누르면 덧셈 또는 뺄셈 연산 후 연산결과를 register file에 저장※ 이 때 LCD 출력은 LCD_test module을 통해서 자동으로 이루어 짐ㄷ) 소스코드의 구조그림 소스코드 구조☞LCD_DISPLAY : LCD_test module과 data_gen module을 통합하는 최상위 module☞LCD_TEST : LCD를 초기화 시키고 register file로부터 데이터를 읽어서 LCD에 출력하는 module☞DATA_GEN : 외부 DIP 스위치 및 PUSH 스위치를 통해서 데이터를 읽어서 register file 에 저장 및 계산 결과 저장ㄹ) 입력 스위치DIP_SW(0:3): 16진수 한 자리를 표현PUSH1: DIP_SW를 통해서 설정된 16진수를 operand1로 설정: LCD의 첫 열, 첫 칸에 16진수로 표시PUSH2: DIP_SW를 통해서 설정된 16진수를 operand2로 설정: LCD의 첫 열, 세 번째 칸에 16진수로 표시PUSH3: operand1과 operand2를 이용하여 operator대로 연산 실시: LCD의 첫 열 네 번째 칸에 ‘=’을 표시하고 계산하여야 함PUSH_SW0: operand1과 operand2에 대해서 덧셈 연산을 설정: LCD의 첫 열 두 번 째 칸에 ‘+’를 표시PUSH_SW1: operand1과 operand2에 대래서 뺄셈 연산을 설정: LCD의 첫 열 두 번째 칸에 ‘-’를 표시RESET : LCD에 표시되는 내용을 지우고 새로운 입력을 받을 준비※ PUSH 스위치는 Active 'L'임을 감안하여 소스코드를 작성 할 것ㅁ) LCD 출력 예시그림 LCD 출력 예시?입출력 범위입력 : 0 ~ F(16진수)출력 : 00 ~ FF(16진수)ㅂ) Pin tableSignalPinSignalPinFPGA_CLKp79LCD_A(0)p50operand(3)(DIP_SW0)p12LCD_A(1)p51operand(2)(DIP_SW1)p13LCD_ENp52operand(1)(DIP_SW2)p15LCD_D(0)p57operand(0)(DIP_SW3)p16LCD_D(1)p58Load_plus(PUSH_SW0)p18LCD_D(2)p61Load_minus(PUSH_SW1)p19LCD_D(3)p62Load_op1(PUSH1)p102LCD_D(4)p63Load_op2(PUSH2)p101LCD_D(5)p64Calculate(PUSH3)p100LCD_D(6)p65FPGA_RSTBp205LCD_D(7)p67표 Pin table② Describe how do you solve the problem.(1)DIP_SW를 통해 들어오는 4비트 데이터를 어떻게 LCD 출력으로 연결시킬 것인가를 생각해야 할 것이다. DIP_SW는 4개가 있기 때문에 이 스위치들로 총 16개의 데이터를 표현할 수 있다. 2진수로 생각해보면 0000 ~ 1111까지 표현할 수 있을 것이며, 10진수로 생각해보면 0 ~ 15까지 표현할 수 있을 것이고, 16진수로 생각해보면 0 ~ F까지 표현할 수 있을 것이다. 이렇게 입력으로 들어온 데이터를 16진수로 LCD에 출력하고 싶다면 reg_file에는 어떤 값이 들어가야 할까?이것은 character font table을 참조해야만 알 수 있을 것이다. 그런데 이 character font table에 있는 출력문자의 upper 4비트와 lower 4비트를 16진수로 표시하면 아래의 table의 LCD 행에 있는 값들을 얻게 된다. 이 table을 통해 알 수 있는 것은 입력으로 들어온 데이터와 reg_file로 보내줘야 데이터들의 관계이다. table을 자세히 보면 입력으로 들어온 값이 0~9 사이일 때, 그 값에 X"30"을 더해주면 입력으로 들어온 값을 그대로 LCD에 출력할 수 있다는 사실을 알 수 있다. 그리고 입력 값이 10~15사이에 있으면, 그 값에 X"37"을 더해줬을 때 입력 값을 그대로 LCD에 출력할 수 있음을 알 수 있다. 이를 잘 이용하면 reg_file에 보내줘야 할 값들을 결정할 수 있을 것이다.Decimal012345*************415Hexa0123456789ABCDEFLCD*************6*************44546표 Decimal/ Hexa/ LCD(2) 덧셈과 뺄셈에서 두 자리 수 출력되는 경우는 어떻게 생각해야 할까?덧셈과 뺄셈은 +연산자와 -연산자를 이용함으로 구현할 수 있을 것이다. 하지만 문제는 그 연산 결과를 어떻게 LCD 출력으로 내보내는가 하는 것이다. 이것에 대해 알아보기 위해 한 가지를 예를 생각해보았다.ex) A + 9 (1010 + 1001 )첫 번째 operand로는 A, 두 번째 operand로는 9, 그리고 연산자가 ‘+’로 들어온 경우이다. 이 때 calculate push 버튼을 누르면 LCD에는 ‘=’ 기호와 함께 13이라는 출력이 나와야 할 것이다. 왜냐하면 연산결과는 16진수여야 하기 때문이다.첫 번째 operand에는 2진수로 1010 값이 들어있을 것이며, 두 번째 operand에는 1001 값이 들어있을 것이다. 그런데 이 두 값을 더하면 MSB에서 carry가 발생하여 결과는 10011이 되고 5비트가 되게 된다. 4비트로는 표현할 수 없는 데이터가 나오게 되는 것이다. 우리는 이를 방지하기 위해 operand로 들어오는 4비트의 데이터를 5비트로 바꿔주는 작업을 해줘야 할 것이다.이 작업이 끝나게 되면 첫 번째 operand의 값은 01010이 되며, 두 번째 operand의 값은 01001이 되는 것이다.(최 상위 비트에 0 추가) 따라서 연산결과는 정상적으로 10011이 될 것이다. 그렇다면 우리는 이 값을 어떻게 13으로 LCD에 출력할 수 있을까? 여러 번의 모의 연산을 통해 최종적으로 다음과 같은 결론을 얻을 수 있었다.1 0 0 1 116진수 : 1 3즉, 연산결과의 MSB 값이 1이냐 0이냐를 확인해봄으로 써 우리는 LCD의 첫 열 다섯 번째 칸에 1을 출력해야할지 또는 0을 출력해야 할지를 결정할 수 있다는 뜻이다. 위와 같이 연산결과의 MSB가 1일 경우에는 결과 값으로 LCD에 16진수 두 자리가 출력될 것이며자리 값은 1이 돼야 하는 것이다. 만약 연산결과의 MSB가 0이면자리 값에는 0이 출력돼야 할 것이다. 이러한 특성을 이용하여 덧셈 뺄셈 연산의 결과를 출력하는 소스코드를 작성하였다.3. Implementation다음은 이 프로그램을 구성하는 entity 중 하나인 data_gen의 중요한 port들에 대한 개략적인 설명이다.☞FPGA_RSTB : LCD에 표시된 내용을 지우고, 계산기를 reset 하는 역할☞FPGA_CLK : 오실레이터의 4MHz clock이 입력되는 port☞load_operand1 : 첫 번째 피연산자를 저장하게 하는 port☞load_operand2 : 두 번째 피연산자를 저장하게 하는 port☞load_plus : '+'기호를 출력하게 하는 port☞load_minus : '-'기호를 출력하게 하는 port☞calculate : '='기호의 출력과 함께 연산을 수행하게 하는 port☞operand : DIP_SW로 입력데이터를 받는 port♣이번 실습의 목표가 입력데이터와 LCD 출력데이터 간의 관계를 밝히고, 계산기의 덧셈, 뺄셈 연산 알고리즘을 짜보는 것이기 때문에 이에 대한 소스코드만 중점적으로 알아보고자 한다.아래의 process는 data_gen entity 안에 있는 process이다.process(FPGA_RSTB, FPGA_CLK)beginif FPGA_RSTB = '0' then ……①for i in 0 to 31 loopreg_file(i)
Shift register 설계1. Introduction1)Flip-Flop에 대해 이해한다.2)VHDL 언어를 통해 shift register를 설계 할 수 있다.3)shift register에 쓰이는 DFF를 이해한다.4)다양한 shifter들의 개념과 동작원리에 대해 이해할 수 있다.2. Problem Statement① Describe what is the problem.Purpose: shift register는 circular shifter/ logical shifter/ arithmetic shifter를 구현? shift register들은 비동기 reset 및 동기 enable 로 작동하도록 구현할 것? mode port를 통해 shifter의 종류를 선택? direction port를 통해 shift를 왼쪽으로 할 것인가 오른쪽으로 할 것인가를 결정실습 시에 entity는 다음을 따를 것entity shifter isPort ( clk, reset, enable, dir : in STD_LOGIC;mode : in STD_LOGIC_VECTOR(1 downto 0);pi : in STD_LOGIC_VECTOR(3 downto 0);q : out STD_LOGIC_VECTOR(3 downto 0));end shifter;표 shifter entityshifter 구현은 아래의 표를 따른다.표 프로그램 동작 표② Describe how do you solve the problem.비동기 reset 이므로 reset 의 동작은 CLK의 영향을 받지 않는다.표2 에 따르면 reset이 L(low) 일 때는 다른 port 들이 don't care term이 되고 출력 Q는 L로 세팅 된다. reset이 H(High) 일 때, CLK의 rising edge 와 enable의 값에 따라 회로가 본격적으로 동작하게 된다.enable 이 L이면 Q는 이전 값을 유지하게 되고, H이면 mode의 값에 따라 그리고 dir의 값에 따라 shift의 종류와 shift의 방향이 결정된다.shift의 종류가 총 3개이며, 데이터의 입력을 표현해야 하므로 mode의 비트 수는 적어도 2개여야 하며, 방향은 왼쪽 오른쪽만 결정하면 되므로 1비트면 충분하다. 보다 구체적인 동작 설명은 표로 대신한다.그리고 clock의 주기는 10 ns로 한다.?각 circular shifter, logical shifter, arithmetic shifter들에 대한 알고리즘을 작성?각 shifter들을 clock과 reset, enable, mode, direction port 들과의 연결 방법?Circular shift는 각 비트의 데이터들을 방향이 오른쪽인 경우 한 비트 아래로 이동시키는 shift, 이 때 가장 하위에 있는 비트(LSB)의 데이터는 최상위 비트(MSB)로 이동그림 오른쪽 circular shift에 대한 설명도?Logical shift는 각 비트의 데이터들을 방향이 오른쪽인 경우 한 비트 아래로 이동시키는데, 이때 최하위 비트의 데이터는 사라지며 최상위 비트는 0으로 채워짐그림 오른쪽 logical shift에 대한 설명도?Arithmetic shift는 shift 연산이 일어나도 부호가 일정하게 유지된다는 특징을 가지고 있음. 부호를 유지하기 위해 최상위 비트를 유지하기도 하며(오른쪽 방향인 경우), 또는 최하위 비트를 0으로 채우게 됨그림 오른쪽 arithmetic shift에 대한 설명도그림 왼쪽 arithmetic shift에 대한 설명도?shifter의 동작이 표2를 따라야 하므로 먼저 reset과 CLK rising edge는 독립적인 조건으로 다뤄야 할 것이다. CLK 과 reset 뿐만이 아니라 프로그램 전체적으로 여러 가지 port들이 조건으로 작용하기 때문에 if-elsif 구문을 활용한다.?주의해야 할 점: 각 조건들의 우선순위를 고려한다. 앞에서 언급한 대로 reset과 CLK rising edge가 최우선 순위를 가지며 그 다음은 enable, mode, direction 순이다.3. Implementationclk : clock port. 10 ns 주기로 clock을 형성한다.reset: reset 기능을 하는 port.enable: enable의 기능을 하는 port. clock과 동기로 작동한다.dir : shift direction을 표시해주는 port.mode: 회로 동작의 mode를 결정 해주는 port.pi: 4비트 데이터 입력 port.q: 4비트 데이터 출력 port.표 각 port 설명이 회로는 비동기 reset 및 동기 enable로 동작하는 회로이다. 이 회로의 특성을 if-elsif 구문으로 구현하면 다음과 같다.if(reset = '0') thenin_q
Memory 설계1. Introduction1)ROM과 RAM의 특징을 안다.2)RAM(Random Access Memory)를 VHDL로 구현 한다.3)VHDL 문법 중 Type declarations에 대해서 안다.2. Problem Statement① Describe what is the problem.Purpose: 메모리를 설계하려면 가장 먼저 데이터를 저장할 수 있는 공간을 만들어야 하는데, 그 공간을 어떻게 만들 수 있는지와 데이터를 메모리에 쓸 때 어떤 문법을 사용하여 쓸 수 있는지에 대해 초점을 맞춰 설계한다.메모리는 clock의 상승에지에서 동작하도록 하며, enable port와 write enable port가 동기로 동작하고 특히 write enable 값에 따라 메모리를 읽기, 쓰기모드로 동작시킬 수 있도록 설계한다.?RAM의 entity는 다음과 같이 구성한다.entity raminfr isPort ( clk, en, we : in STD_LOGIC;addr, di : in STD_LOGIC_VECTOR(3 downto 0);do : out STD_LOGIC_VECTOR(3 downto 0));end raminfr;표 RAM의 entity※Port 설명clk : clock port. 10 ns 주기로 clock을 형성en : enable의 기능을 하는 port. clock과 동기로 작동we : write enable의 기능을 하며 clock과 동기로 작동L(0)일 때는 읽기모드, H(1)일 때는 쓰기모드로 동작addr : 데이터를 쓸 때 또는 읽을 때, 데이터의 주소를 알려주는 port.di : 4비트 데이터 입력 port.do : 4비트 데이터 출력 port.?RAM의 동작은 다음의 진리표를 따른다.ENWEADDRDICLKDOLXXX↑XHLRead addressX↑Read dataHHWrite addressWrite data↑Write data표 RAM 동작 진리표※고려사항모든 동작은 clock이 상승에지일 때 일어난다.en이 we 보다 우선되도록 설계돼야 하며, en이 Low일 때는 다른 port들의 값들이 don't care term이 된다.en이 High이고 we가 Low이면 프로그램은 읽기 모드가 되어 주소(addr)값에 있는 데이터를 읽어 출력데이터(do)로 낸다.en이 High이고 we가 High이면 프로그램은 쓰기 모드가 되어 입력데이터(di)로 들어온 데이터를 주소 값에 쓰게 된다.clock 주기는 10 ns 로 설정하며 testbench input의 초기 값은 0으로 한다.② Describe how do you solve the problem.?데이터를 저장할 수 있는 공간을 생성한다. VHDL에서는 type declaration 을 사용할 수 있다. Type declaration의 예문은 다음과 같다.type ram_type is array( 15 downto 0 ) of std_logic_vector( 3 downto 0 );표 type declaration이 문장은 ram_type 이라는 이름을 갖는 데이터 유형을 선언하는 문장이다. 이 데이터 유형은 4비트의 벡터가 총 16개 들어갈 수 있도록 선언되어 있다.?메모리에 데이터를 쓰는 것과 불러오는 것, 쉽게 생각하면 저장 공간에 데이터를 할당 하고 읽어 오는 것이라고 볼 수 있다. 즉,
Multiplexer 설계1. Introduction1) Encoder와 Decoder의 원리를 이해한다.2) MUX(멀티플렉서)의 작동 원리를 이해한다.3) 8x1 MUX를 VHDL언어로 구현 할 수 있다.4) 2x1 MUX를 이용하여 8x1 MUX를 구현 할 수 있다.5) when else구문에 대해서 익힌다.2. Problem Statement① Describe what is the problem.Purpose: 2x1 MUX 7개를 이용하여 8x1 MUX 1개를 구현해 내는 것? 우선은 2x1 MUX를 구현? 2x1 MUX 7개를 연결? 어떻게 연결해야 하는 가를 결정? 각 2x1 MUX의 입력과 출력은 무엇인가?? MUX의 출력은 다시 어떤 2x1 MUX의 입력이 되는 것인가?? 선택선의 사용결정? 8개의 입력이 있으면 선택선은 최소 3개가 있어야 함? 2x1 MUX 하나하나에 선택선 하나가 반드시 필요? when else 구문 사용법을 알아서 생각해낸 알고리즘을 소스코드를 작성② Describe how do you solve the problem.8x1 MUX를 구현하기 위해서는 먼저 2x1 MUX를 구현해야 한다.그림 2x1 MUX2x1 MUX는 말 그대로 2개의 입력을 받아 선택선에 따라 1개의 출력을 내보내는 MUX이다. 때문에 2개의 입력포트와 1개의 출력포트가 있으면 될 것이다. 그리고 선택 조건에 필요한 1비트 포트도 하나 있어야 한다. 이 포트(port name: s)는 level에 따라 다음과 같이 사용하면 된다.(그림 2)그림 2x1 MUX를 이용한 8x1 MUX diagram즉, 2x1 MUX에 필요한 1비트의 선택선을 3 level로 연결하여 3비트의 선택선으로 이용하는 것이다. 그래서 3비트 중 LSB는 Level 1에 있는 2x1 MUX 들의 선택비트가 되며, 3비트 중 가운데 비트는 Level 2의 MUX들, 그리고 MSB는 Level 3의 MUX의 선택비트가 된다.2x1의 MUX가 만들어진 후에는, 이 2x1 MUX를 component로 이용하는 entity를 생성한다. 그리고 나서는 각 2x1 MUX의 입력과 출력을 잘 고려하여 component와 그곳에 들어가는 입출력 신호를 정해주면 된다.3. Implementation8x1 MUX를 구현하기 위해서는 2x1 MUX가 필요하다. 2x1 MUX(source code file name: mux2.vhd)의 입력포트는 i(std_logic_vector(1 downto 0))와 s(STD_LOGIC)이며, 출력은 o(STD_LOGIC)이다. i 는 입력데이터로서 2개의 값을 가지며 s는 선택선, o는 출력 데이터를 나타낸다. 2x1 MUX를 만드는 데 있어서 가장 중요한 구문은 바로 아래의 구문이다.o '0');--Outputssignal o : std_logic;BEGIN-- Instantiate the Unit Under Test (UUT)uut: mux8_2 PORT MAP (i => i,s => s,o => o);stim_proc: process --process descriptionbegini
4-bit 가산기 설계1. Introduction1) 비트의 덧셈, 뺄셈과 관련하여 반가산기, 전가산기, 보수(complement) 이론 등을 확실히 이해한다.2) 조합논리회로의 기본이 되는 4비트 감가산기의 동작원리를 이해한다.3) VHDL simulation을 위하여 Model Technology/Mentor Graphics의 “ISE WebPACK 및 ModelSim”을 사용법을 익힌다.4) 4비트 감가산기를 VHDL언어로 구현 할 수 있다.2. Problem Statement① Describe what is the problem.?1비트 신호에 대한 전가산기를 구현?1비트 전가산기를 component(FA) 로 이용하여 4비트 신호에 대한 감가산기 구현⇒각 비트와 FA가 하나씩 대응?이 때 각 FA의 carry-out이 다음 FA의 carry-in이 된다는 사실을 프로그램에 적용※주의1)감산기를 구현할 때 2의 보수법을 이용※주의2)m의 값을 이용하여 m=0 일 때, 연산기가 가산기로 작동m=1 일 때, 연산기가 감산기로 작동그림 1비트 전가산기그림 4비트 감/가산기 다이어그램(2의 보수 이용)② Describe how do you solve the problem.반가산기 같은 경우는 입력 신호로 피 연산 신호만 필요하다. 예를 들어 x, y를 더하고자 한다면 carry-in 필요 없이 x, y만 있으면 된다. 그러나 전가산기 같은 경우는 x, y에다 carry-in까지 필요하다. 전가산기의 출력은 s, carry-out 이다. 입력 신호들과 carry-in을 적절하게 연산시켜주면 4비트에 대한 가산기를 구현할 수 있을 것이다.4비트 감/가산기를 구현할 때는 가장 먼저 입력 신호 x, y와 출력 신호 s를 std_logic_vector(3 downto 0)로 선언해야 한다. 왜냐하면 이 세 신호들은 4비트의 정보를 가지고 있어야 하기 때문이다.그리고 이미 만들어 놓은 전가산기를 하나의 component로 취급하여 비트 하나하나에 적용하는 것이다. 그렇기 때문에 1bit Full_adder 4개가 필요하다.이 때 중요한 것은 port map을 어떻게 작성하느냐 하는 것이다. 맨 위의 FA(0)에 들어갈 carry-in신호가 없으므로 미리 선언해둔 ci신호가 들어가야 할 것이다. (ci는 덧셈에서는 더해지는 1에 불과 하지만 뺄셈 시에는 음수 표현을 위해 사용된다는 것에 유념하자.) 또한 첫 번째 FA의 carry-out이 두 번째 FA의 carry-in으로 들어간다는 사실을 적용하기 위해서 FA(i)의 carry-out 신호와 FA(i+1)의 carry-in 신호를 똑같은 이름으로 사용하면 될 것이다.마지막으로 이 연산기가 감산기로도 작동하게 하기 위해서 m(mode)이라는 신호를 적절하게 사용해야 할 것이다. 위의 다이어그램(4비트 감/가산기 다이어그램)을 참고하여, y와 m을 XOR 연산한 값을 새로운 입력신호(z)로 사용하면 구현이 가능할 것이다.3. Implementation전가산기(entity name: Full_adder) 에서의 입력신호(x, y, carry-in)와 출력 신호(s, ci)의 관계이다.s