Nội Dung:
1. CÁC CẤU TRÚC CƠ BẢN CỦA NGÔN NGỮ VHDL
2. CÁC ĐỐI TƯỢNG DỮ LIỆU
3. CÁC KIỂU DỮ LIỆU
4. CÁC TOÁN TỬ
5. CÁC KIỂU TOÁN HẠNG
6. CÁC PHÁT BIỂU TUẦN TỰ
7. CÁC PHÁT BIỂU ĐỒNG THỜI
68 trang |
Chia sẻ: tlsuongmuoi | Lượt xem: 5961 | Lượt tải: 1
Bạn đang xem trước 20 trang tài liệu Kiến thức cơ bản về VHDL, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
n hay một tín hiệu, một Entity, một cổng, hay một chương trình con, hay các khai báo tham biến. Khi khai báo một tên cần phải khai báo ký tự đầu tiên phải kiểu chữ ký tự, lưu ý dấu gạch dưới không được phép đứng sau cùng, các từ khoá của VHDL không được dùng để làm khai báo các kiểu định danh, chẳng hạn như entity, port ....
Ví dụ: xyz = xYZ = XYZ = XyZ
S(3) phần tử thứ ba của mảng S
X3.
3.5.3. Kiểu INDEX
Kiểu INDEX được sử dụng để chỉ ra một phần tử nào đó trong một mảng.
Cú pháp sử dụng của khai báo này như sau:
array_name (expression)
Với array_name là một tên của một hằng hay một biến nào đó nằm trong một mảng. Còn expression phải trả về giá trị nằm trong dải chỉ số của mảng đó.
Ví dụ:
type memory is array ( 0 to 7 ) of INTEGER range 0 to 123;
variable DATA_ARRAY : memory;
variable ADDR : INTEGER range 0 to 7;
variable DATA: INTEGER range 0 to 123;
DATA:= DATA_ARRAY ( ADDR );
3.5.4. Kiểu Slice và ALIAS
Một khai báo Slice được dùng để chỉ ra một số phần tử của mảng. Hướng của nó cần phải phù hợp với hướng mảng. Alias được dùng để tạo ra một tên mới cho tất cả các phần tử hoặc một số phần tử nào đó nằm trong một mảng.
Ví dụ:
variable A1: BIT_VECTOR ( 7 downto 0 );
A2: = A1(5 downto 2) ;
Alias A3: BIT_VECTOR (0 to 3) is A1(7 downto 4);
--Có nghĩa là A3(0)=A1(7), A3(1)=A1(6), A3(2)=A1(5), A3(3)= A1(4)
Alias A4: BIT is A1(3);
3.5.5. Kiểu thuộc tính ATTRIBUTE
Lấy các thuộc tính cuả một biến hay một tín hiệu của một kiểu cho trước nào đó và trả về một kiểu giá trị. Dưới đây là các kiểu thuộc tính thường dùng trong ngôn ngữ VHDL:
- Left: Trả về chỉ số của phần tử ở bên trái cùng của một kiểu dữ liệu.
- Right: Trả về chỉ số của phần tử ở bên phải cùng của một kiểu dữ liệu.
- High: Trả về chỉ số của phần tử cao nhất của một kiểu dữ liệu.
- Low: Trả về chỉ số của phần tử thấp nhất của một kiểu dữ liệu.
- Range: Được dùng để lấy về dải của chỉ số.
- Reverse_range: Dùng để xác định dải chỉ số ngược lại.
- Length: Trả về số phần tử của kiểu BIT_VECTOR.
- Event: Mô tả sự thay đổi giá trị của tín hiệu tại thời điểm mô phỏng.
Ví dụ:
variable A1 : BIT_VECTOR ( 10 downto 0 );
A1' left -- Trả về giá trị là 10.
A1' right -- Trả về giá trị 0.
A1' high -- Trả về giá trị là 10.
A1' low -- Trả về giá trị là 0.
A1' range -- Trả về là 10 downto 0.
A1' reverse_range -- Trả về giá trị là 0 to 10.
A1' length -- Trả về giá trị là 11.
3.5.6. Kiểu tập hợp
Kiểu tập hợp có thể được dùng để gán giá trị cho một đối tượng thuộc kiểu mảng hoặc kiểu Record trong khi khởi tạo khai báo hoặc trong các phát biểu gán.
Ví dụ:
type color_list ( red, orange, blue, white );
type color_array is array (color_list) of BIT_VECTOR ( 1 downto 0 );
variable X : color_array;
X := (" 00 " , " 01 " , " 10 " ," 11 " );
X := ( red => "00" , blue => "01" , orange => "10" , white => "11" );
Trong dòng thứ hai, chúng ta định nghĩa một mảng mà số các phần tử của chúng (dải chỉ số) được đưa ra bởi color_list. Từ color_list chúng ta có một mảng gồm bốn phần tử và mảng color_array cũng sẽ bao gồm bốn phần tử, mà mỗi phần tử này lại được định nghĩa bởi kiểu Bit_Vector. Hơn nữa, chúng ta sử dụng dải chỉ số của mảng color_list sẽ có dải từ 0 đến 3, vì việc định nghĩa của mảng này chỉ chỉ ra dải chỉ số chứ không chỉ ra kiểu của phần tử trong mảng.
3.5.7. Biểu thức gán kiểu
Biểu thức gán kiểu được dùng để chỉ ra kiểu của một toán hạng nào đó.
Cú pháp của chúng như sau:
type_name' ( expression );
Ví dụ:
type color1 is (red, orange, blue, white);
type color2 is (purple, green, red, black);
color2'(red);
Như chúng ta thấy toán hạng red có cả trong hai kiểu color1 và color2, vì vậy nó cần phải được gán một kiểu dữ liệu rõ ràng và điều này được thực hiện bởi câu lệnh thứ 3.
3.5.8. Phép chuyển đổi kiểu tín hiệu
Phép chuyển đổi kiểu cho phép chuyển đổi các kiểu có kiểu dữ liệu gần giống nhau.
Ví dụ:
signal X : STD_LOGIC_VECTOR ( 3 downto 0 );
signal Y : STD_ULOGIC_VECTOR ( 3 downto 0 );
Y <= STD_ULOGIC_VECTOR (X);
Sau câu lệnh thứ ba Y sẽ nhận kiểu STD_ULOGIC_VECTOR.
3.6. CÁC PHÁT BIỂU TUẦN TỰ
Phát biểu tuần tự chỉ ra sự thực hiện từng bước của một quá trình. Chúng thực hiện từ câu lệnh đầu tiên, câu lệnh thứ hai, ... câu lệnh cuối cùng. Các phát biểu nằm trong một phát biểu quá trình (phát biểu Process) được gọi là phát biểu tuần tự. Các phát biểu sau đây là các phát biểu tuần tự được định nghĩa trong VHDL:
- Các phát biểu gán biến Variable.
- Các phát biểu gán tín hiệu Signal.
- Các phát biểu If.
- Các phát biểu Case.
- Các phát biểu Null.
- Các phát biểu xác nhận Assertion.
- Các phát biểu vòng lặp Loop.
- Các phát biểu Next.
- Các phát biểu Exit.
- Các phát biểu Wait.
- Các phát biểu Procedure.
- Các phát biểu Return.
3.6.1. Phát biểu gán biến
Dùng để thay thế giá trị hiện thời của biến với một giá trị mới, giá trị mới này được chỉ ra bởi một biểu thức. Biến có thể được khai báo và sử dụng bên trong một phát biểu quá trình hay còn được gọi là phát biểu Process. Một biến được gán một giá trị sử dụng thông qua phát biểu gán biến, mà phát biểu này có hình thức như sau:
target_variable : = expression;
Lưu ý, các biến được khai báo trong một Process không thể chuyển giá trị ra ngoài Process, điều đó có nghĩa là chúng chỉ được cấp phát trong Process hoặc trong chương trình con.
Ví dụ về phép gán biến trong một Process.
process (C,D)
variable Av, Bv, Ev : integer := 0;
begin
Av := 2;
Bv := Av + C;
Ev := Av * 2;
A <= Av;
B <= Bv;
E <= Cv;
end process;
A = 3 A <= 3 Av = 3
B = 3 B <= 3 Bv = 3
C = 1
D = 2
E = 6 E = 6 Ev = 6
Biểu thức được xác định giá trị khi phát biểu được thực thi và giá trị được tính toán sẽ được gán cho biến một cách tức thời. Biến được tạo tại thời điểm sản sinh và duy trì giá trị của nó trong suốt thời gian chạy chương trình. Do vì một quá trình không bao giờ được thoát ra trong mỗi trạng thái hoạt động của nó, nghĩa là chúng được thực thi, hoặc ở trong một trạng thái chờ. Nếu ở trạng thái chờ thì chúng phải chờ cho đến khi một sự kiện khác chắc chắn xảy ra. Một quá trình bắt đầu thực hiện tại điểm khởi đầu của một quá trình mô phỏng, tại thời điểm này nó được thực thi cho đến khi gặp một phát biểu wait hoặc gặp các thành phần được khai báo trong danh mục cần được xử lý khai báo trong Process.
Xem thí dụ về phát biểu Process như sau:
Ví dụ 1:
process(A)
variable EVENT_ON_A : INTEGER : = -1;
begin
EVENT_ON_A : = EVENT_ON_A +1;
end process;
Ví dụ 2:
Subtype INT16 is INTEGER range 0 to 65536;
Signal S1, S2 : INT16;
Signal GT : BOOLEAN;
process (S1, S2)
variable A, B : INT6;
constant C : INT16 : = 100;
Begin
A := S1 +1 ;
B : = S2*2 - C;
GT B;
End Process;
Tại lúc bắt đầu của quá trình mô phỏng. Quá trình được thực thi một lần. Biến EVENT_ON_A được gán giá trị -1 sau đó tăng lên 1. Sau đó, thời điểm bất kỳ xảy ra, sự kiện trên tín hiệu A, quá trình có hiệu lực và phát biểu gán biến đơn được thực thi. Nó làm cho biến EVENT_ON_A tăng lên một. Tại thời điểm kết thúc của quá trình mô phỏng, biến EVENT_ON_A chứa tổng số sự kiện xảy ra trên tín hiệu A.
Một thí dụ khác của phát biểu quá trình :
signal A, Z:INTEGER;
. . .
PZ: process(A); -- PZ là nhãn của quá trình
variable V1,V2 : INTEGER;
begin
V1:=A-V2; -- statement 1
Z<= -V1; -- statement 2
V2:= Z+V1*2; -- statement 3
end process PZ;
Giả sử một sự kiện xảy ra trên tín hiệu A tại thời điểm T1 và biến V2 được gán giá trị là 10, trong phát biểu thứ 3, sau đó một sự kiện xảy ra trên tín hiệu A tại thời điểm T2, giá trị của V2 được sử dụng trong phát biểu 1 sẽ cũng là 10. Một biến cũng có thể được khai báo bên ngoài một quá trình hoặc một chương trình con. Một biến có thể được đọc và cập nhật bởi một hoặc có thể nhiều quá trình, những biến này được gọi là shared variable (biến chia sẻ).
3.6.2. Phát biểu gán tín hiệu
Phát biểu gán tín hiệu sẽ thay thế giá trị hiện tại của tín hiệu với một giá trị mới bởi việc sử dụng một biểu thức. Tín hiệu và kết quả của biểu thức cần có cùng một kiểu dữ liệu.
Cú pháp của chúng như sau:
target_signal <= [ Transport] expression [after time_expression]
Phát biểu gán tín hiệu có thể xuất hiện bên trong hoặc bên ngoài một quá trình. Nếu nó xảy ra bên ngoài của một quá trình, nó được xem là một phát biểu gán tín hiệu đồng thời. Khi phát biểu gán tín hiệu xuất hiện bên trong quá trình, nó được xem như là một phát biểu gán tín hiệu có thứ tự và nó được thực thi tuần tự theo thứ tự của những phát biểu tuần tự khác xuất hiện bên trong quá trình.
Ví dụ phép gán tín hiệu trong một Process (Với A,B,C,D là các tín hiệu):
process (C,D)
variable Av, Bv, Ev : integer :=0;
begin
Av := 2;
Bv := Av + C;
Av := D + 1;
Ev := Av * 2;
A <= Av;
B <= Bv;
C <= Cv;
end process;
A = 3 A <= 3 Av = 3
B = 3 B <= 3 Bv = 3
C = 1
D = 2
E = 6 E <= 6 Ev = 6
Khi một phát biểu gán tín hiệu được thực thi, giá trị của biểu thức được tính toán và giá trị này được chuẩn bị để gán cho tín hiệu sau khi delay. Lưu ý rằng biểu thức được định lượng tại thời điểm phát biểu và không thực thi ngay mà nó sẽ thực thi sau một thời gian giữ chậm. Có hai kiểu Delay được cung cấp để chuẩn bị cho việc thực thi tín hiệu:
- Transport Delay.
- Inertial Delay.
a. Transport Delay.
Nó tương tự như sự giữ chậm bên trong của một dòng điện chạy qua dây dẫn. Nếu thời gian giữ chậm này được xem như tiêu tốn vào thực hiện công việc nào đó và tiếp sau nó (đúng thời điểm của một công việc trước hoàn thành) cần phải thực hiện một công việc khác thì thời gian thực hiện các công việc tiếp theo sẽ được thêm vào cuối của công việc trước đó. Còn nếu khoảng thời gian cần thực hiện một công việc tiền định (thời gian thực hiện của một công việc tiếp theo nào đó đứng trước thời điểm thực hiện một công việc trước) thì câu lệnh Transport sẽ thực hiện chèn vào và thực hiện công việc tiền định này.
Xem ví dụ sau: Giả sử ta có một process và biểu đồ như sau:
Hình 3.4: Biểu đồ thời gian Transport Delay
Ví dụ:
..........
process (.....)
Begin
S <= transport 1 after 1 ns, 3 after 3 ns, 5 after 5 ns;
S <= transport 4 after 4 ns;
end process;
Như ví dụ và biểu đồ trên ta thấy công việc thứ tư cần thực hiện trước công việc thứ 5, nhưng trong phần chương trình thì phát biểu của công việc thứ 5 lại được thực hiện trước công việc thứ tư. Hình vẽ dưới đây mô tả phát biểu Transport, sau 3s đèn sẽ được bật sáng và sáng trong khoảng thời gian đúng bằng thời gian bật công tắc.
Hình 3.5: Mô tả Transport Delay.
b. Inertial Delay
Inertial Delay (giữ chậm do quán tính), là giá trị mặc định của VHDL. Nó được dùng cho các thiết bị mà không có phản ứng cho đến khi đầu vào được phép trong một khoảng thời gian nhất định. Thường thì với tín hiệu có khoảng thời gian tác động không đều và nhỏ hơn thời gian giữ chậm của các cổng thì sẽ bị bỏ qua.
Với ví dụ trên, mô tả hoạt động của đèn với độ giữ chậm do sức ì quán tính của mạch. Nếu thời gian tác động của công tắc nhỏ hơn độ giữ chậm của mạch thì đầu ra sẽ không có tác động hay đèn sẽ không được bật sáng. Giả sử ta có câu lệnh đèn sẽ được bật sáng sau 3 giây, nhưng công tắc chỉ tác động trong thời gian hai giây thì đèn sẽ không được bật sáng. Xem hình vẽ 3.6 dưới đây:
Hình 3.6: Mô tả Inertial Delay (thời gian bật công tắc là 2s).
Giả sử ta có câu lệnh bật đèn sau 3s. Khi bật công tắc trong thời gian 4s sau đó tắt công tắc, thì đèn sẽ được sáng sau khi công tắc bật được 3s và sáng trong 4s đúng bằng thời gian bật công tắc.
Xem hình 3.7 dưới đây:
Hình 3.7: Mô tả Inertial Delay (thời gian bật công tắc là 4s).
c. So sánh Transport Delay và Inertial Delay
Hình 3.8: So sánh Transport Delay và Inertial Delay.
Như trên hình 3.8 ta thấy trong trường hợp Inertial Delay, tín hiệu A có tác động trong khoảng 10ns, nhưng câu lệnh thực hiện đầu ra S sau 20ns, vì vậy đầu ra S sẽ không có tác động. Còn trong trường hợp Transport Delay tín hiệu đầu ra sẽ được sao y tín hiệu đầu vào sau khi bắt đầu sườn lên của tín hiệu vào có tác động (đúng bằng khoảng 20 ns của câu lệnh).
3.6.3. Phát biểu IF
Một phát biểu if được dùng để chọn lựa những phát biểu tuần tự cho việc thực thi dựa trên giá trị của biểu thức điều kiện. Biểu thức điều kiện ở đây có thể là một biểu thức bất kỳ mà giá trị của chúng phải là kiểu luận lý.
Dạng thông thường của phát biểu if là:
if boolean-expression then
sequential-statements
{elsif boolean-expression then
sequential -statement }
{else
sequential-statement}
end if;
Ví dụ 1:
if sum <=100 then --“<=” is less-than-or-equal-to operator.
SUM:=SUM+10;
end if;
Ví dụ 2:
signal IN1, IN2, OU : STD_LOGIC;
process (IN1, IN2)
begin
if IN1 = '0' or IN2 = '0' then
OU <= '0' ;
elsif IN1 = 'X' or IN2 = 'X' then
OU <= '1';
else
OU <= '1' ;
end if;
end process;
Ví dụ 3:
D_FF : process (D, CLK)
begin
if rising_edge (CLK) then Q <= D;
end if;
end process D_FF;
Hình 3.9: Thực thể D_FF.
3.6.4. Phát biểu CASE
Dạng của phát biểu case là:
case expression is
when choices => sequential -statement -- branch 1
when choices => sequential -statement -- branch 2
-- -- Có thể có nhiều nhánh
{when others => sequential-statement} -- last branch
end case;
Phát biểu case lựa chọn một trong những nhánh cho việc thực thi dựa trên giá trị của biểu thức. Giá trị biểu thức phải thuộc kiểu rời rạc hoặc kiểu mảng một chiều. Các chọn lựa (Choices) có thể được diễn tả như một giá trị đơn, hoặc một dải giá trị bằng việc sử dụng dấu " | " hoặc sử dụng mệnh đề khác. Tất cả các giá trị có thể có của biểu thức phải được thể hiện trong phát biểu case đúng một lần. Các mệnh đề khác có thể được sử dụng để bao quát tất cả các giá trị, và nếu có, phải là nhánh cuối cùng trong phát biểu case. Mỗi một chọn lựa phải có cùng kiểu với kiểu của biểu thức. Một thí dụ cho phát biểu case:
Ví dụ 1:
type WEEK_DAY is (MON, TUE, WED, THU, FRI, SAT, SUN);
type DOLLARS is range 0 to 10;
variable DAY: WEEK_DAY;
variable POCKET_MONEY: DOLLARS;
case DAY is
when TUE => POCKET_MONEY :=6; -- branch1
when MON | WED => POCKET_MONEY :=2; -- branch2
when FRI to SUN => POCKET_MONEY :=7; -- branch3
when others => POCKET_MONEY :=0; -- branch4
end case;
Nhánh 2 được chọn nếu DAY có giá trị là MON hoặc WED. Nhánh 3 bao gồm các giá trị FRI, SAT và SUN. Trong khi nhánh 4 gồm các giá trị còn lại là THU. Phát biểu case cũng là phát biểu tuần tự, tuy nhiên nó cũng có thể được phát biểu xếp lồng nhau.
Ví dụ 2:
ProgrGate: process (Mode, PrGIn1, PrGIn2)
begin
case Mode is
when “000” => PrGOut <= PrGIn1 and PrGIn2;
when “001” => PrGOut <= PrGIn1 or PrGIn2;
when “010” => PrGOut <= PrGIn1 nand PrGIn2;
when “011” => PrGOut <= PrGIn1 nor PrGIn2;
when “100” => PrGOut <= not PrGIn1;
when “101” => PrGOut <= not PrGIn2;
when others => PrGOut <= ‘0’;
end case;
end process ProgrGate;
Hình 3.10: Thực thể Programmable Gate.
3.6.5. Phát biểu NULL
Phát biểu null
Là một phát biểu tuần tự không gây ra bất kỳ hành động nào. Hệ thống sẽ bỏ qua phát biểu NULL và tiếp tục thực thi với phát biểu kế tiếp. Một thí dụ cho việc sử dụng phát biểu này là trong phát biểu if hoặc trong phát biểu case.
Ví dụ:
Variable A, B : INTEGER range 0 to 31 ;
Case A is
when 0 to 12 => B:= A;
when others => Null;
End Case;
3.6.6. Phát xác nhận ASSERTION
Phát biểu xác nhận rất hay dùng cho việc kiểm tra thời gian và các điều kiện ngoài dải.
Ví dụ:
assert (X >3 )
report " Setup violation"
severity warning;
3.6.7. Phát biểu Loop
Một phát biểu lặp được sử dụng để lặp lại một loạt các câu lệnh tuần tự.
Cú pháp của phát biểu lặp là:
[loop-label:] iteration-scheme loop
sequential-statements
end loop [loop-lebel];
Có 3 kiểu sơ đồ lặp. Đầu tiên là sơ đồ lặp có dạng:
for identifier in range
Ví dụ 1: Ví dụ về For ...Loop
FACTORAL:=1;
for NUMBER in 2 to N loop
FACTORAL :=FACTORAL*NUMBER;
end loop;
Trong thí dụ này, thân của vòng lặp thực thi N-1 lần, với định danh lặp là NUMBER và tăng lên 1 sau mỗi vòng lặp. Đối tượng NUMBER được khai báo ẩn trong vòng lặp tùy thuộc vào kiểu integer, nó có giá trị từ 2 đến N. Vì vậy khai báo không rõ ràng cho định danh vòng lặp là điều cần thiết, định danh vòng lặp cũng không thể được gán cho bất kỳ giá trị nào trong vòng lặp for. Nếu một biến khác có cùng tên được tạo bên ngoài vòng lặp for, đó là hai loại biến được giải quyết riêng rẽ và biến sử dụng trong vòng lặp for sẽ chuyển giao cho định danh vòng lặp. Vùng của vòng lặp FOR cũng có thể là vùng của một kiểu liệt kê.
Ví dụ 2:
type HEXA is (‘0’,’1’,’2’,’3’,’A’,’B’,’C ’); . . . .
for NUM in HEXA’(‘2’) downto HEXA’(‘0’) loop
-- Num sẽ lấy những giá trị trong kiểu HEXA từ 2 cho đến 0.
end loop;
Ví dụ 3: Ví dụ về While .... loop
process
variable Count : integer := 0;
begin
wait until Clk = ‘1’;
while Level = ‘1’ loop
Count := Count +1;
wait until Clk = ‘0’;
end loop;
end process;
3.6.8. Phát biểu NEXT
Phát biểu next cũng là phát biểu liên tục cũng chỉ có thể sử dụng bên trong vòng lặp. Cú pháp tương tự như phát biểu exit:
next [loop-label][when condition];
Kết quả của phát biểu next sẽ bỏ qua những phát biểu còn lại trong lần lặp hiện tại của vòng lặp và tiếp tục thực thi với phát biểu đầu tiên trong vòng lặp kế tiếp. Nếu tồn tại một lần và nếu nhãn vòng lặp không rõ ràng thì sẽ xảy ra hiện tượng lặp đến vô cùng. Đối lập với phát biểu exit, nó là nguyên nhân của vòng lặp bị giới hạn.
Ví dụ 1:
for j in 10 downto 5 loop
if SUM < TOTAL_SUM then
SUM:=SUM +2;
elsif SUM = TOTAL_SUM then
next;
else
null;
end if;
K:=K+1;
end loop;
Khi phát biểu next được thực thi, quá trình thực hiện sẽ nhảy đến phần cuối của vòng lặp (phát biểu cuối cùng K := K+1) sau đó giảm giá trị của định danh vòng lặp j, và thực hiện lại từ đầu.
Ví dụ 2:
signal DataBus : bit_vector(3 downto 0);
signal Ones : integer;
CountOnes: process (DataBus)
variable NumOfOnes : integer := 0;
begin
for Cntr in 3 downto 0 loop
next when DataBus(Cntr) = ‘0’;
NumOfOnes := NumOfOnes + 1;
end loop;
Ones <= NumOfOnes;
end process CountOnes;
3.6.9. Phát biểu EXIT
Phát biểu exit là một phát biểu tuần tự nó chỉ có thể sử dụng bên trong vòng lặp. Nó có thể làm cho quá trình thực hiện nhảy đến vòng lặp trong cùng hoặc ra khỏi vòng đến vị trí của nhãn xác định nào đó khi nó gặp nhãn này trong vòng lặp.
Cú pháp của một phát biểu exit là:
exit [loop-label][when condition]
Nếu nhãn vòng lặp không được chỉ ra thì quá trình thực hiện sẽ lặp đến vòng lặp trong cùng. Nếu mệnh đề WHEN được sử dụng thì việc tồn tại vòng lặp chỉ xảy ra nếu điều kiện là đúng. Ngược lại, việc thực hiện sẽ tiếp tục với phát biểu kế tiếp.
Ví dụ:
SUM :=1; J:=0 ;
L3:loop
J:=J+21;
SUM:=SUM*10
if (SUM >100) then
exit L3; -- Thực hiện exit khỏi L3 nếu Sum> 100
enf if;
end loop L3;
3.6.10. Phát biểu WAIT
Như chúng ta đã thấy, một quá trình mô phỏng có thể trì hoãn (hay treo sự thực hiện của một phát biểu Process hoặc một chương trình con ) cho đến khi gặp một điều kiện phù hợp. Có 3 hình thức cơ bản của phát biểu wait.
wait on sensitivity-list;
wait until boolean -expression;
wait for time-expression;
Ví dụ 1:
wait on A,B ;
wait until A = B;
wait for 10 ns;
wait on CLOCK for 20 ns ;
wait until SUM >100 for 50 ms;
Sự hiện diện của sensitivity list trong một quá trình trùng với trường hợp một trong ba trường hợp trên của phát biểu “wait”. Một phát biểu quá trình có wait on ở cuối của Process tương đương với một phát biểu quá trình có khai báo sensitivity-list.
Xem hình dưới đây: Hai process này là tương đương nhau.
process
begin
somestatements1;
somestatements2;
somestatements3;
wait on SomeSign;
end process;
-------------------
process (SomeSign)
begin
somestatements1;
somestatements2;
somestatements3;
end process;
Ví dụ 2:
process -- Không sensitivity list
variable TEMP1, TEMP2:BIT;
begin
TEMP1:=A and B;
TEMP2:=C and D;
TEMP1:=TEMP1 or TEMP2;
Z<=not TEMP1;
wait on A, B, C, D; -- Thay thế cho sensitivity-list ở đầu Process .
End process.
Ví dụ 3: Hai Process trong ví dụ dưới đây chỉ ra hai process có phát biểu Wait on. Process bên trái sẽ làm cho Process treo ngay sau khi Start và chờ cho đến khi có sự kiện xuất hiện trên tín hiệu SigA. Còn Process bên phải sẽ thực hiện ba câu lệnh và sau đó rơi vào trạng thái chờ đến khi xuất hiện sự kiện trên tín hiệu SigB.
process
begin
wait on SigA;
somestatements1;
somestatements2;
somestatements3;
end process;
--------------------------
process
begin
somestatements1;
somestatements2;
somestatements3;
wait on SigB;
end process;
3.6.11. Các lời gọi chương trình con
Khi mô tả thiết kế theo kiểu hoạt động hành vi, các chương trình con thường hay được sử dụng và đưa ra cách thức sử dụng thuận tiện. Có hai loại chương trình con hay được sử dụng là Hàm và Thủ tục.
- Thủ tục ( Procedure) trả về nhiều giá trị.
- Hàm ( Function ) trả về một giá trị đơn.
Các lời gọi thủ tục sẽ gọi thủ tục mà nó cần được thực hiện trong một quá trình. Phát biểu trả về ( return ) sẽ là điểm kết thúc một chương trình con, và nó chỉ được sử dụng trong một hàm hoặc một thủ tục. Đối với hàm thì nó có qui định với phát biểu trả về trong thân hàm, nhưng với thủ tục thì có thể sử dụng tuỳ ý trong thân thủ tục. Cú pháp của phát biểu trả về như sau:
return [expression];
Ở đây expression sẽ đưa ra các giá trị trả về của hàm, phát biểu return trong một hàm cần phải có một biểu thức và giá trị trả về của nó, nhưng đối với phát biểu trả về trong thủ tục thì không cần phải có mặt của biểu thức. Một hàm có thể có nhiều hơn một phát biểu trả về, nhưng chỉ có một phát biểu trả về được sử dụng bởi một lời gọi hàm.
3.7. CÁC PHÁT BIỂU ĐỒNG THỜI
Các phát biểu đồng thời được thực hiện song song trong cùng thời điểm mô phỏng, chúng không thực hiện theo thứ tự mà chúng được viết ra trong một kiến trúc. Các phát biểu đồng thời chuyển thông tin thông qua các đường tín hiệu.
Dưới đây là các phát biểu đồng thời được định nghĩa trong VHDL:
- Các phát biểu gán của một quá trình (Process).
- Các phát biểu gán tín hiệu đồng thời .
- Các phát biểu gán tín hiệu điều kiện.
- Các phát biểu gán tín hiệu đợc chọn lựa.
- Các phát biểu Block.
- Các lời gọi thủ tục đồng thời.
- Các phát biểu xác nhận đồng thời.
3.7.1. Phát biểu Process
Phát biểu process là phát biểu bao gồm một tập các phát biểu tuần tự và phát biểu process lại chính là phát biểu đồng thời. Có nghĩa là tất cả các phát biểu Process trong một thiết kế được thực hiện một cách đồng thời. Tuy nhiên tại một thời điểm nhất định được đưa ra chỉ có một phát biểu tuần tự được thực hiện trong mỗi process. Một Process được kết nối với phần còn lại của thiết kế bởi việc đọc hoặc viết ra các giá trị từ các tín hiệu và các cổng mà chúng đã được khai báo phía ngoài Process. Cú pháp của chúng được viết như sau:
[label:] process [(sensitivity_list)]
{process_declaration_part}
begin
{sequential_statements}
end process [label];
Phần khai báo của một process chỉ ra các đối tượng mà vùng hoạt động của nó chỉ thuộc vùng của một process và chúng có thể là các đối tượng sau đây:
- Khai báo biến .
- Khai báo hằng .
- Khai báo các kiểu.
- Khai báo các kiểu con.
- Khai báo các bí danh Alias.
- Các mệnh đề USE.
Một sensitivity list (tập các sự kiện thay đổi trạng thái cần xử lý trong một quá trình) có cùng ý nghĩa với một Process có chứa phát biểu wait, mà phát biểu wait này là phát biểu cuối cùng trong một process và chúng có dạng sau:
Wait on sensitivity list ;
Một process có chức năng giống như một vòng lặp vô hạn mà trong nó có chứa toàn bộ các phát biểu tuần tự được chỉ ra trong vòng lặp đó. Vì vậy một phát biểu process cần phải có hoặc một sensitivity list hoặc một phát biểu wait on hoặc cả hai.
Ví dụ 1:
architecture A2 of example is
signal i1, i2, i3, i4, and_out, or_out : bit;
begin
pr1 : process (i1, i2, i3, i4)
begin
and_out <= i1 and i2 and i3 and i4;
end process pr1;
pr2 : process (i1, i2, i3, i4)
begin
or_out <= i1 or i2 or i3 or i4 ;
end process pr2;
end A2
Ví dụ 2:
name: process (sensitivity list)
declarations
begin
sequential statements;
end process name;
---------------------
MUX2TO1: process (A,B,SEL)
constant High : Bit := ‘1’;
begin
Y <= A;
if (SEL= ‘1’) then Y <= B;
end if;
end process MUX2TO1;
3.7.2. Các phép gán tín hiệu đồng thời
Một dạng khác của việc gán tín hiệu đồng thời đó là các phép gán tín hiệu đồng thời, các phép gán này được dùng ở bên ngoài của một process nhưng phải nằm trong một kiến trúc (architecture). Cú pháp của phép gán này như sau:
target_signal <= expression [after time_expression ];
Tương tự như các phép gán tín hiệu tuần tự, mệnh đề after sẽ bị bỏ qua bởi bộ tổng hợp. Với bất kỳ một tín hiệu nào nằm bên phải của một phép gán đều mang ý nghĩa tương tự như một phần tử trong sensitivity list .
Một thân architecture có thể chứa số lượng bất kỳ của những phát biểu gán tín hiệu đồng thời. Vì chúng là những phát biểu đồng thời nên thứ tự của những phát biểu là không quan trọng. Những phát biểu gán tín hiệu đồng thời được thực thi bất cứ khi nào có sự kiện xảy ra trong tín hiệu được sử dụng trong biểu thức.
Ví dụ1 :
architecture A1 of example is
signal i1, i2, i3, i4, and_out, or_out : bit;
begin
and_out <= i1 and i2 and i3 and i4;
or_out <= i1 or i2 or i3 or i4;
end A1;
Ví dụ 2:
architecture A2 of example is
signal i1, i2, i3, i4, and_out, or_out : bit;
begin
process (i1, i2, i3, i4)
begin
and_out <= i1 and i2 and i3 and i4;
end process ;
process (i1, i2, i3, i4)
begin
or_out <= i1 or i2 or i3 or i4 ;
end process ;
end A2;
Ví dụ 3:
architecture A3 of example is
signal i1, i2, i3, i4, and_out, or_out : bit;
begin
process
begin
and_out <= i1 and i2 and i3 and i4;
or_out <= i1 or i2 or i3 or i4;
wait on i1, i2, i3, i4;
end A3;
Ba ví dụ trên đây là tương đương nhau.
3.7.3. Các phép gán tín hiệu có điều kiện và các phép gán tín hiệu được chọn lựa
a. Các phép gán tín hiệu có điều kiện.
Một phép gán tín hiệu có điều kiện chính là một phát biểu đồng thời và có một đích gán nhất định, tuy nhiên phép gán này có thể có nhiều hơn một biểu thức cho một đích. Ngoại trừ biểu thức cuối cùng, các biểu thức còn lại phải có một điều kiện chắc chắn, các điều kiện này được đánh giá theo thứ tự. Nếu một điều kiện được đánh giá là TRUE thì biểu thức tương ứng được sử dụng, ngược lại các biểu thức còn lại sẽ được sử dụng. Nhớ rằng chỉ một biểu thức được sử dụng tại một thời điểm. Cú pháp của câu lệnh này như sau:
target <= {expression [ after time_expression ] when condition else}
expression [ after time_expression ];
Một phát biểu gán tín hiệu có điều kiện có thể được mô tả bởi một phát biểu process mà process có chứa phát biểu IF. Bạn có thể sử dụng phát biểu gán tín hiệu có điều kiện ở trong một process .
Ví dụ 1:
architecture A1 of example is
signal a, b, c ,d : integer ;
begin
a 10 ) else
c when ( d >5 ) else
d;
end A1;
Ví dụ 2:
architecture A2 of example is
signal a, b, c ,d : integer ;
begin
process (b, c, d)
begin
if ( d > 10) then a <= b
elsif ( d >5 ) then a <= c;
else a <= d;
end if;
end process;
end A2;
Ví dụ 3: Sử dụng các phát biểu có điều kiện.
ExProc: process (sensitivityList)
begin
if Cond1
then
….
case Cond2 is
when Val1 => …
when Val2 => …
when others => for I in 1 to 4 loop
….
end loop;
end case;
else
while Cond3 loop
….
end loop
….
end if;
…
end process ExProc;
b. Các phép gán tín hiệu có chọn lựa.
Phép gán tín hiệu có chọn lựa có thể chỉ một đích gán và cũng chỉ có một biểu thức with. Giá trị này được kiểm tra giống như phát biểu Case thông thờng. Nó sẽ quản lý bất cứ sự thay đổi nào xuất hiện tới các tín hiệu được chọn lựa. Cú pháp của chúng như sau:
with choice_expression select
target <= {expression [after time_expression] when choices}
expression [ after time_expression] when choices;
Bất kỳ phép gán tín hiệu có chọn lựa nào đều có thể được mô tả tương đương bởi phát biểu process có chứa phát biểu case. Bạn không được sử dụng phát biểu gán tín có chọn lựa ở trong một process .
Ví dụ 1:
with SEL select
Z <= a when 0 | 1 | 2,
b when 3 to 10,
c when others;
Ví dụ 2:
process ( SEL, a, b, c )
case SEL is
when 0 | 1 | 2| => Z <= a;
when 3 to 10 => Z <= b;
when others => Z <= c;
end case;
end process ;
Hai ví dụ trên đây là hoàn toàn tương đương nhau.
3.7.4. Các phát biểu Block
Các block cho phép người thiết kế nhóm các phần theo trật tự logic của các mẫu đồng thời, với điều kiện là các phần này không nằm trong lược đồ sử dụng của các mẫu khác (các mẫu mà chúng được sử dụng để thay thế các thành phần khác trong một thiết kế). Các block được sử dụng để tổ chức các phát biểu gán đồng thời theo thứ bậc. Cú pháp của chúng như sau:
label : Block
{block_declarative_part}
begin
{concurrent_statement}
end block [label];
Phần khai báo block chỉ ra các đối tượng thuộc miền cục bộ của block và có thể là các thành phần sau đây:
- Khai báo tín hiệu.
- Khai báo hằng.
- Khai báo kiểu.
- Khai báo các kiểu con.
- Thân các chương trình con
- Khai báo bí danh ALIAS
- Các mệnh đề use
- Khai báo các thành phần ( Component).
Các đối tượng được khai báo trong một block chỉ được phép hoạt động trong block đó và các block vòng trong của nó. Khi một block con khai báo một đối tượng có trùng tên với đối tượng trong block cha thì khai báo của block con sẽ định nghĩa lại đối tượng trùng tên với block cha.
Ví dụ:
architecture BHV of example is
signal : out 1 : integer;
signal : out 2 : bit;
begin
B1 : block
signal S : bit;
begin
B1-1 : block
signal S : integer;
begin
out 1 <= S ;
end block B1-1;
end block B1;
B2: block
begin
out 2 <= S ;
end block B2;
end BHV;
Trong ví dụ này ta thấy block B1-1 là block con của block B1. Cả B1 và B1-1 đều khai báo tín hiệu S. Tín hiệu S trong B1-1 sẽ là kiểu integer và truyền cho tín hiệu out 1 cũng là kiểu integer, mặc dù S được khai báo trong B1 là kiểu Bit. Tín hiệu S trong B1 được sử dụng trong B2 là kiểu Bit, trùng với kiểu tín hiệu out 2.
3.7.5. Các lời gọi thủ tục đồng thời
Một lời gọi thủ tục đồng thời chính là một lời gọi thủ tục mà nó được thực thi ở bên ngoài một process, nó đứng độc lập trong một kiến trúc architecture. Lời gọi thủ tục đồng thời bao gồm:
- Có các tham số IN, OUT, INOUT.
- Có thể có nhiều hơn một giá trị trả về
- Nó được xem như một phát biểu.
- Nó tương đương với một process có chứa một lời gọi thủ tục đơn.
Hai ví dụ dưới đây là tương đương nhau.
Ví dụ 1:
architecture .................
begin
procedure_any (a,b) ;
end..........;
Ví dụ 2:
architecture ................
begin
process
begin
procedure_ any (a,b);
wait on a,b;
end process ;
end .............;
3.7.6. Các chương trình con
Các chương trình con bao gồm các thủ tục và các hàm mà nó có thể được gọi để thực hiện công việc nào đó lặp lại từ các vị trí gọi khác nhau trong VHDL. Trong VHDL cung cấp hai kiểu chương trình con khác nhau là:
- Các thủ tục (Procedure).
- Các hàm ( Function ).
a. Hàm và các đặc trưng của hàm.
- Chúng được gọi và thực hiện như một biểu thức.
- Luôn trả về một đối số.
- Tất cả các tham số của hàm đều phải là chế độ mode IN.
- Tất cả các tham số của hàm phải thuộc lớp các tín hiệu hoặc các hằng.
- Bắt buộc phải khai báo kiểu của giá trị trả về.
- Không được chứa các phát biểu Wait.
Cú pháp của hàm được khai báo như sau:
function identifier interface_list return type_mark is
{subprogram_declarative_item}
Begin
{sequential_statement}
end [identifier];
Các định danh identifier chỉ ra tên của một hàm, còn interface_list chỉ ra định dạng tham số của một hàm.
Mỗi một tham số được định nghĩa theo cú pháp sau:
[class] name_list [mode] type_name [:=expression];
ở đây class của tham số đối tượng phải được chỉ ra là tín hiệu hoặc hằng, còn mode của đối tượng cần phải là mode in. Nếu không có tham số mode được chỉ ra thì được hiểu như là mode IN, còn nếu không có tham số class được chỉ ra thì tham số được hiểu như là một hằng.
Xem ví dụ sau:
process
function c_to_f ( c : real ) return real is
variable f : real;
begin
f := c*9.0/5.0 + 32.0;
return (f);
end c_to_f;
variable temp : real;
begin
temp : = c_to_f (5.0) + 20.0; -- temp = 61
end process;
Tham số chuyển vào hàm được hiểu mặc định là một hằng số, vì không có khai báo của class.
b. Thủ tục và các đặc trưng của chúng.
- Chúng được gọi như một lời phát biểu.
- Có thể trả về không hoặc một hoặc nhiều đối số.
- Các tham số chuyển giao cho thủ tục có thể là mode in, out, và inout.
- Các tham số chuyển giao cho thủ tục có thể là tín hiệu, hằng, biến.
- Có thể có chứa phát biểu Wait.
Cú pháp khai báo thủ tục như sau:
procedure identifier interface_list is
{subprogram_declarative_item}
begin
{sequential_statement}
end [identifier];
Identifier được sử dụng để chỉ ra tên của procedure và interface_list chỉ ra các tham số hình thức của procedure. Mỗi tham số được sử dụng theo định nghĩa sau:
[class] name_list [mode] type_name [:=expression];
Class của đối tượng được xem như hằng, biến , hoặc là tín hiệu và mode của đối tượng có thể là in, out , inout. Nếu không có mode được chỉ ra thì tham số được hiểu như mode in, nếu không có class được chỉ ra thì các tham số mode in được hiểu như là các hằng, còn tham số mode out và inout được hiểu như là các biến.
Các tham số có thể là các hằng, các biến, hoặc các tín hiệu và mode của chúng có thể là in, out, hoặc inout. Nếu lớp của các tham số không xác định rõ ràng thì mặc nhiên nó là constant, nếu nó là mode in, còn nó là biến nếu mode của tham số đó là out hoặc inout.
Một ví dụ thân procedure mô tả hành vi hoạt động của các đơn vị logic số học như sau:
type OP_CODE is ( ADD, SUB, MUL, DIV, LT, LE, EQ);
…
procedure ARITH_UNIT ( A, B : in INTEGER ;
OP : in OP_CODE ;
Z : out INTEGER;
ZCOMP : out BOOLEAN ) is
begin
case OP is
when ADD => Z := A+B;
when SUB => Z := A-B;
when MUL => Z := A*B;
when DIV => Z := A/B;
when LT => ZCOMP := A<B;
when LE => ZCOMP := A<=B;
when EQ => ZCOMP := A=B;
end case ;
end ARITH_UNIT;
Ta xem một ví dụ khác của thân một procedure, procedure này quay véc tơ đã được xác định với tên là ARRAY_NAME, bắt đầu từ bit START_BIT tới bit STOP_BIT, bởi một giá trị ROTATE_BY. Lớp đối tượng của tham số ARRAY_NAME được xác định một cách tường minh. Biến FILL_VALUE tự động được khởi tạo về ‘0’ mỗi khi procedure được gọi.
Procedure ROTATE_LEFT
(signal ARRAY_NAME : inout Bit_vector ;
START_BIT, STOP_BIT : in NATUAL;
ROTATE_BY : in POSITIVE ) is
Variable FILL_VALUE : BIT;
begin
assert STOP_BIT > START_BIT
report “STOP_BIT is not greater than START_BIT”
severity NOTE;
for MACVAR3 in 1 to ROTATE_BY loop
FILL_VALUE := ARRAY_NAME (STOP_BIT);
for MACVAR1 in STOP_BIT downto (START_BIT + 1) loop
ARRAY_NAME (MACVAR1) <= ARRAY_NAME (MACVAR1 –1);
end loop;
ARRAY_NAME (START_BIT) <= FILL_VALUE ;
end loop;
end procedure ROTATE_LEFT;
Các procedure được gọi bởi lời gọi procedure. Một lời gọi Procedure có thể là một phát biểu tuần tự hoặc một phát biểu đồng thời, phát biểu này phụ thuộc vào nơi xuất hiện lời gọi thủ tục hiện tại. Nếu lời gọi này nằm bên trong một phát biểu process hoặc một chương trình con khác thì nó được gọi là phát biểu gọi procedure tuần tự, ngược lại nó được gọi là phát biểu gọi procedure gọi đồng thời.
Cú pháp của phát biểu gọi procedure như sau :
[ label : ] procedure_name ( list_of_actual );
Thực tế các biểu thức, các biến, các tín hiệu hoặc các file, được chuyển vào trong thủ tục và các tên của đối tượng và các tên này sẽ được dùng để lấy các giá trị tính toán từ trong thủ tục. Chúng được chỉ ra một cách rõ ràng bởi việc sử dụng sự kết hợp theo tên và kết hợp theo vị trí .
Ví dụ:
ARITH_UNIT (D1, D2, ADD, SUM, COMP ); -- Sự kết hợp theo vị trí.
ARITH_UNIT ( Z => SUM, B=> D2, A=>D1,
OP=>ADD, ZCOMP => COMP); -- Sự kết hợp theo tên.
Một phát biểu gọi thủ tục tuần tự được thực thi tuần tự cùng với các phát biểu tuần tự chung quanh nó. Một phát biểu gọi thủ tục đồng thời được thực thi bất cứ lúc nào khi có một sự kiện xảy ra trên một trong các tham số, mà các tham số này là một tín hiệu ở chế độ in hoặc inout. Một lời gọi thủ tục đồng thời có nghĩa tương đương với một process có chứa một lời gọi thủ tục tuần tự và một phát biểu wait. Phát biểu wait này sẽ làm cho quá trình chờ cho đến khi có một sự kiện xuất hiện trên các tham số tín hiệu của mode in hoặc inout.
Sau đây là một ví dụ của lời gọi thủ tục đồng thời và phát biểu process tương đương với nó:
architecture DUMMY_ARCH of DUMMY is
-- Tiếp đến là thân của thủ tục
procedure INT_2_VEC ( signal D : out BIT_VECTOR ;
START_BIT, STOP_BIT : in NATUAL ;
signal VALUE : in INTEGER ) is
begin
-- Mô tả hoạt động hành vi của thủ tục
end INT_2_VEC;
begin
-- Đây là ví dụ của một lời gọi thủ tục đồng thời.
INT_2_VEC (D_ARRAY, START, STOP, SIGNAL_VALUE);
end DUMMY_ARCH;
Phát biểu process tương đương với lời gọi một thủ tục đồng thời như sau:
process
begin
INT_2_VEC (D_ARRAY,START,STOP,SIGNAL_VALUE);
-- Phần thể hiện của các lời gọi thủ tục tuần tự
wait on SIGNAL_VALUE;
-- Chờ sự kiện trên SIGNAL_VALUE và xem chúng nh một tín hiệu
-- vào.
end process;
Một procedure có thể sử dụng hoặc là một phát biểu đồng thời hoặc là phát biểu tuần tự. Các lời gọi đồng thời thường xuyên được dùng để mô tả chính là các process.
Ví dụ của thủ tục dùng có khai báo postpone (trì hoãn).
postponend procedure INT_2_VEC ( signal D:out BIT_VECTOR ;
START_BIT,STOP_BIT : in NATUAL;
signal VALUE :in INTEGER) is
begin
-- Phần khai báo hoạt động của thủ tục
end INT_2_VEC;
Ngữ nghĩa của một lời gọi thủ tục đồng thời dùng postponed là tương đương với ngữ nghĩa của phát biểu process tương ứng với nó và được gọi là phát biểu process bị trì hoãn.
Một thân process có thể có phát biểu wait, trong khi một function thì không được phép có. Các function được sử dụng để tính toán các giá trị một cách tức thì. Vì vậy một function không cần có phát biểu wait trong đó. Một function không thể gọi một procedure có phát biểu wait trong thủ tục đó.
Một process mà có chứa lời gọi một thủ tục mà trong thủ tục này có chứa phát biểu wait, thì process này không được khai báo sensitivity list. Hơn nữa từ thực tế chúng ta thấy một process không thể nhận biết các tín hiệu thuộc sensitivity list vì nếu có process này sẽ rơi vào trạng thái chờ ngay lập tức.
Với một thủ tục có chứa phát biểu wait thì bất cứ biến hay hằng nào được khai báo trong thủ tục đó sẽ giữ nguyên giá trị của chúng trong suốt thời gian thực hiện phát biểu wait và tồn tại chỉ khi thủ tục được kết thúc.
3.8. CÁC ĐÓNG GÓI
Bạn có thể đóng gói để cất các chương trình con, các kiểu dữ liệu, các hằng... thường dùng để sử dụng chúng trong các thiết kế khác. Một package bao gồm hai phần chính: Phần khai báo và phần thân package, phần khai báo chỉ ra giao tiếp cho package.
Cú pháp của khai báo package như sau:
package package _name is
{package _declarative_item}
end [package _name];
Phần package _declarative_item có thể là bất kỳ kiểu nào sau đây:
- Khai báo kiểu.
- Khai báo các kiểu con.
- Khai báo tín hiệu.
- Khai báo các hằng.
- Khai báo bí danh ALIAS.
- Khai báo các thành phần.
- Khai báo các chương trình con.
- Các mệnh đề USE.
Chú ý ! Khai báo tín hiệu trong package có một số vấn đề cần luu ý trong khi tổng hợp, bởi vì một tín hiệu không thể được chia sẻ bởi hai Entity. Vì vậy nếu muốn dùng chung khai báo tín hiệu bạn phải khai báo tín hiệu này là tín hiệu toàn cục.
Phần thân của package chỉ ra hoạt động thực tế của một package. Phần thân của package phải luôn có tên trùng với phần khai báo.
Cú pháp của khai báo này như sau:
package body package _name is
{package _body_declarative-item}
end [package _name] ;
Phần package _body_declarative-item có thể bao gồm:
- Khai báo kiểu.
- Khai báo các kiểu con.
- Khai báo các hằng
- Mệnh đề use.
- Thân các chương trình con.
Ví dụ:
library IEEE;
use IEEE.NUMERIC_BIT.all;
package PKG is
subtype MONTH_TYPE is integer range 0 to 12;
subtype DAY_TYPE is integer range 0 to 31;
subtype BCD4_TYPE is unsigned ( 3 downto 0);
subtype BCD5_TYPE is unsigned ( 4 downto 0) ;
constant BCD5_1: BCD5_TYPE : = b"00001" ;
constant BCD5_7: BCD5_TYPE : = b"00111" ;
function BCD_INC (L : in BCD4_TYPE) return BCD5_TYPE;
end PKG;
package body PKG is
function BCD_INC (L :in BCD4_TYPE) return BCD5_TYPE is
variable V,V1, V2 : BCD5_TYPE;
begin
V1 : = L + BCD5_1;
V2 : = L + BCD5_7;
case V2(4) is
when ' 0 ' => V : = V1;
when ' 1 ' => V : = V2;
end case;
return (V);
end BCD_INC;
end PKG;
3.9. MÔ HÌNH CẤU TRÚC
Thông thường một hệ thống số được mô tả theo tập hợp có thứ bậc của các thành phần. Mỗi thành phần bao gồm một tập các cổng để có thể giao tiếp được với các thành phần khác. Khi mô tả một thiết kế trong VHDL và một thiết kế có thứ bậc chính là một thiết kế đưa ra các khai báo của các thành phần và các phát biểu thể hiện thành phần đó.
Một đơn vị cơ sở để diễn tả hành vi hoạt động chính là các phát biểu process, còn đơn vị cơ sở để diễn tả theo kiểu cấu trúc chính là các phát biểu thể hiện của các đơn vị thành phần. Cả hai loại này đều có thể có mặt trong một thân của một kiến trúc (architecture).
3.9.1. Các khai báo thành phần
Một thân kiến trúc có thể sử dụng các Entity khác (không trong cùng khai báo của architecture ), các Entity này được mô tả tách biệt và được đặt trong thư viện thiết kế. Để sử dụng chúng, người ta dùng các khai báo thành phần và các phát biểu thể hiện của chúng .Trong mô tả thiết kế, mỗi phát biểu khai báo thành phần phải tương ứng với một Entity. Các phát biểu khai báo thành phần phải giống với các phát biểu được chỉ ra trong Entity (các phát biểu giao tiếp vào ra của thành phần đó). Cú pháp khai báo của chúng như sau:
component component _name
[ port ( local_port_declaration ) ]
end component ;
Trong đó component _name mô tả tên của Entity và port_declaration là khai báo các cổng của component và phải trùng với phần khai báo đã chỉ ra của component nằm trong phần khai báo của Entity.
3.9.2. Các thể hiện của component
Một component được định nghĩa trong một architecture có thể được thể hiện thông qua việc sử dụng các phát biểu thể hiện của chúng. Khi thể hiện chỉ được phép thể hiện phần giao tiếp của component (bao gồm tên, kiểu, hướng của các cổng vào ra của chúng), các tín hiệu bên trong chúng không được thể hiện.
Cú pháp thể hiện component như sau:
instantiation_label : component _name
port map (
[ local_port_name =>] expression
{ [local_port_name =>] expression}
);
Một phát biểu thể hiện component cần phải khai báo phần nhãn của thể hiện trước instantiation_label. Hình vẽ 3.11 và 3.12 dưới đây mô tả phần giao diện và phần thực thi bên trong của một bộ cộng full_Adder.
Hình 3.11: Phần giao diện component của bộ cộng Full_adder
Hình 3.12: Các thành phần bên trong bộ Full_adder.
Như trên hình vẽ chúng ta thấy phần thực thi có ba loại cổng khác nhau và chúng được mang tên như sau: OR2_gate, AND2_gate, XOR_gate, chúng được dùng để xây dựng nên bộ cộng. Để mô tả và thể hiện chúng trong thiết kế, ta có thể viết chương trình để thực thi từng thành phần của chúng như sau:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Entity AND2_gate is
port ( I0, I1 : in STD_LOGIC ;
O : out STD_LOGIC );
End AND2_gate;
Architecture BHV of AND2_gate is
Begin
O <= I0 and I1;
End BHV;
-----------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Entity XOR_gate is
port ( I0, I1 : in STD_LOGIC ;
O : out STD_LOGIC );
End XOR_gate;
Architecture BHV of XOR_gate is
Begin
O <= I0 xor I1;
End BHV;
-------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Entity OR2_gate is
port ( I0, I1 : in STD_LOGIC ;
O : out STD_LOGIC );
End OR2_gate;
Architecture BHV of OR2_gate is
Begin
O <= I0 xor I1;
End BHV;
Để thể hiện các component này trong một thiết kế, ta khai báo chúng như sau:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Entity FULL_ADDER is
port (A, B, Cin : in STD_LOGIC;
Sum, Cout : out STD_LOGIC);
End FULL_ADDER;
Architecture IMP of FULL_ADDER is
component XOR_gate
port ( I0, I1 : in STD_LOGIC; O : out STD_LOGIC );
end component ;
component AND2_gate
port ( I0, I1 : in STD_LOGIC; O : out STD_LOGIC );
end component;
component OR2_gate
port ( I0, I1 : in STD_LOGIC; O : out STD_LOGIC );
end component;
signal N1, N2, N3: STD_LOGIC;
begin
U1 : XOR_gate port map (I0 => A, I1=> B, O=>N1);
U2 :AND2_gate port map ( A, B, N2);
U3 :AND2_gate port map ( Cin, N1, N3);
U4 :XOR_gate port map ( Cin, N1, Sum);
U5 :OR2_gate port map ( N3, N2, Cout);
end IMP;
3.9.3. Các phát biểu Generate
Phát biểu generate là một phát biểu đồng thời và nó được định nghĩa trong phần architecture. Nó được dùng để mô tả các cấu trúc giống nhau, hay tái tạo lại các cấu trúc khác giống như bản gốc. Cú pháp của chúng như sau:
instantiation _label : generation_scheme generate
{concurrent_statement}
end generate [instantiation _label];
Có hai loại lược đồ generation : Lược đồ for và lược đồ if. Lược đồ for được dùng để diễn tả cấu trúc thông thường, nó được dùng để khai báo một tham số generate và một dải rời rạc của lược đồ for (chỉ ra tham số vòng lặp và dải rời rạc trong các phát biểu lặp tuần tự). Các giá trị tham số của generate có thể được đọc nhưng không được gán hay chuyển ra ngoài phát biểu generate.
a. Sử dụng lược đồ for:
Ví dụ: Giả sử ta có bộ cộng 4 bit mà trong đó bao gồm bốn bộ cộng Full_adder như đã được mô tả ở trên. Xem hình 3.13 dưới đây:
Hình 3.13: Bộ cộng 4 bit.
Để mô tả bộ cộng 4 bit này và sử dụng phát biểu generate, sử dụng mô tả bộ cộng Full_Adder như trên ta đã mô tả. Ta có thể viết chúng như sau:
architecture IMP of FULL_ADDER4 is
signal X, Y, Z : STD_LOGIC_VECTOR ( 3 downto 0 ) ;
signal Cout : STD_LOGIC ;
signal TMP : STD_LOGIC_VECTOR ( 4 downto 0 ) ;
component FULL_ADDER
port ( A, B, Cin : in STD_LOGIC ;
Sum, Cout : out STD_LOGIC );
end component ;
begin
TMP (0) <= ' 0 ';
G : for I in 0 to 3 generate
FA: FULL_ADDER port map ( X (I), Y(I), TMP (I), Z (I),TMP (
I+1 )); end generate ;
Cout <= TMP (4);
end IMP;
b, Sử dụng lược đồ if
Hình 3.14: Sơ đồ bộ cộng bốn bit sử dụng một bộ cộng
Half_ADDER và ba bộ cộng Full_ADDER.
Một số cấu trúc có dạng không theo qui luật chuẩn nào, với trường hợp này ta có thể sử dụng lược đồ if. Giả sử ta mô tả bộ cộng bốn bit như trên hình 3.14 và sử dụng lược đồ IF generate để mô tả bộ cộng này. Chương trình được viết như sau:
architecture IMP of FULL_ADDER4 is
signal X, Y, Z : STD_LOGIC_VECTOR ( 3 downto 0 ) ;
signal Cout : STD_LOGIC ;
signal TMP : STD_LOGIC_VECTOR ( 4 downto 1) ;
component FULL_ADDER
port ( A, B, Cin : in STD_LOGIC ;
Sum, Cout : out STD_LOGIC );
end component ;
component HALF_ADDER
port ( A, B : in STD_LOGIC ;
Sum, Cout : out STD_LOGIC );
end component ;
begin
G0 : for I in 0 to 3 generate
G1: if I = 0 generate
HA: HALF_ADDER port map ( X (I), Y(I), Z (I), TMP ( I+1 ));
end generate ;
G2: if I >= 1 and I <= 3 generate
FA: FULL_ADDER port map ( X (I), Y(I), TMP (I), Z (I),TMP ( I+1 ));
end generate ;
end generate ;
Cout <= TMP ( 4 );
end IMP;
3.9.4. Các thông số của việc định cấu hình
Trong một Entity có thể có một vài cấu trúc, vì vậy các chi tiết của việc định cấu hình cho phép người thiết kế chọn các Entity và kiến trúc của nó.
Cú pháp khai báo của chúng như sau:
for instantiation _list : component _name
use Entity library_name. Entity _name [( architecture _name)] ;
Nếu chỉ có một kiến trúc architecture thì tên architecture có thể bỏ qua. Xem thêm một ví dụ dưới đây:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
Entity FULL_ADDER is
port ( A, B, Cin : in STD_LOGIC;
Sum, Cout : out STD_LOGIC);
End FULL_ADDER;
Architecture IMP of FULL_ADDER is
component XOR_gate
port ( I0, I1 : in STD_LOGIC; O : out STD_LOGIC );
end component ;
component AND2_gate
port ( I0, I1 : in STD_LOGIC; O : out STD_LOGIC );
end component;
component OR2_gate
port ( I0, I1 : in STD_LOGIC; O : out STD_LOGIC );
end component;
signal N1, N2, N3: STD_LOGIC;
for U1 : XOR_gate use entity work.XOR_gate (BHV);
for others : XOR_gate use entity work.XOR_gate (BHV);
for all : AND2_gate use entity work.AND2_gate (BHV);
for U5 : OR2_gate use entity work.OR2_gate (BHV);
begin
U1 : XOR_gate port map (I0 => A, I1=> B, O=>N1);
U2 :AND2_gate port map ( A, B, N2);
U3 :AND2_gate port map ( Cin, N1, N3);
U4 :XOR_gate port map ( Cin, N1, Sum);
U5 :OR2_gate port map ( N3, N2, Cout);
end IMP;
Các file đính kèm theo tài liệu này:
- Kien thuc co ban VHDL.doc