概述
本文主要参考b站视频:【考研】EDA技术(vhdl技术),建议有时间的跟着听一下,从第8节开始,一直到31节都是讲VHDL,讲的很全面,赶时间的可以直接看我这个笔记。
文章目录
- 1.3 VHDL语言要素
- 1.3.1 VHDL文字规则
- 1.3.2 数据对象
- 1.3.3 VHDL数据类型
- 1.3.4 VHDL中的表达式
- 1.4 VHDL顺序语句(Sequential)
- 1.4.1 对象与赋值语句
- 1.4.2转向控制语句
- 1.4.3 wait语句
- 1.4.4子程序调用语句
- 1.4.5 return 语句
- 1.4.6 null语句
- 1.4.7 其它语句和说明
1.3 VHDL语言要素
四类语言要素:
- 数据对象(Data Object)
- 数据类型(Data Type)
- 操作数(Operands)
- 操作符(Operator)
1.3.1 VHDL文字规则
- 数字型文字
(1)整数文字:十进制整数
如:5,678,156E2(=15600),45_234_287(=45234287)
(2)实数文字:带小数的十进制数
如:23.34,2.0,44.99E-2(=0.4499),88_67_551.23_909(8867551.23909)
(3)一数制基数表示的文字
格式:基数#数字文字#E指数
如:10#170#(=170)
2#1111_1110#(=254)
16#E#E1(=2#1110_0000#=224)或(=14×16=224)
16#F.01#E+2(=(15+1/(16+16))×16×16=3841.00)
(4)物理量文字
如:60s、100m、177A
注:整数可综合实现;实数一般不可综合实现;物理最不可综合实现; - 字符串型文字
按字符个数多少分为:
- 字符:用单引号引起来的ASCⅡ字符,可以是数值,也可以是符号或字母。如:‘A’,’*’,‘Z’
- 字符串:用双引号引起来的一维字符数组
字符串分为:
(1)文字字符串:“文字”
如:“ERROR”,
“XXXXXXXX“,“ZZZZZZZZ",“X”,“BOTH S AND Q EQUAL TOL”
在VHDL中“X”表示不定值状态,“Z”代表高阻状态
(2)数位字符串:
称为位矢量,代表二进制、八进制、十六进制的数组。其位矢量的长度为等值的二进制数的位数。
格式:基数符号“数值”
其中基数符号有三种:
B:二进制基数符号。O:八进制基数符号,每一个八进制数代表一个3位的二进制数。X:十六进制基数符号,每一个十六进制数代表一个4位的二进制数。
如:
B“1_1101_1110” 二进制数数组,长度为9
O“34“ 八进制数数组,长度为6
X”1AB” 十六进制数数组,长度为12
- 标识符
定义常数、变量、信号、端口、子程序或参数的名字。
- 基本标识符的要求(87标准):
以英文字母开头;不连续使用下划线“_”,不以下划线“_”结尾;由26个大小写英文字母、数字0-9及下划线“_”组成的字符串。
基本标识符中的英文字母不分大小写;VHDL的保留字不能作为标识符使用。
合法标识符如下:
my_counter、Decoder_1、FFT、Sig_N、Not Ack、State0
非法标识符如下:
_Decoder_1、2FFT、Sig_#N、Not-Ack、ALL_RST_、data__BUS、return、entity
- 扩展标识符(93标准):
以反斜杠来界定,免去了87标准中基本标识符的一些限制。可以以数字打头,允许包含图形符号,允许使用VHDL保留字,区分字母大小写等。
如:74LS163、Sig_#N、entity、ENTITY
- 下标名及下标段名
- 下标名:用于指示数组型变量或信号的某一元素。
格式:标识符(表达式)
- 下标段名:用于指示数组型变量或信号的某一段元素。
格式:标识符(表达式 to/downto 表达式)
to是递增,downto是递减
如:a:std_logic_vector(7 downto 0)
a(7),a(6)…a(0)
a(7 downto 0),a(7 downto 4),a(5 downto 3)…
1.3.2 数据对象
三种对象:常量(Constant)
变量(Variable)
信号(Signal)
三种对象的物理含义:常量代表数字电路中的电源、地、恒定逻辑值等常数;变量代表暂存某些值的载体,常用于描述算法;信号代表物理设计中的某一条硬件连接线,包括输入、输出端口。
三种对象的特点及说明场合:
信号:全局量,用于architecture、package、entitiy。
变量:局部量,用于process、function、procedure。
常量:全局量,可用于上面两种场合。
- 常量说明
常量说明:对某一个常量名赋予一个固定的值。
格式:constant 常数名:数据类型:=表达式;
例:
constant data:bit_vector(3 downto 0):="1010";
constant width:integer:=8;
constant x:new_bit:='x';
常量数据类型必须与表达式的数据类型一致。
常量的可视性(作用范围):
常量是全局量,其作用范围取决于常量被定义的位置。
2. 变量说明
变量是一个局部量,只能在进程和子程序中定义、使用。其作用范围仅限于定义了变量的进程和子程序中。
格式:variable 变量名:数据类型 约束条件:=表达式;
例:
variable a,b:bit;
variable count:integer range 0 to 255:=10;
变量的初值可用于仿真,但综合时被忽略。
3. 信号说明
电子硬件系统运行的基本特性:各部分电路工作的并行特性;信号传输过程中的延时特性;多驱动源的总线特性;时序电路中触发器的记忆特性等。
信号是电子系统内部硬件连接和硬件特性的抽象表示。用来描述硬件系统的基本特性。
格式:signal 信号名:数据类型 约束条件:=表达式;
例:
signal a,b:bit;
signal init:integer:=-1;
signal s1:std_logic:=‘0’;
signal s2:std_logic_vector(15 downto 0);
注:
a.综合时初值被忽略。
b.信号是全局量。可在结构体、实体、块中说明和使用信号。
c.在进程和子程序中只能使用信号,不能说明信号。
例:进程中信号与变量的使用
Entity ex is
port(....…);
end ex;
architecture arch_ex of ex is
signal a,b:std_logic;
begin
process(a,b)
variable c,d:std_logic;
begin
c:=a+b;
d:=a-b;
end process;
end arch_ex;
信号与端口的区别:
除没有方向说明外,信号与实体的“端口(PORT)”概念相似。端口是一种隐形的信号。
entity exam is
port([signal]a,b:in std_logic;
[signal]c:out std_logic);
end exam;
端口是一种有方向的信号。即输出端口不能读出数据,只能写入数据;输入端口不能写入数据,只能读出数据。
信号本身无方向,可读可写。
1.3.3 VHDL数据类型
VHDL是一种强数据类型语言。要求设计实体中的每一个常数、信号、变量、函数以及设定的各种参量都必须具有确定的数据类型,并且相同数据类型的量才能互相传递和作用。
VHIDL数据类型分为四大类:
标量类型(SCALAR TYPE)、复合类型(COMPOSITE TYPE)、存取类型(ACCESS TYPE)、文件类型(FILES TYPE)
又分为:
预定义数据类型、用户自定义数据类型
- VHDL的预定义数据类型
1)布尔量(boolean)
布尔量具有两种状态:false和true
常用于逻辑函数,如相等(=)、比较(<)等中作逻辑比较。
如,bit值转化成boolean值:
boolean_var:=(bit_var=‘1’);
2)位(bit)
bit表示一位的信号值。放在单引号中,如’0’或’1’。
3)位矢量(bit_vector)
bit_vector是用双引号括起来的一组位数据。
如:“001100” X"00B10B"
4)字符(character)
用单引号将字符括起来。
variable character_var:character;Character_var:=‘A’:
5)整数(integer)
integer表示所有正的和负的整数。硬件实现时,利用32位的位矢量来表示。可实现的整数范围为:
-(231-1)to(231-1)
VHDL综合器要求对具体的整数作出范围限定,否则无法综合成硬件电路。
如:signals:integer range 0 to 15;
信号s的取值范围是0~15,可用4位二进制数表示,因此s将被综合成由四条信号线构成的信号。
6)自然数(natural)和正整数(positive)
natural是integer类型的子类型,表示非负整数。
positive是integer类型的子类型,表示正整数。
定义如下:
subtype natural is integer range 0 to integer’high:subtype positive is integer range 1 to integer’high:
7)实数(REAL)或称浮点数
取值范围:-1.0E38~+1.0E38
实数类型仅能用于VHDL仿真器,一般综合器不支持。
8)字符串(string)
string是character类型的一个非限定数组。用双引号将一串字符括起来。如:
variable string_var:string(1 to 7);
string_var:="Rosebud";
9)时间(TIME)
由整数和物理单位组成,在仿真器中使用
如:55 ms,20 ns
10)错误等级(SEVERITY_LEVEL)
仿真中用来指示系统的工作状态,共有四种:
NOTE(注意)、WARNING(警告)、ERROR(出错)、FAILURE(失败)
2. IEEE预定义标准逻辑位与矢量
1)std_logic 类型
由ieee库中的std_logic_1164程序包定义,为九值逻辑系统,如下:
(“U”,“X”,“0”,“1”,“Z”,“W”,“L”,“H”,“-”)
“U”:未初始化的,“X”:强未知的,
“0”:强0,“1”:强1,“Z”:高阻态,“W”:弱未知的,“L”:弱0,“H”:弱1,
“-”:忽略
由std logic类型代替bit类型可以完成电子系统的精确模拟,并可实现常见的三态总线电路。
2)std_logic_vector类型
由std logic构成的数组。定义如下:
type std_logic_vector is array(natural range<>) of std_logic;
赋值的原则:相同位宽,相同数据类型。
3. 其它预定义标准数据类型
Synopsys公司程序包
STD_LOGIC_ARITH中:
1)无符号型(UNSIGNED)定义如下:
type unsigned is array(natural range<>)of std_logic;UNSIGNED("1000")=8
最左位是最高位:
variable var:unsigned(0 to 10);var(0)是最高位
signal sig:unsigned(5 downto 0);sig(5)是最高位
2)有符号型(SIGNED)定义如下:
type signed is array(natural range<>)of std_logic;
最高位为符号位,综合器认作补码。
SIGNED(“0101”)=5,SIGNED(“1011”)=-5
variable var:signed(0 to 10);
var(0)是符号位
3)小整型(SMALL_INT):0 TO 1
4. 用户自定义类型
用户自定义类型是VHDL语言的一大特色。
可由用户定义的数据类型有:
枚举类型、整数和实数类型、数组类型、记录类型、子类型
用类型定义语句TYPE和子类型定义语句SUBTYPE实现用户自定义数据类型。
TYPE语句格式:
type 数据类型名 is 数据类型定义 [of 基本数据类型];
例:
type byte is array(7 downto 0) of bit;
variable addend:byte;
type week is(sun,mon,tue,wed,thu,fri,sat);
SUBTYPE语句格式:
subtype 子类型名 is 基本数据类型 约束范围;
例:
subtype digits is integer range 0 to 9;
由subtype语句定义的数据类型称为子类型。子类型不是一种新的数据类型,而是已有的数据类型的子集。
1)枚举类型
枚举该类型的所有可能的值。格式:
type 类型名称 is (枚举文字{, 枚举文字});
如:
type std_logic is('U','X','0','1','Z','W','L','H','-')
如:
type color is (blue,green,yellow,red);
type my_logic is('0','1','U','Z');
variable hue:color;
signal sig:my_logic;
hue:=blue;
sig<='Z';
枚举类型的编码:
综合器自动实现枚举类型元素的编码,一般将第一个枚举量(最左边)编码为0,以后的依次加1。编码用位矢量表示,位矢量的长度将取所需表达的所有枚举元素的最小值。
如:type color is(blue,green,yellow,red);
编码为:blue=“00”;green=“01”;yellow=“10”;red=“11”;
2)整数类型
用户定义的整数类型是标准包中整数类型的子范围。
格式:
type 类型名称 is integer 整数范围;
例:type my integer is integer range 0 to 9;
3)数组类型
数组:同类型元素的集合。VHDL支持多维数组。多维数组的声明:
type byte is array(7 downto 0) of bit;
type vector is array(3 downto 0) of byte;
限定数组、非限定数组、属性:
限定数组:
其索引范围有一定的限制。
格式:
type 数组名 is array (数组范围) of 数据类型;
非限定数组:数组索引范围被定义成一个类型范围。
格式:
type 数组名 is array(类型名称range<>) of 数据类型;
例:非限定数组
type bit_vector is array(integer range <>)of bit;
variable my_vector:bit_vector(5 downto -5);
属性:
VHDL为多种类型定义了属性。
语法如下:对象'属性
VHDL为数组预先定义的属性:
left right high low length range reverse_range
对应变量:
variable my_vector:bit_vector (5 downto -5);
各属性如下:
BT版美
my vector’left 5
my_vector’right -5
my_vector’high 5
my_vector’low -5
my_vector’length 11
my_vector’range(5 downto -5)
my_vector’reverse_range(-5 to 5)
4)记录类型
记录是不同类型的名称域的集合。
格式如下:
type 记录类型名 is record
元素名:数据类型名;
元素名:数据类型名;
end record;
访问记录体元素的方式:记录体名.元素名
例:
constant len:integer:=8;
subtype byte_vec is bit_vector (len-1 downto 0);
type byte_and_ix is record
byte:byte_vect;
ix:integer range 0 to len;
end record;
signal x,y,z:byte_and_ix;
signal data:byte_vec;
signal num:integer;
x.byte<="11110000";
x.ix<=2;
data<=y.byte;
num<=y.ix;
z<=x;
5)子类型
子类型是已定义的类型或子类型的一个子集。
格式:subtype 子类型名 is 数据类型名[范围]:
例:
bit_vector类型定义如下:
type bit_vector is array (natural range <>) of bit;
如设计中只用16bit;可定义子类型如下:
subtype my_vector is bit_vector (0 to 15);
注:子类型与基(父)类型具有相同的操作符和子
程序。可以直接进行赋值操作。
5. 数据类型转换
VHDL是一种强类型语言,不同类型的数据对象必须经过类型转换,才能相互操作。
1)类型转换函数方式
通过调用类型转换函数,使相互操作的数据对象的类型一致,从而完成相互操作。
library ieee;
use ieee.std_logic_1164.all;
entity cnt4 is
port(clk: in std_logic;
p: inout std logic vector(3 downto 0));
end cnt4;
-- 调用转化函数相应的库和程序包
library dataio;
use dataio. std_logic_ops. all;
architecture behv of cnt4 is
begin
process(clk)
begin
if clk'event and clk='1' then
p<=to_vector(2, to_integer(p)+1);
end if;
end process;
end behv:
2)直接类型转换方式
对相互间非常关联的数据类型(如整型、浮点型),可进行直接类型转换。
格式:数据类型标识符(表达式)
如:
variable a,b:real;
variable c,d:integer;
a:=real©;
d:=integer(b);
1.3.4 VHDL中的表达式
表达式:由操作符和操作数构成,完成算术或逻辑运算。
- 操作符
VHDL操作符的分类:
逻辑操作符(Logical Operator)、关系操作符(Relational Operator)、算术操作符(Arithmetic Operator)、重载操作符(Overloading Operator)
1)逻辑操作符
6种:and、or、nand、nor、xor、not
要求:操作数类型必须相同。可为如下类型:
bit、bit_vector、std_logic、std_logic_vector、boolean数组操作数的维数、大小必须相同。
注:当有两个以上的逻辑表达式时,左右没有优先级差别,必须使用括号,如:
x<=(a and b)or(not c and d):例外:当逻辑表达式中只有“and”、“or”、“xor”运算符时,可以省略括号。如:
a<=b and c and d and e;
a<=b or c or d or e;
a<=b xor c xor d xor e;
2)关系操作符
6种:=、/=、<、<=、>、>=用于比较相同父类的两个操作数,返回boolean值。
3)加减操作符
加操作符“+”、减操作符“-”、串联(并置)操作符“&”
串联操作符“&”通过连接操作数来建立新的数组。操作数可以是一个数组或数组中的一个元素。
例:
signal a,d:bit_vector(3 downto 0);
signal b,c,g:bit_vector(1 downto 0);
signal e:bit_vector(2 downto 0);
signal f,h,i:bit;
a<=not b & not c;--array&array
d<=not e & not f;--array&element
g<=not h & not i; --element&element
4)一元操作符
仅有一个操作数的操作符。
包括:“+”、“-”
5)乘除操作符
用于整数类型;“*”、“/”、“mod”、“rem”
综合的限制:“/”、“mod”、“rem”三种操作符的右操作数必须为2的正整数次幂,即2n。实际电路用移位实现。
2. 操作数
操作数:操作符进行运算时所需的数据。
操作数的种类:
标志符;集合;属性;表达式;函数调用;索引名;文字;限定表达式;记录和域;片段名;类型转换
3、重载操作符
VHDL是强类型语言,相同类型的操作数才能进行操作。VHDL自身定义的算术和布尔函数仅对内部数据类型(standard程序包中的数据类型)有效。即:
算术运算符+,-,<,>,<=,>=仅对integer类型有效。逻辑运算符AND,OR,NOT仅对bit类型有效。如:variable a,b,c:integer;
variable x,y,z:bit;
c:=a+b;z:=x and y;
问题:a,b,c与x,y,z之间,或与std_logic等其它数据类型之间能否相互操作?
重载操作符定义:
对已存在的操作符重新定义,使其能进行不同类型操作数之间的运算,称为重载操作符。定义重载操作符的函重载操作符由原操作符加双引号表示。如“+”
重载操作符的定义见IEEE库的程序包:
std_logic_arith、std_logic_unsigned、std_logic_signed
重载操作符的使用:
LIBRARY ieee;
USE ieee.std_logic_1164.all
USE ieee.std_logic_unsigned.all;
ENTITY overload IS
PORT(a:IN STD_LOGTC_VECTOR(3 downto 0);
b:IN STD_LOGIC_VECTOR(3 downto 0);
c:IN integer range 0 to 15;
sum1:OUT STD_LOGIC_VECTOR (4 downto 0);
sum2:OUT STD_LOGIC_VECTOR(4 downto 0));END overload;
ARCHITECTURE example OF overload IS
BEGIN
PROCESS(a, b)
BEGIN
sum1<=a+b;
sum2<=a+c;
END PROCESS;
END example;
1.4 VHDL顺序语句(Sequential)
硬件执行:并发执行(VHDL本质)
仿真执行:顺序执行、并发执行
分为两大类:顺序(Sequential)描述语句
并发(Concurrent)描述语句
顺序描述语句:
执行顺序与书写顺序一致,与传统软件设计语言的特点相似。顺序语句只能用在进程与子程序中。
可描述组合逻辑、时序逻辑。
常用的顺序描述语句:
赋值语句;if语句;case语句;loop语句;next语句;exit语句;子程序;return语句;wait语句;null语句。
1.4.1 对象与赋值语句
- VHDL中常用的5种对象:
1)简单名称,如my_var;
2)索引名称,如my_array_var(3);
3)片断名称,如my_array_var(3 to 6);
4)记录域名,如my_record.a_field;
5)集合,如(my_varl,my_var2)。
所有对象均分为:变量和信号
对象:=表达式;-变量赋值
对象<=表达式;-信号赋值
要求:表达式的值必须与对象的类型、宽度一致。 - 变量赋值与信号赋值变量与信号的差异:
1)赋值方式的不同:
变量:=表达式;信号<=表达式;
2)硬件实现的功能不同:
信号代表电路单元、功能模块间的互联,代表实际的硬件连线;
变量代表电路单元内部的操作,代表暂存的临时数据。
3)有效范围的不同:
信号:程序包、实体、结构体;全局量。
变量:进程、子程序;局部量。
ARCHITECTURE
4)赋值行为的不同:
信号赋值延迟更新数值、时序电路;
变量赋值立即更新数值、组合电路。
5)信号的多次赋值
a.一个进程:最后一次赋值有效
b.多个进程:多源驱动、线与、线或、三态
例:信号的多次赋值
architecture rtl of ex is
signal a:std_logic;
begin
prgcess(..…)
begin
a<=b;
...
a<=c;
end process;
end rtl;
architecture rtl of ex is
signal a: std _logic;
begin
process(..…)
begin
a<=b;
end process;
process(..…)
begin
a<=c;
end process;
end ex;
例:信号赋值与变量赋值的比较
信号赋值:
architecture rtl of sig is
signal a,b:std logic;--定义信号
begin
process(a,b)
begin
a<=b;
b<=a;
end process;
end rtl; --结果是a和b的值互换
变量赋值:
architecture rtl of var is
begin
process
variable a,b:std logic;--定义变量
begin
a:=b;
b:=a;
end process;
end rtl;--结果是a和b的值都等于b的初值
例:变量赋值实现循环语句功能
process(indicator,sig)
variable temp:std_logic;
begin
temp:='0';
for i in 0 to 3 loop
temp:=temp xor(sig(i)and indicator(i));
end loop;
output<=temp;
end process;
以上语句等效为:
process(indicator,sig)
variable temp:std_logice;
begin
temp:=‘0';
temp:=temp xor(sig(0)and indicator(0));
temp:=temp xor(sig(1)and indicator(1));
temp:=temp xor(sig(2)and indicator(2));
temp:=temp xor(sig(3)and indicator(3));
output<=temp;
end process;
如改为信号,则无法实现原功能:
signal temp:std_logic;
process(indicator,sig,temp)
begin
temp<=‘0';
temp<=temp xor(sig(0)and indicator(0));
temp<=temp xor(sig(1)and indicator(1));
temp<=temp xor(sig(2)and indicator(2));
temp<=temp xor(sig(3)and indicator(3));
output<=temp; --只有最后一次赋值有效
end process;
1.4.2转向控制语句
转向控制语句通过条件控制开关决定是否执行一条或几条语句,或重复执行一条或几条语句,或跳过一条或几条语句。
分为五种:
if语句、case语句、loop语句、next语句、exit 语句
1、if 语句
if 语句执行一序列的语句,其次序依赖于一个或多个条件的值。
1)if语句的门闩控制
if 条件 then
顺序处理语句;
end if;
例:
if(ena='1')then
q<=d;
end if;
综合后生成锁存器(latch)
条件改为时钟沿,则生成D触发器:
library ieee;
use ieee. std_logic_1164. all;
entity dff is
poxt (clk,d: in std_logic;
g: out std_logic);
end dff;
architecture rtl of dff is
begin
process(clk)
begin
if (clk' event and clk='1') then
q<=d;
end if;
end process;
end rtl;
2)if 语句的二选择控制
格式:
if 条件 then
顺序处理语句;
else
顺序处理语句;
end if;
用条件来选择两条不同程序执行的路径。
此描述的典型电路是二选一电路:
architecture rtl of mux2 is
begin
process(a,b,sel)
begin
if(sel='1') then
y<=a;
else
y<=b;
end if;
end process;
end rtl;
3)if 语句的多选择控制
if 语句的多选择控制又称为if语句的嵌套。
格式:
if 条件 then
顺序处理语句;
elsif 条件 then
顺序处理语句;
.
.
.
elsif 条件 then
顺序处理语句;
else
顺序处理语句;
end if;
典型电路是多选一(四选一)电路。
library ieee;
use ieee. std_logic_1164. all;
entity mux4 is
port (input: in std_logic_vector(3 downto 0);
sel: in std_logic_vector(1 downto 0);
y: out std_logic);
end mux4;
architecture rtl of mux4 is
begin
process(input, sel)
begin
if(sel="00") then y<=input (0);
elsif (sel="01") then y<=input(1);
elsif (sel="10") then y<=input(2);
else y<=input(3);
end if;
end process;
end rtl;
if_then_elsif语句中隐含了优先级别的判断,最先出现的条件优先级最高,可用于设计具有优先级的电路。如8-3优先级编码器。
library ieee;
use ieee.std_logic_1164.all;
entity coder is
port(input:in std_ logie vector(7 downto 0);
output:out std logic vector(2 downto 0));
end coder;
architecture art of coder is
begin
process(input)
begin
if input(7)='0' then
output<="000";
elsif input(6)='0' then
output<="001";
elsif input(5)='0' then
output<="010";
elsif input(4)='0' then
output<="011";
elsif input(3)='0' then
output<"100";
elsif input(2)='0' then
output<="101";
elsif input(1)='0' then
output<="110";
else
output<="111";
end if;
end process;
end art;
- case 语句
case 语句常用来描述总线或编码、译码行为。可读性比if语句强。
格式如下:
case 表达式 is
when 分支条件=>顺序处理语句;
when分支条件=>顺序处理语句;
when分支条件=>顺序处理语句;
end case;
其中的分支条件可有以下的形式:
when 值=>顺序处理语句;
when 值 to 值=>顺序处理语句;
when 值|值|值…|值=>顺序处理语句;
以上三种方式的混合;
when others=>顺序处理语句;
Case语句使用注意:
1)分支条件的值必须在表达式的取值范围内。
2)两个分支条件不能重叠。
3)CASE语句执行时必须选中,且只能选中一个分支条件。
4)如果没有others分支条件存在,则分支条件必须覆盖表达式所有可能的值。
对std_logic,std_logic_vector数据类型要特别注意使用others分支条件。
例:用case语句描述四选一电路
library ieee;
use ieee. std _logic_1164.all;
entity mux4 is
port(a,b,i0,i1,i2,i3: in std_logic;
q: out std_logic);
end mux4;
architecture mux4_behave of mux4 is
signal sel: std_logic_vector(1 downto 0);
begin
process(a,b,i0,i1,12,i3)
begin
sel<=b & a;
case sel is
when "00"=>q<=i0;
when "01"=>q<=i1;
when "10"=>q<=i2;
when"11"=>q<=i3;
when others =>'x';
end case;
end process;
end mux4_behave;
例:case语句的误用
signal value:integer range 0 to 15;
signal out_1:bit;
case value is --缺少when条件语句
end case
case value is --分支条件不包含2到15
when 0=>out 1<=‘1’;
when 1=>out 1<='0';
end case;
case value is --在5到10上发生重叠
when 0 to 10=>out 1<=‘1’;
when 5 to 15=>out 1<=‘0';
end case;
例:根据输入确定输出值
library ieee;
use ieee.std_logic_1164.all;
entity mux41 is
port(s4,s3,s2,s1:in std_logic;
z4,z3,z2,z1:out std logic);
end mux41;
architecture art of mux41 is
signal sel:integer range 0 to 15;
begin
process(s4,s3,s2,s1)
begin
sel<=0;
if s1='1' then sel<=sel+1;
elsif s2='1' then sel<=sel+2;
elsif s3='1' then sel<=sel+4;
elsif s4='1' then sel<=sel+8;
else null;
end if;
z1<='0';z2<='0'; z3<='0';z4<='0';
case sel is
when 0=>z1<='1';
when 1|3=>z2<='1';
when 4 to 7|2=>z3<='1';
when others =>z4<='1';
end case;
end process;
end art;
- Loop语句
loop语句与其它高级语言中的循环语句相似。Loop语句有三种格式。
1)无限loop语句
[loop label]:LOOP
-sequential statement
EXIT loop_label;
END LOOP;
VHDL重复执行loop循环内的语句,直至遇到exit 语句结束循环。
L2:loop
a:=a+1;
exit L2 when a>10;
end loop L2;
2)for.…loop语句
[标号]:for 循环变量 in 离散范围 loop
顺序处理语句;
end loop[标号];
特点:
①循环变量是loop内部自动声明的局部量,仅在loop内可见。
②离散范围必须是可计算的整数范围:
整数表达式 to 整数表达式
整数表达式 downto 整数表达式
例:用for…loop语句描述的8位奇偶校验电路
library ieee;
use ieee.std_logic_1164.all;
entity parity_check is
port(a:in std_logic_vector(7 downto 0);
y:out std_logic);
end parity_check;
architeeture rtl of parity_check is
begin
process(a)
variable tmp:std_logic;
begin
tmp:='1';--奇校验
for i in 0 to 7 loop
tmp:=tmp xor a(i);
end loop;
y<=tmp;
end process;
end rtl;
仿真结果:
将tmp变量的初始值改为‘0’,则为偶校验电路。
3)while…loop语句
[标号]:while 循环条件 loop
顺序处理语句;
end loop[标号];
例:
sum:=0;
i:=0;
abcd:while(i<10)loop
sum:=sum+i;
i:=i+1;
end loop abcd;
注:循环变量i需事先定义、赋初值,并指定其变化方式。==一般综合工具不支持while…loop语句。==而for循环语句一般是可综合的。
例:用while…loop 语句描述的8位奇偶校验电路
library ieee;
use ieee.std_logic_1164.all;
entity parity_check is
port(a: in std_logic_vector(7 downto 0);
y: out std_logic);
end parity_check;
architecture behav of parity_check is
begin
process(a)
variable tmp:std_logic;
variable i: integer;
begin
tmp:='0';i:=0;
while(i<8) loop
tmp:=tmp xor a(i);
i:=i+1;
end loop;
y<=tmp;
end process;
end behav;
- Next语句
在loop语句中next语句用来跳出本次循环。
格式:
next [标号] [when 条件表达式];
分三种情况:
1)next;
无条件终止当前的循环,跳回到本次循环LOOP语句开始处,开始下次循环。
2)next [标号]:
无条件终止当前的循环,跳转到指定标号的LOOP语句开始处,重新开始执行循环操作。
3)next [标号] [when条件表达式];
当条件表达式的值为true,则执行next语句,进入跳转操作,否则继续向下执行。
例:
L1:while i<10 loop
L2:while j<20 loop
next L1 when i=j;
end loopL2;
end loopL1;
例:
LX: for cnt_value in 1 to 8 loop
S:a(cnt_value):='0';
k:=0;
L_Y:loop
S2:b(k):='0';
next L_X when(e>f);
S3:b(k+8);='0';
k:=k+1;
next loop L_Y;
next loop L_X;
- Exit 语句
exit 语句将结束循环状态。
格式:
exit [标号] [when 条件表达式];
next语句与exit语句的格式与操作功能非常相似,区别是:next语句是跳向loop语句的起始点,而exit语句则是跳向loop语句的终点。
例:
process(a)
variable int a:integer;
begin
int_a:=a;
for i in 0 to max_ limit loop
if(int_a<=0) then
exit;
else int_a:=int_a-1;
end if;
end loop;
end process;
例:
signal a,b: std_logic_vector(3 downto 0);
signal a_less_than_b: boolean;
......
a_less_than_b <= false;
for I in 3 downto 0 loop
if a(I) = '1' and b(I) = '0' then
a_less_than_b <= false;
exit;
elsif a(I) = '0' and b(I) = '1' then
a_less_than_b <= true;
exit;
else null;
end if;
end loop;
1.4.3 wait语句
进程在仿真时的两个状态:执行或挂起。
进程状态的变化受wait 语句或敏感信号量变化的控制。
可设置4种不同的条件:
wait–无限等待
wait on–敏感信号量变化(仿真中用的多一些)
wait until–条件满足(可综合)
wait for–时间到
- wait on语句
格式:
wait on 信号[,信号];
例:以下两种描述是完全等价的
process(a,b)
begin
y<=a and b;
end process;
process
begin
y<=a and b;
wait on a,b;
end process;
敏感信号量列表和wait 语句只能选其一,两者不能同时使用。
2. wait until语句(可综合)
格式:
wait until 表达式;
当表达式的值为“真”时,进程被启动,否则进程被挂起。
wait until语句的三种表达方式:
wait until 信号=value;
wait until 信号’event and 信号=value;
wait until not(信号’stable)and 信号=value;
时钟信号clk的上升沿的描述:
wait until clk=‘1’;
wait until rising_edge(clk);
wait until clk’event and clk=‘1’;
wait until not(clk’stable)and clk=‘1’;
由以上描述可实现相同的硬件电路结构。
例:用wait until语句描述时钟沿,实现D触发器
architecture rtl of d is
begin
process
begin
wait until clk'event and clk='1';
q<=d;
end process;
end rtl:
例:求平均电路
process
begin
wait until clk' event and clk='1';
ave<=a;
wait until clk' event and clk='1';
ave<=ave.+a;
wait until clk' event and clk='1';
ave=ave+a;
wait until clk' event and clk='1';
ave<=(ave+a)/4;
end process;
例:同步复位功能电路
process
begin
rst loop:loop
wait until clk event and clk='1';
if rst='1' then
x<=0;
else
x<=a;
end if;
end loop rst_loop;
end process;
1.4.4子程序调用语句
定义:子程序是独立的、有名称的算法。
过程(Procedure)和函数(Function)
过程:0个或多个in、inout、或out参数。
函数:0个或多个in参数,一个return值。
子程序首:指明其名称、参数及返回值。
子程序体:描述子程序要实现的功能。
子程序调用:在任何地方(并行或顺序执行区域)根据其名称调用子程序
过程调用:
procedure name(
[parameter_name =>] expression
{,[parameter_name=>]expression});
函数调用:
function_name(
[parameter_name =>] expression
{,[parameter_name=>]expression});
1.4.5 return 语句
return语句只能用于子程序中,并用来终止一个子程序的执行。
格式:return [表达式];
分为:1)return;用于过程,只是结束过程,不返回任何值。
2)return 表达式;用于函数,并且必须返回一个值。
例:用于过程的return语句
procedure rs(s,r: in std_logic;
q,nq: inout std_logic) is
begin
if s='1' and r='1' then
report "forbidden state:s and r are equal to '1' ";
return;
else
q<=s and nq after 5 ns;
nq<=r and q after 5 ns;
end if;
end procedure rs;
例:用于函数的return语句
function opt(a,b,sel:std_logic)
return std_logic is
begin
if sel='1' then
return(a and b);
else
return(a or b);
end if;
end function opt;
1.4.6 null语句
null为空语句,不作任何操作。格式:null;
entity ex15 is
port (control: in integer range 0 to 7;
a: in bit;
z:out bit);
end ex15;
architecture behav of ex15 is
begin
process(control, a)
begin
z<=a;
case control is
when 0|7 => z <= not a;
when others => null;
end case;
end process;
end behav;
1.4.7 其它语句和说明
属性(attribute)描述:属性是某一对象的特征表示,是一个内部预定义函数。格式为:对象名’属性标识符
综合器支持的属性有:left、right、high、low、range、rverse_range、length、event、stable
属性’event:
对在当前的一个极小的时间段Δ内发生的事件的情况进行检测。
如发生事件,则返回true,否则返回false。
发生事件:信号电平发生变化。
时钟信号的上升沿描述:clock‘event and clock=‘1’
时钟信号的下降沿描述:clock’event and clock=‘0’
上升沿触发器描述:
process(clock)
begin
if clock'event and clock = '1' then
q<=data;
end if;
end proess;
属性’stable
属性’stable的测试功能与event刚好相反,信号在Δ时间段内无事件发生,则返回true,否则返回false。
以下两语句的功能相同:
clock’event and clock=‘1’
not(clock’stable)and clock=‘1’
- 参考资料:
【考研】EDA技术(vhdl技术) - 其他教程:
VHDL硬件描述语言学习笔记(一)
VHDL硬件描述语言学习笔记(二)
VHDL硬件描述语言学习笔记(三)
最后
以上就是神勇红牛为你收集整理的VHDL硬件描述语言学习笔记(二)的全部内容,希望文章能够帮你解决VHDL硬件描述语言学习笔记(二)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复