VHDL硬件描述语言学习笔记(二)

本文主要参考b站视频:【考研】EDA技术(vhdl技术),建议有时间的跟着听一下,从第8节开始,一直到31节都是讲VHDL,讲的很全面,赶时间的可以直接看我这个笔记。

1.3 VHDL语言要素

四类语言要素:

  • 数据对象(Data Object)
  • 数据类型(Data Type)
  • 操作数(Operands)
  • 操作符(Operator)

1.3.1 VHDL文字规则

  1. 数字型文字
    (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
    注:整数可综合实现;实数一般不可综合实现;物理最不可综合实现;
  2. 字符串型文字
    按字符个数多少分为:
  • 字符:用单引号引起来的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
  1. 标识符
    定义常数、变量、信号、端口、子程序或参数的名字。
  • 基本标识符的要求(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\
  1. 下标名及下标段名
  • 下标名:用于指示数组型变量或信号的某一元素。
    格式:标识符(表达式)
  • 下标段名:用于指示数组型变量或信号的某一段元素。
    格式:标识符(表达式 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。
常量:全局量,可用于上面两种场合。

  1. 常量说明
    常量说明:对某一个常量名赋予一个固定的值。
    格式: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)
又分为:
预定义数据类型、用户自定义数据类型

  1. 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中的表达式

表达式:由操作符和操作数构成,完成算术或逻辑运算。

  1. 操作符
    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 对象与赋值语句

  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)。
    所有对象均分为:变量和信号
    对象:=表达式;-变量赋值
    对象<=表达式;-信号赋值
    要求:表达式的值必须与对象的类型、宽度一致。
  2. 变量赋值与信号赋值变量与信号的差异:
    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;
  1. 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;
  1. 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;
  1. 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;
  1. 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–时间到

  1. 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’


  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页

打赏作者

凳子花❀

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值