§ 3.2 VHDL的数据对象数据对象:可以被赋值的客体包括:常量 (costant)、变量( variable)、信号 (signal)和文件 (file)
物理意义:常量 ——代表硬件电路中的电源和地,只能赋值一次;
变量 ——用于局部数据的暂时存储,是一种载体,可连续赋值;
信号 ——代表物理设计中某一条硬件连接线,可连续赋值;
文件 ——可作为参数向子程序传递,并通过子程序对文件进行读写操作。
3.2.1 常量常量 ——指在 VHDL设计描述中不发生变化的值,常根据说明赋值。
常量说明:
constant 常量名 [,常量名 …],数据类型 [:=表达式 ];
例,constant VCC,real:=3.3;
constant GND1,GND2,real:=0.0;
constant delay,time:=10ns;
constant width,integer:=8;
采用常量可改善 VHDL程序的可读性,并使程序的修改更为方便。
常量必须在程序包、实体说明、结构体和进程的说明区域说明。
entity实体名 is
[类属说明 ;]
[端口说明 ;]
[实体说明部分 ;]
[实体语句部分 ;]
end [entity]实体名 ;
实体
architecture结构体名 of 实体名 is
[结构体说明语句 ;]
begin
功能描述语句 ;
end [architecture] 结构体名;
结构体
[进程标号,]process[敏感信号表 ][is]
[进程语句说明部分; ]
begin
进程语句部分;
end process [进程标号 ];
进程
3.2.2 变量和信号
1、变量变量的作用:对暂时数据进行局部存储。
是一个局部量,在进程语句、过程语句和函数语句说明区说明。
变量说明格式:
variable 变量名 [,变量名 …],数据类型 [约束条件 ][:=表达式 ];
例,variable count,integer range 0 to 255,=0;
variable tmp,std_logic:=?0?;
variable a,b,integer,=256;
variable x,y,z,integer:=16;
variable clk_en,std_logic;
2、信号信号的作用:起着连线的作用,将实体与实体、元件与元件连接起来构成系统。
是一个全局量,在程序包、实体说明和结构体中都可以说明。
信号说明格式:
signal 信号名 [,信号名 …],数据类型 [约束条件 ][:=表达式 ];
变量赋值语句,目标变量,=表达式;
例,signal count1,count2,integer range 0 to 255,=0;
signal clk,std_logic,=?0?;
signal a,b,integer,=16;
signal data_bus,std_logic_vector(7 downto 0);
信号赋值语句:
目标信号 <= 表达式;
例:设计一个与非门电路
architecture one of nand_2 is
signal ab,std_logic_vector (1 downto 0);
begin
ab<=a & b;
process(ab) is
begin
case ab is
when? 00? =>c<=‘ 1’ ;
when? 01? =>c<=‘ 1’ ;
when? 10? =>c<=‘ 1’ ;
when? 11? =>c<=‘ 0’ ;
when others =>null;
end case;
end process;
end one;
architecture one of nand_2 is
begin
process(a,b) is
variable comb,std_logic_vector (1 downto 0);
comb:=a & b;
begin
case comb is
when? 00? =>c<=‘ 1’ ;
when? 01? =>c<=‘ 1’ ;
when? 10? =>c<=‘ 1’ ;
when? 11? =>c<=‘ 0’ ;
when others =>null;
end case;
end process;
end one;
变量和信号的区别:
( 1)变量赋值是没有延迟的,而信号赋值是有延迟的;
( 2)变量只在定义它的进程、过程和函数中可见;而信号可是过个进程的全局信号。
(3)变量在硬件中没有一定的对应关系,而信号是硬件中连线的抽象描述。
例:设计三输入与非门电路
N A N D 3
in s t
三输入与非门的真值表输 入 输 出
A B C Y
0 0 0 1
0 0 1 1
0 1 0 1
0 1 1 1
1 0 0 1
1 0 1 1
1 1 0 1
1 1 1 0CBAY
三输入与非门电路
library ieee;
use ieee.std_logic_1164.all;
entity nand_3 is
port(a,b,c:in std_logic;
y,out std_logic);
end nand_3;
architecture one of nand_3 is
begin
y<=not (a and b and c);
end one;
采用进程语句结构
——信号
library ieee;
use ieee.std_logic_1164.all;
entity nand_3 is
port(a,b,c:in std_logic;
y,out std_logic);
end nand_3;
architecture one of nand_3 is
signal abc,std_logic_vector (2 downto 0); --结构体说明语句
begin
abc<=a & b & c; --进程语句说明
process(abc) is
begin
case abc is
when?000? => y<=‘1’;
when?001? => y<=‘1’;
when?010? => y<=‘1’;
when?011? => y<=‘1’;
when?100? => y<=‘1’;
when?101? => y<=‘1’;
when?110? => y<=‘1’;
when?111? => y<=‘0’;
when others =>null;
end case;
end process;
end one;
采用进程语句结构
——变量
library ieee;
use ieee.std_logic_1164.all;
entity nand_3 is
port(a,b,c:in std_logic;
y,out std_logic);
end nand_3;
architecture one of nand_3 is
begin
process(a,b,c) is
variable abc,std_logic_vector (2 downto 0);
begin
abc,=a & b & c;
case abc is
when?000? => y<=‘1’;
when?001? => y<=‘1’;
when?010? => y<=‘1’;
when?011? => y<=‘1’;
when?100? => y<=‘1’;
when?101? => y<=‘1’;
when?110? => y<=‘1’;
when?111? => y<=‘0’;
when others =>null;
end case;
end process;
end one;
§ 3.3 VHDL的数据类型
3.3.1 标量类型包括:整数类型、浮点数类型、可枚举类型和物理类型。
主要用来描述一次持有一个值的对象。
1.整数类型整数范围,-2 147 483 647 ~+ 2 147 483 647 即 -( 231-1) ~+( 231-1)
例,十进制整数,12345,10E4,-256,-1999;
二进制整数,2#111111111#,2#1111_1111#,-2#10011101#;
八进制整数,8#377#,8#3_77#,-8#3257#;
十六进制整数,16#32a7#,16#32_a7#,-16#afff7#;
通常在定义变量或信号的时候应该对整数的范围有所约束,如:
variable tmp,integer range -255 to +255;
signal count,integer range -1023 to +1023;
2,浮点数类型表示所使用的大部分数据类型,范围从 -1.0E38到 +1.0E38范围内的实数。
主要用于进行算法研究的描述,只能用于 VHDL的仿真器中。
例,128.5,220.0,15.0,+1.0E3,-1.8。
在进行浮点数书写时,一定要有小数点,否则将会有编译错误。如:
variable voltage,real range 0 to 220;
3,可枚举类型一组用表列形式给定的适用于特定操作所需要的值,是一种抽象意义非常强的建模工具。
定义格式,type 数据类型名 is (枚举元素,枚举元素,…);
枚举元素:标识符或单个字符。如:
monday,red,open,?X?,?Z?等。
例:描述一周每一天的状态,可定义一个名为 week的数据类型:
type week is (sunday,monday,tuesday,wednsday,thirsday,friday,saturday);
两个预定义的可枚举类型,bit(位 )和 boolean(布尔 )
type bit is(?0?,?1?);
type boolean is (false,true);
4,物理类型通常用来作为测试单元,表示像时间、电压和电流等物理量,只对仿真有意义。
预定义物理类型:时间类型 (包含整数和物理量单位两部分 );
整数和物理量单位之间至少要留一个空格,如 10 ns;
在 standard程序包中预定义了时间类型:
type time is range -1e18 to +1e18
units
fs;
ps= 1000 fs;
ns = 1000 ps;
us = 1000 ns;
ms = 1000 us;
sec = 1000 ms;
min = 60 sec;
hr = 60 min;
end units;
3.3.2 复合类型包括:数组类型和记录类型数组类型:由相同类型的标量元素组成的集合,即同构复合类型;
记录类型:不同类型的标量元素组成的集合,即异构复合类型。
1、数组类型定义,type 数组类型名 is array 约束范围 of 数组元素类型;
例:
type word is array (15 downto 0) of std_logic;
type data_bus is array (0 to 7) of bit;
downto ——表示数组中的元素是降序排列
to ——表示数组中的元素是升序排列在 IEEE 1076和 IEEE 1164标准的程序包中给出了数组类型 bit_vector和
std_logic_vector的预定义:
type bit_vector is array (natural range <>) of bit;
type std_logic_vector is array (natural range <>) of std_logic;
natural:数组下标类型名,在标准程序包中定义为大于等于 0的整数。
例:二维数组的定义
type matrix is array (0 to 7,0 to 5) of std_logic;
Constant romdata,matrix:=(
(?0?,?1?,?0?,?0?,?0?,?0?),
(?1?,?1?,?1?,?0?,?0?,?0?),
(?0?,?1?,?0?,?0?,?1?,?0?),
(?0?,?1?,?1?,?0?,?1?,?0?),
(?1?,?0?,?0?,?1?,?1?,?0?),
(?0?,?1?,?1?,?0?,?1?,?0?),
(?0?,?1?,?0?,?0?,?1?,?0?),
(?0?,?1?,?1?,?0?,?1?,?0?),
);
对数组的赋值:
按下标对每一个数组元素赋值;
或对整个数组进行一次赋值。如:
type byte is array (0 to 7) of bit;
signal name,byte;
signal byte1,byte;
signal tmp,bit;
( a)按照下标对每个元素赋值:
name(7)<=?0?;
name(6)<=?1?;
name(5)<=?0?;
name(4)<=?0?;
name(3)<=?0?;
name(2)<=?1?;
name(1)<=?1?;
name(0)<=?1?;
( b)对整个数组进行一次赋值:
name <=,01000111”;
对数组的引用
(a)引用整个数组
byte1 <=name;
(b)引用数组元素
tmp< name(5);
2,记录类型主要用来弥补数组类型不能将不同类型的标量元素组织在一个集合中的缺点。
定义格式:
type 记录类型名 is record
记录元素名 1:数据类型名;
记录元素名 2,数据类型名;
……
end record;
例:关于万年历的记录类型
type month_name is (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec);
type calendar is record
year,integer range 0 to 3000;
month,month_name;
day,integer range 1 to 31;
enable:bit;
data_output,std_logic_vector(7 downto 0);
end record;
对记录的赋值:
对记录的每一个记录元素分别赋值;
或对记录进行整体赋值。
先定义一个信号:
signal calendar_date,calendar;
(a)对记录的每一个元素分别赋值:
calendar_date.year <= 2001;
calendar_date.month <= Feb;
calendar_date.day <=2;
calendar.date.endable <=?1?;
calendar_date.data<=“10101111”;
(b)对记录整体赋值
calendar_date <=(2001,Feb,2,?1?,“10101111”);
例:设计 8线 —3线编码器编码:把二进制码按一定规律编排,使每组代码具有特定的含义编码器:具有编码功能的逻辑电路。
编码器的功能:把 2N个输入转化为 N位编码输出。
8线 —3线编码器
Q0
Q1
Q2
D0
D1
D2
D3
D4
D5
D6
D7
输 入 输出
D0 D1 D2 D3 D4 D5 D6 D7 Q2 Q1 Q0
1 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 1
0 0 1 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 0 1 1
0 0 0 0 1 0 0 0 1 0 0
0 0 0 0 0 1 0 0 1 0 1
0 0 0 0 0 0 1 0 1 1 0
0 0 0 0 0 0 0 1 1 1 1
8线 —3线编码器的真值表
8线 —3线编码器
library ieee;
use ieee.std_logic_1164.all;
entity bianma8_3 is
port(d:in std_logic_vector(7 downto 0);
q,out std_logic_vector(2 downto 0));
end bianma8_3;
architecture one of bianma8_3 is
begin
process(d) is
begin
case d is
when?00000001? => q<=?000?;
when?00000010? => q<=?001?;
when?00000100? => q<=?010?;
when?00001000? => q<=?011?;
when?00010000? => q<=?100?;
when?00100000? => q<=?101?;
when?01000000? => q<=?110?;
when?10000000? => q<=?111?;
when others =>q<=?000? ;
end case;
end process;
end one;
例:设计 3线 —8线译码器译码:是编码的逆过程,是将具有特定含义的二进制码进行辨别,并转换成控制信号译码器:具有译码功能的逻辑电路地址译码器:将一系列代码转换成与之一一对应的有效信号
3,8 D E C O D E R
A
B
G1
C
G 2 A N
G 2 B N
Y 0 N
Y 1 N
Y 2 N
Y 3 N
Y 4 N
Y 5 N
Y 6 N
Y 7 N
74138
i n st
74138译码器输 入 输出
G1 G2 G3 C B A Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
X 1 X X X X 1 1 1 1 1 1 1 1
X X 1 X X X 1 1 1 1 1 1 1 1
0 X X X X X 1 1 1 1 1 1 1 1
1 0 0 0 0 0 1 1 1 1 1 1 1 0
1 0 0 0 1 0 1 1 1 1 1 1 0 1
1 0 0 0 0 1 1 1 1 1 1 0 1 1
1 0 0 0 1 0 1 1 1 1 0 1 1 1
1 0 0 0 1 1 1 1 1 0 1 1 1 1
1 0 0 1 0 0 1 1 0 1 1 1 1 1
1 0 0 1 0 1 1 0 1 1 1 1 1 1
1 0 0 1 1 1 0 1 1 1 1 1 1 1
3线 —8线译码器的真值表
library ieee;
use ieee.std_logic_1164.all;
entity decoder3_8 is
port(a:in std_logic_vector(2 downto 0);
g1,g2,g3,in std_logic;
y,out std_logic_vector(7 downto 0));
end decoder3_8;
G1,G2,G3 ——使能端
A,B,C ——二进制码输入端
Y0…….Y7 ——编码输出端
architecture one of decoder3_8 is
begin
process(a,q1,q2,q3) is
begin
if g1=?0?then y<=“11111111”;
elsif g2=?1?or g3=?1?then y<=“11111111”;
else
case a is
when,000” => y<=“11111110”;
when,001” => y<=“11111101”;
when,010” => y<=“11111011”;
when,011” => y<=“11110111”;
when,100” => y<=“11101111”;
when,101” => y<=“11011111”;
when,110” => y<=“10111111”;
when,111” => y<=“01111111”;
when others=>y<=“11111111”;
end case;
end if;
end process;
end one;