VHDL Data Types
VHDL 데이터형
- VHDL에서는 사용자가 직접 데이터형을 선언할 수 있다.
- VHDL에서는 Type의 부분 Type (Subtype)을 선언할 수 있다.
- VHDL에서 Object는 거의 무한한 종류의 데이터형을 사용할 수 있다.
Scalar Type (1 Dimension) |
Integer Type |
Real Type | |
Enumerated Type | |
Physical Type | |
Composite Type (Multi Dimension) |
Array Type (Homogeneous Elements) |
Record Type (Heterogeneous Elements) |
|
Access Type | |
File Type |
* VHDL Predefined Data Types
BOOLEAN | INTEGER | CHARACTER |
BIT | POSITIVE | STRING |
BIT VECTOR | NATURAL | |
REAL |
Data Type Declaration
TYPE <type_name> IS <type_mark>;
* Data Type 선언 위치
1) Entity Declaration Section
2) Architecture Delcaration Section
3) Package Declaration Section
4) Process Declaration Section
5) Subprogram Declaration Section
Scalar Type
Integer Type (정수형)
- 정수형 범위는 System-Dependent하지만, 적어도 -2,147,483,647에서 2,147,483,647까지는 커버해야 한다.
Example. Integer Type
Type integer IS range -2147483647 to 2147483647;
Type byte IS range -127 to 127;
variable a : integer;
a := 1; -- OK
a := -1; -- OK
a := 1.0; -- Error
Real Type (실수형)
- 실수형의 범위는 System Dependent하지만, 적어도 -1.0E38에서 1.0E38까지는 커버해야 한다.
- 실수형의 최댓값과 최솟값은 High와 Low라는 Attribute를 사용하여 나타낼 수도 있다.
Example. Real Type
Type real IS range -1.0E38 to +1.0E38;
variable a : real;
a := 1.0; -- OK
a := -1.0E10; -- OK
a := 1.5E-20; -- OK
a := 1; -- Error
a := 5.3 ns; -- Error
Enumeration Type (열거형)
- 문자 혹은 문자열들이 값들로 정의된 데이터형이다.
Example. Enumeration Type
-- Predefined Enumerated Types
Type bit IS ('0', '1');
Type boolean IS (true, false);
Type severity_level IS (note, warning, error, failure);
-- User-Defined Enumerated Types
Type switch_level IS ('0', '1', 'X');
Type four_level IS ('0', '1', 'X', 'Z');
Type multi_level IS (low, high, rising, falling);
Type color IS (red, yellow, green);
* Bit Type (비트형)
- '0' 또는 '1'을 갖는 데이터 형이다.
- \(\texttt{std_logic_1164}\) Package 사용시, \(\texttt{bit}\) 대신 \(\texttt{std_logic}\)을 사용해야 한다.
Example. Enumeration Type with Package
package instruction_pkg is
type instruction_type is
(add, sub, lda, ldb, sta, stb, outa, xfr)
end instruction_pkg;
use work.instruction_pkg.all;
entity microprocessor is
port ( instr : in instruction_type;
addr : in integer;
data : inout integer );
end microprocessor;
architecture simple of microprocessor is
begin
process (instr)
type reg_type is array (0 to 255) of integer;
variable a, b : integer;
variable reg : reg_type;
begin
case instr is
when lda => a := data;
when ldb => b := data;
when add => a := a + b;
when sub => a := a - b;
when sta => reg(addr) := a;
when stb => reg(addr) := b;
when outa => data <= a;
when xfr => a := b;
end case;
end process;
end simple;
Example. State Machine
use work.std_logic_1164.all;
entity traffic_light is
port ( sensor, clock : in std_logic;
red_light : out std_logic;
green_light : out std_logic;
yellow_light : out std_logic );
end traffic_light;
architecture simple of traffic_light is
type three_state is (red, green, yellow);
signal present_state, next_state : three_state;
begin
process
begin
wait until clock'event and clock = '1';
present_state <= next_state;
end process;
process(present_state, sensor)
begin
case present_state is
when green =>
red_light <= '0';
green_light <= '1';
yellow_light <= '0';
next_state <= yellow;
when red =>
red_light <= '1';
green_light <= '0';
yellow_light <= '0';
if (sensor = '1') then
next_state <= green;
else
next_state <= red;
when yellow =>
red_light <= '0';
green_light <= '0';
yellow_light <= '1';
next_state <= red;
end case;
end process;
end simple;
Physical Type (물리형)
- 시간,거리, 전류, 등의 물리적 단위를 나타낼 때 사용하는 데이터형이다.
- 사용자가 범위를 정의할 수 있고, 범위를 지정하지 않은 경우, Default Range*로 지정된다.
* Default Range (=integer Type의 범위)
-2,147,483,647 ~ 2,147,483,647
Example. Physical Type (Time)
Type time IS range -1.0E38 to +1.0E38;
unit fs; -- base unit
ps = 1000 fs;
ns = 1000 ps;
us = 1000 ns;
ms = 1000 us;
sec = 1000 ms;
min = 60 sec;
hr = 60 min;
end unit;
Composite Type
Array Type (배열형)
- 같은 종류의 정수형을 하나의 배열로 묶어 사용할 수 있다.
- 선언 방법에 따라, 제한형과 무제한형으로 나뉜다.
1) Constrained Array Type (제한형)
- 이미 선언된 데이터형을 정해진 Index 범위내에서 열거하여 만든 배열형이다.
- 일종의 BUS형태의 데이터형이다.
Example. Constrained Array Type
Type byte IS array(7 downto 0) OF bit;
...
variable : byte
...
a := "01110000";
Example. Constrained Array Type with Package
package array_example is
type large_bus is array (0 to 31) of bit;
type small_bus is array (0 to 7) of bit;
end array_example;
use work.array_example.all;
entity extract is
port (data_in : in large_bus;
data_out : out small_bus;
start : in integer );
end extract;
architecture test of extract is
begin
process (data_in, start)
begin
for i in 0 to 7 loop
data_out(i) <= data_in (i + start);
end loop;
end process;
end test;
Example. Multi-Dimensional Array
varialbe x : std_logic;
constant width : integer := 3;
constant len : integer := 7;
type mem_t is array (0 to len, 0 to width) of std_logic
constant rom_data : mem_t :=
( ( '0', '0', '0', '0' ),
( '0', '0', '0', '1' ),
( '0', '0', '1', '0' ),
( '0', '0', '1', '1' ),
( '0', '1', '0', '0' ),
( '0', '1', '0', '1' ),
( '0', '1', '1', '0' ),
( '0', '1', '1', '1' )
);
...
x := rom_data (3, 3);
2) Unconstrained Array Type (무제한형)
- 제한형과 달리, 선언된 데이터형의 Index 사용 범위를 정하지 않고 사용할 수 있는 배열형이다.
Example. Unconstrained Array Type
Type bit_vector(natural range <>) OF bit;
Type string IS array(positive range <>) OF character;
Example. Unconstrained Array Type
function shift_r (val : bit_vector)
return bit_vector is
variable result : bit_vector (0 to val'length - 1);
begin
result := val;
if(val'length > 1) then
for i in 0 to val'length -2 loop
result(i) := result(i + 1);
end loop;
result(val'length - 1) := '0';
else
result(0) := '0';
end if;
return result;
end shift_r;
* Predefined Attribute of Array Type
a'LENGTH[N]
- \(\texttt{N}\)차원 \(\texttt{a}\) Array의 크기를 리턴하는 속성이다.
- \(\texttt{N}\)을 명시하지 않을 경우, Default로 1이 지정된다.
Record Type (레코드형)
- 다양한 Type의 Object들을 하나로 묶는 Type이다.
- 각각의 Field로 나누어서 별개의 데이터형을 선언할 수 있다.
- Record Type으로 선언된 Object의 Attribute를 참조하기 위해, Membership Operator로 Dot(.) Operator를 사용한다.
Example. Record Type
type op_type is (add, sub, mpy, div, jmp);
type instruction_type is
record
opcode : op_type;
src : integer;
dst : integer;
end record;
...
process(x)
variable instr : instruction_type;
variable src : integer;
begin
instr := (add, 1, 2);
src := instr.src;
end process;
Example. Record Type
-- Enumerated Types
Type MONTH_NAME IS ("JAN", "FEB", "MAR", "APR", "MAY", "JUN",
"JUL", "AUG", "SEP", "OCT", "NOV", "DEC");
type DATE is
record
DAY : INTEGER range 1 to 31;
MONTH : MONTH_NAME;
YEAR : INTEGER range 0 to 3000;
end record;
Example. Record Type
Type information IS
record value : bit;
context : integer;
end record;
...
variable kk : information;
...
kk.value := '1';
kk.context := 9;
...
Access Type (액세스형)
- C, Pascal의 Pointer Type과 유사하다.
- Access Type은 오로지 Variable만을 위한 데이터형이다.
- Access Type이 선언된 이후에는 Dynamic Memory Management를 위해
Predefined Function \(\texttt{new, deallocate}\)를 사용할 수 있다.
Example. Access Type
process (x)
type fifo_elem_ary is array (0 to 3) of std_logic;
type fifo_elem_acs is access fifo_elem_ary;
varialbe fifo_ptr : fifo_elem_acs := null;
begin
fifo_ptr := new fifo_elem_ary;
fifo_ptr.all := ('0', '1', '0', '1');
fifo_ptr.all(0) := 'X';
deallocate(fifo_ptr);
end process;
File Type (파일형)
- 파일 입출력에 관련된 데이터형으로, 외부와의 입출력, 특정 파일에 대한 변수를 선택하여 사용한다.
- VHDL의 회로 표현에 대한 검증 단계(Simulation Debugging)에서 많이 사용되는 데이터형이다.
- 특별한 회로 동작의 입출력을 제외하면 거의 사용되지 않는다.
- VHDL의 표준 패키지 \(\texttt{TEXTIO}\)에 선언되어 있다.
- 파일형은 Synthesis가 되지 않는다.
* Predefined Procedures and Functions of File Type
read(file, data) -- Procedure
write(file, data) -- Procedure
endfile(file) -- Function (return boolean value)
Example. File Type
Type TEXT is file of STRING;
file INPUT : TEXT is IN "std_input";
file OUTPUT : TEXT is OUT "std_output";
Example. File Type
TYPE int_file IS FILE OF INTEGER;
FILE myfile : int_file IS IN "/cho/test/data_file";
Example. File Type
USE work.std_logic_1164.all;
ENTITY rom IS
PORT( addr : IN integer;
cs : IN std_logic;
data : OUT integer );
END rom;
ARCHITECTURE rom OF rom IS
BEGIN
PROCESS(addr, cs)
TYPE rom_file_t IS FILE OF integer;
FILE rom_file : rom_file_t IS IN ("rom1.dat", "r");
TYPE data_t IS array(0 to 63) OF integer;
VARIABLE rom_data : data_t;
VARIABLE : integer := 0;
BEGIN
WHILE NOT ENDFILE(rom_file) AND (i < 64) LOOP
READ(rom_file, rom_data(i));
i := i + 1;
END LOOP;
IF (cs = '1') THEN data <= rom_data (addr);
ELSE data <= -1;
END IF;
END PROCESS;
END rom;
"std_logic" Type
- \(\texttt{std_logic_1164}\)를 선언하여 \(\texttt{std_logic}\) 데이터형을 사용할 수 있다.
std_logic 값 | Description |
'U' | 초기화되지 않은 값 (Uninitialized) |
'X' | 알 수 없는 값 (Unknown) |
'0' | 논리값 0 |
'1' | 논리값 1 |
'Z' | High Impedance 값 |
'W' | Pull-Up 혹은 Pull-Down된 알 수 없는 값 (Weak Unknown) |
'L' | Pull-Up 혹은 Pull-Down된 논리값 0 |
'H' | Pull-Up 혹은 Pull-Down된 논리값 0 |
'-' | Don't Care 값 |
Example. AND Gate
library ieee;
use ieee.std_logic_1164.all;
entity and_gate is
port (a, b : in std_logic;
c : out std_logic );
end and_gate;
architacture data_flow of and_gate is
begin
c <= a and b;
end data_flow;
Example. OR Gate
library ieee;
use ieee.std_logic_1164.all;
entity or_gate is
port ( a, b : in std_logic;
c : out std_logic );
end or_gate;
architecture data_flow of or_gate is
begin
c <= a or b;
end data_flow;
Example. XOR Gate
library ieee;
use ieee.std_logic_1164.all;
entity xor_gate is
port ( a, b : in std_logic;
c : out std_logic );
end xor_gate;
architecture data_flow of xor_gate is
begin
c <= a xor b;
end data_flow;
Example. AND / OR / NOT Gate
library ieee;
use ieee.std_logic_1164.all;
entity gate is
port ( x, y : IN std_logic;
and_out : OUT std_logic;
or_out : OUT std_logic;
not_out : OUT std_logic );
end gate;
architecture behavior of gate is
begin
and_out <= x and y;
or_out <= x or y;
not_out <= not x;
end behavior;
Subtypes
- 한 Type의 부분 Type을 선언할 수 있다.
- 어떤 Type의 Subtype으로 선언함으로써 Type Mismatching을 방지할 수 있다.
Example. Subtype
TYPE integer IS range -2147483647 to 2147483647;
SUBTYPE natural IS range 0 to integer'high;
* a'HIGH Attribute (URL)
Example. Subtype
PACKAGE subtype_pkg IS
subtype eightval IS integer range 0 to 7;
END subtype_pkg;
use work.subtype_pkg.all;
use work.std_logic_1164.all;
ENTITY mux8 IS
PORT( i0, i1, i2, i3, i4, i5, i6, i7 : IN std_logic;
sel : IN eightval;
q : OUT std_logic );
END mux8;
ARCHITECTURE mux8 OF mux8 IS
BEGIN
WITH sel SELECT
q <= i0 AFTER 10 ns WHEN 0,
i1 AFTER 10 ns WHEN 1,
i2 AFTER 10 ns WHEN 2,
i3 AFTER 10 ns WHEN 3,
i4 AFTER 10 ns WHEN 4,
i5 AFTER 10 ns WHEN 5,
i6 AFTER 10 ns WHEN 6,
i7 AFTER 10 ns WHEN 7;
END mux8;
VHDL Object (VHDL 객체)
- VHDL에서 사용되는 Obejct로는 signal, variable, constant 가 있다.
Signal
- 외부 변수이다. (해당 architecture 구문 전 영역에서 사용할 수 있다.)
- Synthesis시에, wire 또는 register로 구현된다.
- 시간에 따라 변하는 값을 갖는다. (\(\Delta\)-Delay)
- signal에 값(파형)이 인가될 때, 현재의 변화된 값이 바로 대입되지 않고, process문이 끝난 시점에 대입된다.
- 대입 시점에 대한 정보와 Signal Attribute로 인해 Signal은 Variable보다 더 많은 메모리 공간을 필요로 한다.
* signal의 선언 위치
1) Entity Declaration Section
2) Architecture의 Declaration Section
- architecture문과 begin문 사이
3) Package Declaration Section
4) subprogram의 parameter에서 선언
5) port signal에서 선언
Example. Signal Declaration in Package Declaration Section
use work.std_logic_1164.all;
package sigdecl is
type bus_t is array (0 to 7) of std_logic;
signal vdd : std_logic := '1';
signal gnd : std_logic := '0';
function magic_func(a : in bus_t) return bus_t;
end sigdecl;
Example. Signal Declaration in Entity Declaration Section
use work.sigdecl.all;
use work.std_logic_1164.all;
entity board_design is
port ( din : in bus_t;
dout : out bus_t );
signal clk : std_logic := '1';
end board_design;
architecture data_flow of board_design is
signal int_bus : bus_t;
begin
int_bus <= din when (clk = '1') else
int_bus;
dout <= magic_func(int_bus) when (clk = '0') else
('X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
clk <= not(clk) after 50 ns;
end data_flow;
* Signal Assignment
- Delta Delay 이후에 대입된다.
- Delay값을 명시하지 않을 경우, System 내부의 자체적인 Delay 이후에 대입되게 되므로,
가능하면+ Delay Time을 명시해야 한다.
- \(\texttt{<=}\) 연산자를 이용한다.
Example. 4 to 1 MUX (wrong and right)
use work.std_logic_1164.all;
entity mux4 is
port ( I0, I1, I2, I3, a, b : in std_logic;
q : out std_logic );
end mux4;
architecture wrong of mux4 is
signal muxval : integer;
begin
process (I0, I1, I2, I3, a, b)
begin
muxval <= 0;
if (a = '1') then muxval <= muxval + 1;
end if;
if (b = '1') then muxval <= muxval + 2;
end if;
-- Delay 값이 명시되지 않아, muxval값이 정해지는 시점이 불투명하여 옳지 못한 코드이다.
case muxval is
when 0 => q <= I0 after 10 ns;
when 1 => q <= I1 after 10 ns;
when 2 => q <= I2 after 10 ns;
when 3 => q <= I3 after 10 ns;
when others => null;
end case;
end process;
end wrong;
architecture right of mux4 is
begin
process (I0, I1, I2, I3, a, b)
variable muxval : integer;
begin
muxval := 0;
if(a = '1') then muxval := muxval + 1;
end if;
if(b = '1') then muxval := muxval + 2;
end if;
case muxval is
when 0 => q <= I0 after 10 ns;
when 1 => q <= I1 after 10 ns;
when 2 => q <= I2 after 10 ns;
when 3 => q <= I3 after 10 ns;
when others => null;
end case;
end process;
end right;
Variable
- 내부 변수이다. (process 구문 내에서만 사용할 수 있다.)
- Synthesis시에, wire로 바로 구현되지 않고, 연산의 중간 단계로 활용된다.
- 현재의 값만을 가지며, process문과 subprogram문 내에서만 유효하다.
- Signal에 비해, Variable은 보다 적은 메모리 공간을 차지한다.
* variable의 선언 위치
1) Process Declaration Section
- process문과 begin문 사이에 선언
2) Subprogram Declaration Section
- subprogram의 parameter에서 선언
Example. Process Declaration Section
use work.std_logic_1164.all;
entity and5 is
port ( a, b, c, d, e : in std_logic;
q : out std_logic );
end and5;
architecture and5 of and5 is
begin
process (a, b, c, d, e)
variable state : std_logic;
variable delay : time;
begin
state := a and b and c and d and e;
if state = '1' then
delay := 4.5 ns;
elsif state = '0' then
delay := 3 ns;
else
delay := 4 ns;
end if;
q <= state after delay;
end process;
end and5;
* Variable Assignment
- \(\Delta\)-Delay 없이, 그 즉시 대입된다.
- \(\texttt{:=}\) 연산자를 이용한다.
Constant
- 상수는 코드의 가독성을 제고하고, 코드 수정을 용이하게 한다.
Example. Declaration Constant
constant pi : real := 3.1415;
* constant의 선언 위치
1) Entity Declaration Section
2) Architecture Declaration Section
3) Package Declaration Section
4) Process Declaration Section
5) Subprogram Declaration Section