Sổ tay lập trình VHDL [email protected]
Created by [email protected]
Giới thiệu ngôn ngữ VHDL
3.1. Các cấu trúc cơ bản của ngôn ngữ VHDL.
Các thành phần chính xây dựng trong ngôn ngữ VHDL được chia ra
thành năm nhóm cơ bản như sau:
- Entity
- Architecture
- Package
- Configuration.
{} : Khai báo một hoặc nhiều các đối tượng, mà các đối tượng này có
thể được định nghĩa bởi người dùng.
a. Khai báo Generic dùng để khai báo các hằng mà chúng có thể được
dùng để điều khiển cấu trúc và sự hoạt động của Entity. Cú pháp của khai
báo này như sau:
generic ( constant_name : type [:=init_value]
{;constant_name: type[:=init_value]});
ở đây tên hằng constant_name chỉ ra tên của một hằng dạng generic
(hằng dùng chung).
Kiểu (Type) được dùng để chỉ ra kiểu dữ liệu của hằng.
init_value : chỉ ra giá trị khởi tạo cho hằng.
b. Khai báo cổng ( Port ): Được dùng để khai báo các cổng vào, ra của
Entity. Cú pháp của khai báo này như sau:
Port ( port_name : [mode] type [:= init_value]
{; port_name:[mode] type [:=init_value]});
port_name được dùng để chỉ ra tên của một cổng, mode chỉ ra hướng
vào ra của tín hiệu tại cổng đó. Type chỉ ra kiểu dữ liệu của một cổng và
init_value chỉ ra giá trị khởi tạo cho cổng đó.
Chú ý ! Với VHDL không phân biệt chữ hoa và chữ thường, chẳng hạn
như : xyz = xYz = XYZ.
* Có bốn mode được sử dụng trong khai báo cổng :
- in : chỉ có thể được đọc, nó chỉ được dùng cho các tín hiệu đầu vào (
chỉ được phép nằm bên phải phép gán )
- out : Chỉ được dùng để gán giá trị, nó chỉ được dùng cho các cổng đầu
ra ( Nó chỉ được nằm bên trái của phép gán ).
- inout : Có thể được dùng để đọc và gán giá trị. Nó có thể có nhiều hơn
một hướng điều khiển ( Có thể nằm ở bên trái hoặc bên phải phép gán ).
- Buffer : Có thể được dùng để đọc và gán giá trị. ( Có thể nằm ở bên
trái hoặc bên phải phép gán ).
inout là một cổng hai hướng, còn Buffer là một cổng không có hướng.
Hình trên chỉ ra một giao diện của một bộ cộng một bit. Tên Entity của
phần tử này là FULL_ADDER. Nó bao gồm các cổng đầu vào A, B và CIN.
Các cổng này có kiểu dữ liệu là kiểu Bit, còn các cổng đầu ra SUM và
COUT cũng mang kiểu dữ liệu là kiểu BIT. Ngôn ngữ VHDL dùng để diễn
tả giao diện này như sau:
Entity FULL_ADDER is
port ( A, B, CIN : in BIT;
SUM, COUT : out BIT );
End FULL_ADDER ;
Chúng ta có thể điều khiển cấu trúc cũng như thời gian của một Entity
bởi việc sử dụng các hằng generic. Ví dụ sau sẽ chỉ ra việc điều khiển này,
trong ví dụ này hằng N được dùng để chỉ ra số bít của một bộ cộng. Trong
quá trình mô phỏng hoặc quá trình tổng hợp, giá trị thực tế cho mỗi hằng
dùng chung generic có thể bị thay đổi.
entity ADDER is
generic (N : INTEGER := 4);
M : TIME := 10ns);
port ( A, B : in BIT_VECTOR (N -1 downto 0 );
CIN :in BIT;
SUM : out BIT_VECTOR (N-1 downto 0);
COUT : out BIT );
end ADDER;
Giao diện mô tả bộ cộng này như sau:
CINCOUT
SUM (0)SUM (1)SUM (2)SUM (3)
A (3) B (3) A (2) B (2) A (1) B (1) A (0) B (0)
FULL _ ADDER
3.1.2. Các kiểu kiến trúc ( ARCHITECTURES ):
(A='0' and B='0' and CIN='1') or
(A='0' and B='1' and CIN='0') or
(A='1' and B='0' and CIN='1') then
SUM <= '1';
COUT <= '0' ;
elsif (A='0' and B='1' and CIN='1') or
(A='1' and B='0' and CIN='1') or
(A='1' and B='1' and CIN='0') then
SUM <= '0';
COUT <= '1';
elsif (A='1' and B='1' and CIN='1') then
SUM <='1';
COUT <='1';
end if;
end process;
end BEHAVIOURAL;
3.1.2.2. Kiến trúc theo kiểu hoạt động của các luồng dữ liệu:
Một kiến trúc kiểu luồng dữ liệu chỉ ra một hệ thống dưới dạng mô tả
đồng thời của các luồng điều khiển và dịch chuyển của dữ liệu. Nó sử dụng
theo mẫu thông tin hoặc mẫu hoạt động của luồng dữ liệu đó, hoặc mẫu thời
gian của các chức năng logic tổ hợp. Chẳng hạn như các bộ cộng, bộ so sánh,
bộ giải mã, và các cổng logic nguyên thuỷ.
Ví dụ :
architecture DATAFLOW of FULL_ADDER is
signal S : BIT;
begin
S <= A xor B ;
SUM <= S xor CIN after 10 ns;
COUT <= (A and B ) or (S and CIN) after 5ns;
L2
SUM
CARRY
Bộ cộng này gồm có hai đầu vào L1 và L2 , đầu ra là SUM và CARRY.
Kiểu BIT là kiểu tiền định nghĩa của ngôn ngữ VHDL, nó có kiểu liệt kê
dạng chữ ký tự như '0' và '1'.
3.1.3. Các kiểu đóng gói ( Packages ):
Mục đích chính của Package là tập hợp các phần tử có thể bị chia sẻ bởi
hai hay nhiều đơn vị thiết kế ( Hay các phần tử có thể dùng chung được). Nó
có chứa các kiểu dữ liệu, các hằng, các chương trình con có thể dùng chung
giữa các thiết kế. Một Package có chưa hai phần chính:
- Phần khai báo Package.
- Phần thân Package.
3.1.3.1. Phần khai báo Package.
Một khai báo Package được dùng để cất giữ hàng loạt các khai báo
dùng chung, chẳng hạn như các phần tử, các kiểu, các thủ tục, các hàm. Các
khai báo này có thể nhập vào các đơn vị thiết kế khác bởi việc sử dụng một
mệnh đề use.
Ví dụ :
package EXAMPLE_PACK is
type SUMMER is ( MAY, JUN, JUL, AUG, SEP);
component D_FLIP_FLOP
port (D, CK:in BIT;
Q, QBAR: out BIT)
end component;
constant PIN2PIN_DELAY:TIME:=125ns;
function IN2BIT_VEC(INT_VALUE:INTEGER)
return BIT_VECTOR;
end EXAMPLE_PACK;
package package_name is
{package_declarative_item}
end [package_name ];
package body package_name is
{package_declarative_item}
end [package_name]
Một thân package được dùng để lưu các định nghĩa của một hàm và thủ
tục, mà các hàm và thủ tục này chúng đã được khai báo trong phần khai báo
package tương ứng. Vì vậy phần thân package luôn được kết hợp với phần
khai báo của chúng, hơn nữa một phần khai báo package luôn có ít nhất một
phần thân package kết hợp với chúng.
Ví dụ : package EX_PKG is
subtype INT8 is integer range 0 to 255;
constant zero : INT8:=0;
procedure Incrementer (variable Count : inout INT8);
end EX_PKG;
package body EX_PKG is
procedure Incrementer (variable Data : inout INT8) is
begin
if (Count >= MAX ) then
Count:=ZERO;
else Count:= Count +1;
end if;
end Incrementer;
end EX_PKG;
3.1.4. Định cấu hình ( Configurations ) :
Mỗi một Entity bao gồm nhiều kiến trúc khác nhau. Trong quá trình
thiết kế, người thiết kế có thể muốn thử nghiệm với các sự biến đổi khác
nhau của thiết kế bằng việc chọn lựa các kiểu kiến trúc khác nhau.
- Các kiểu kiến trúc Architectures
- Các phép định cấu hình Configurations.
Chú ý! VHDL không hỗ trợ các thư viện theo thứ bậc. Bạn có
thể có nhiều thư viện như theo ý muốn nhưng không được khai báo
lồng nhau!
Để mở một thư viện và truy cập chúng như một Entity đã được biên
dịch trong một thiết kế VHDL mới, điều đầu tiên cần làm là phải khai báo
tên thư viện. Cú pháp của chúng như sau:
Library library_name : [path/directory_name];
Bạn có thể truy cập các đơn vị đã được biên dịch từ một thư viện VHDL
tới ba mức như sau:
library_name.Package_name.item_name
Ví dụ: Giả sử chúng ta tạo một đóng gói để cất một hằng mà hằng này
được sử dụng trong nhiều thiết kế, sau đó dịch nó và cất vào trong thư viện
với tên là burcin .
Package my_pkg is
constant delay: time:=10ns;
end my_pkg;
Tiếp đến chúng ta gọi my_pkg để sử dụng chúng trong thiết kế dưới
đây:
architecture DATAFLOW of FULL_ADDER is
signal S : BIT;
begin
S <= A xor B;
SUM <= S xor CIN after burcin.my_pkg.delay;
COUT <= (A and B ) or (S and CIN) after 5ns;
end DATAFLOW;
3.2. Các đối tượng dữ liệu :
Một đối tượng dữ liệu giữ một giá trị của một kiểu nhất định. Trong
VHDL có ba lớp đối tượng dữ liệu :
toàn cục ( Các thiết kế có thể sử dụng chúng ), các tín hiệu được khai báo
trong Entity là tín hiệu toàn cục trong một Entity, tương tự với tín hiệu được
khai báo trong một kiến trúc, nó là tín hiệu dùng chung trong một kiến trúc
đó.
Cú pháp của chúng có dạng như sau :
Signal Signal_name {,signal_name}: type [:=value];
Ví dụ :
signal BEEP : BIT:= '0';
signal TEMP: STD_LOGIC_VECTOR (8 downto 0);
signal COUNT: INTEGER range 0 to 100 :=5;
3.3. Các kiểu dữ liệu:
Tất cả các đối tượng dữ liệu trong VHDL cần phải được định nghĩa với
một kiểu dữ liệu. Một khai báo kiểu phải chỉ ra tên và dải của kiểu đó. Khai
báo kiểu dữ liệu chúng được phép khai báo trong phần khai báo các đóng
gói, trong phần khai báo Entity, trong phần khai báo kiến trúc, trong phần
khai báo các chương trình con và trong phần khai báo các Process. Các kiểu
dữ liệu bao gồm các kiểu sau:
- Kiểu liệt kê
- Kiểu nguyên.
- Các kiểu dữ liệu tiền định nghĩa.
- Kiểu mảng.
- Kiểu bản ghi.
- Kiểu dữ liệu chuẩn logic.
- Kiểu dữ liệu có dấu và không dấu.
- Các kiểu phụ.
3.3.1. Các kiểu liệt kê ( ENUMERATION ).
Một kiểu liệt kê được chỉ ra bởi việc liệt kê các giá trị cho phép của
kiểu đó. Tất cả các giá trị được định nghĩa bởi người dùng có thể là các tên
định danh, hoặc các các kiểu chữ ký tự . Tên định danh thực chất là một tên
do người dùng đặt ra, chẳng hạn như blue, ball, monday. Kiểu chữ ký tự là
tính chuẩn . Dưới đây là các kiểu dữ liệu được định nghĩa trong gói
STANDARD:
- BOOLEAN: Một kiểu liệt kê với hai giá trị true và False, các thao tác
Logic và các phép toán quan hệ sẽ trả về giá trị Boolean.
- BIT : Một kiểu liệt kê với hai giá trị '0' và '1' , các phép tính logic có
thể lấy và trả về giá trị kiểu BIT.
- CHARACTER: Kiểu liệt kê của các mã ASCII.
- INTEGER : Được dùng để miêu tả các số âm và dương. Dải hoạt động
của chúng được ấn định từ - 2.147.438.647 đến 2.147.438.647. Các hàm
toán học như cộng, trừ ,nhân, chia được hỗ trợ kiểu nguyên.
- NATURE: Các kiểu con của kiểu nguyên đựơc dùng để miêu tả các số
kiểu tự nhiên ( không âm ).
- POSITIVE: các kiểu con của kiểu nguyên được dùng để miêu tả các số
dương.
- BIT_VECTOR : Được dùng để miêu tả một mảng các giá trị kiểu BIT.
- STRING : Một mảng các ký tự, một giá trị kiểu chuỗi được đi kèm bởi
dấu ngoặc kép.
- REAL: Được dùng để mô tả các kiểu số thực, dải hoạt động từ-
1.0E+38 đến +1.0E+38.
- Kiểu thời gian vật lý : Mô tả các giá trị thời gian được dùng trong mô
phỏng.
Có một vài kiểu dữ liệu được định nghĩa trong gói STANDARD như
sau:
Type BOOLEAN is ( fase, true);
Type BIT is ( '0', '1' );
Type SEVERITY_LEVEL is (note, warning, error, failure );
Type INTEGER is range -2147483648 to 2147483648;
Type REAL is Range -1.0E38 to 1.0E38;
Type CHARACTER is (nul, soh, stx, eot, enq, ack,
bel,............);
constant ROM : MAT : = (( '0', '1', '0', '1'),
('1', '1', '0', '1' ),
('0', '1', '1', '1' ),
('0', '1' , '0', '0' ),
('0', '0' ,'0' , '0'),
('1', '1' , '0', '0' ),
('1', '1' , '1', '1' ),
('1', '1' , '0', '0' );
X := ROM (4,3);
Biến X sẽ lấy giá trị '0' được tô đậm.
3.3.5. Kiểu Record :
Kiểu record là một nhóm có nhiều hơn một phần tử có các kiểu khác
nhau. Phần tử của Record bao gồm các phần tử của bất cứ kiểu nào, nó có
thể là các kiểu mảng hoặc kiểu Record.
Ví dụ :
type DATE_TYPE is ( SUN, MON, TUE , WED , THR , FRI , SAT) ;
type HOLIDAY is
record
YEAR : INTEGER range 1900 to 1999;
MONTH : INTEGER range 1 to 12 ;
DAY : INTEGER range 1 to 31;
DATE : DATE_TYPE;
end record ;
signal S : HOLIDAY;
variable T1: integer range 1900 to 1999;
variable T2 : DATE_TYPE;
T1: = S .YEAR;
T2:= S . DATE;
S . DAY <= 30;
3.3.6. Các kiểu STD_LOGIC :
use IEEE.NUMERIC_BIT.all;
use IEEE.NUMERIC_STD.all;
3.3.8. Các kiểu con .
VHDL cung cấp các các kiểu con mà các kiểu con này chúng được định
nghĩa trong các như các tập phụ trong một kiểu khác. Bất cứ ở đâu có một
khai báo kiểu thì ở đó có thể xuất hiện một định nghĩa kiểu con. Kiểu
NATURAL và kiểu POSITIVE là một kiểu phụ hay kiểu con của kiểu
nguyên và chúng có thể được dùng với bất kỳ một hàm nguyên nào.
Ví dụ :
subtype INT4 is INTEGER range 0 to 15;
subtype BIT_VECTOR6 is BIT_VECTOR (5 downto 0);
3.4. Các toán tử :
VHDL cung cấp 6 lớp toán tử , mỗi một toán tử có một mức ưu tiên
nhất định. Tất cả các toán tử trong cùng một lớp thì có cùng một mức ưu
tiên.
Mức
ưu tiên
thấp
nhất
Các toán tử Các toán hạng
Logical_operator
and
or
nand
Cùng kiểu
Cùng kiểu
Cùng kiểu
.
.
-
Cùng kiểu
Cùng kiểu
arithmetic_operator +
-
Bất kỳ kiểu số nào
Bất kỳ kiểu số nào
arithmetic_operator *
/
mod
rem
Cùng kiểu
Cùng kiểu
integer
integer
Mức
ưu tiên
cao
nhất
arithmetic_operator
Logical_operator
**
abs
not
Kiểu mũ integer
Bất kỳ kiểu số nào
Cùng kiểu
3.4.1. Các toán tử logical .
Trong một biểu thức các toán tử sử dụng các toán hạng để tính toán các
giá trị của chúng. Các toán hạng trong một biểu thức bao gồm :
- Kiểu chữ
- Kiểu định danh
- Các tên được đánh theo chỉ số
- Tên các Slice
- Tên các đặc tính
- Các biểu thức điều kiện
- Các lời gọi hàm