`
lovnet
  • 浏览: 6693934 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

FPGA学习笔记4-VHDL

 
阅读更多
VHDL基础(veryhigh speed IC hardware description language)--超高速集成电路语言
-IEEE业界标准硬件描述语言(IEEE 1076)
-用于仿真和综合的高级描述语言

术语
-HDL:硬件描述语言是软件编程语言,用于对硬件进行建模
-行为建模:由其输入输出相应描述的组件 //黑盒子
-结构化建模:由底层互联组成和原语描述的组件
-寄存器传送级(RTL):出于综合目的的一类行为建模
硬件是隐含的或者推断的
可综合
-综合:将HDL译成电路,然后对表征电路进行优化
-进程:VHDL中执行的基本单元,进程中声明按顺序执行,而进程本身同时进行

行为建模
-只有电路功能,没有结构
-没有专门的硬件目标
-用于综合和仿真

结构化建模
-电路功能和结构
-要求明确的硬件实现

RTL综合
分析编写代码-生成等价逻辑结构-译成逻辑-优化逻辑

VHDL综合和其他HDL标准
-VHDL
-ABEL,PALASM,AHDL

更多的VHDL基础
-两种构建方法
综合
仿真
-VHDL包括保留关键字
-语言的大部分对条件不敏感
-VHDL声明以;结束
-VHDL对空白不敏感。用于提高可读性。
-VHDL中的注释以"--"开始,到eol结束

综合的流程
-VHDL库,VHDL模型,技术库->综合编译->生成网络表->时序分析->布局布线->下载至FPGA中->仿真->文本,波形输出

仿真的流程
-VHDL库,VHDL模型,VHDL测试台->仿真编译器->仿真模型->仿真->加入测试向量->文本,波形输出

VHDL设计单元
-实体:用于定义模型的外观(例如:符号),所有设计都以实体来表达,顶层总是一个实体,定义端口的信息
-体系结构:用于定义模型的功能(例如,原理图),填充模型的详细信息
-配置:用于和具有实体的体系结构进行联系,使用配置每个实体可以由多个体系结构
-封装:信息收集,可供VHDL模型引用(例如:库)
包括两部分:封装声明和封装体

实体声明
ENTITY <entity_name> IS
Generic Declarations
Port Declarations
END <entity_name>; //IEEE1076-1989 Version
END ENTITY <entity_name>; //IEEE1076-1993 Version,使用

-类推:符号
-<entity_name>可以是任意字母/数字
-属性声明
用于将信息传递给模型
Quartus2软件对属性声明的使用进行了限制
-端口声明
用于描述输入和输出(例如,引脚)

实体:属性声明
ENTITY <entity_name> IS
GENERIC(
CONSTANT tplh,tphl : time :=5ns;
--关键字CONSTANT可以被省略
tphz,tplz : TIME :=3ns;
default_value : INTEGER :=1;
cnt_dir : STRING := "UP"--最后一个分号可以打在外面
);
Port Declarations
END ENTITY <entity_name>;

-结构:<class>object_name:<type>:=<inital_value>;
<class>:对目标的行为
object_name:标识符
<type>:目标数据类型
<inital_value>:可选,初始化值

实体:端口声明
ENTITY <entity_name> IS
Generic Declarations
PORT(
SIGNAL clk,clr:IN BIT;
--关键字SIGNAL可以省略
q:OUT BIT
); --最后一个分号可以打在外面
END ENTITY <entity_name>;

-结构:<class>object_name:<mode> <type>
<class>:对目标的行为
object_name:标识符
<mode>:端口的方向,in(输入),out(输出),inout(双向),buffer(输出 w/ 内部反馈)
<type>:数据类型,目标可包含什么

体系结构
-类推:原理图
-描述模型功能和可能的时序
-必须与实体相关
-实体可以由多个体系结构
-体系结构进程可以同时执行
-体系结构编码类型
行为:设计怎样工作
RTL:以寄存器来描述设计
功能:没有时序
结构:网表
门/元件级
混合:以上的混合
ARCHITECTURE <identifer> OF <entity_identifier> IS
声明部分,在体系结构使用的本地标识符如果不是端口或者属性声明,则必须在体系结构部分进行声明,然后才可以使用
component declarations
subtype declarations
attribute declarations
attribute specifications
subporgram declarations
subporgram body
BEGIN
--体系结构本身
process statements
concurrent procedual calls
concurrent signal calls
component instantiation statements
generate statements
END ARCHITECTURE <identifier>;


配置
-用于在模型内进行联系
联系一个实体和体系结构
联系一个组件和实体-体系结构
-广泛应用在仿真环境中
为设计选择提供灵活而又快速的途径
-在综合环境中受到限制,或者不支持
CONFIGURATION <identifier> OF <entity_name> IS
FOR <architecture_name>
END FOR;
END CONFIGURATION <identifier>;


封装
-封装是整个模型中存储并使用信息最方便的方式
-封装包括
封装声明(需要),类型声明,子程序声明
封装体(可选),子程序定义
-VHDL由两个内置封装
标准
TEXTIO
PACKAGE <identifier> IS
--封装声明
--常量,端口,函数声明
END PACKAGE <identifier>;
PACKAGE BODY <identifier> IS
--封装体
--函数本身
END PACKAGE BODY <identifier>;



-含有一个封装或者一组封装
-资源库
标准封装
IEEE开发的封装
Altra组件封装
设计中所引用的任意设计单元库
-工作库
单元所编译的库

库/封装模型引用
-所有封装必须被编译
-隐含库
WORK
STD,PS:这些封装中的条目不需要引用,他们是隐含的
-库子项
定义可以被引用的库名称
是路径/目录的符号名称
由工程设置定义
-使用子项
在你指定的库中,指定封装和目标

使用库
-LIBRARY <name>,<name>;
名称是一个符号,由编译器工具定义。PS:WORK和STD不需要定义
-USE lib_name.pack_name.object;--ALL是保留字
-把LIBRARY/USE子句放在前面,所有的后续设计单元都可以访问它


-LIBRARY STD:含有以下封装
standard(类型:比特,布尔,整数,实数和时间。所有算子功能支持这些类型)
textio(文件操作)
-隐含库(内置):不需要在VHDL设计中进行引用

标准封装库定义的类型
-BIT
2逻辑值系统('0','1')
例:
SIGNAL a_temp:BIT;
--附加_VECTOR指示比特阵列
例:
SIGNAL temp:BIT_VECTOR(3 DOWNTO 0);
SIGNAL temp:BIT_VECTOR(0 TO 3);

-BOOLEAN
(false,true)
-INTEGER
十进制正负值
例:
SIGNAL int_tmp:INTEGER; --32位数
SIGNAL int_tmp1:INTEGER RANGE 0 TO 255; --8位数


标准封装中定义的其他类型
-NATURAL:0~4字节长度整数
-POSTIVE:1~4字节长度整数
-CHARACTER:ARCII字符
-STRING:字符串
-TIME:包括时间单位的数值(例如,ps,us,ns,ms,sec,min,hr


-LIBRARY IEEEL;
含有以下封装
--std_logic_1164(std_logic类型以及相关函数)
--std_logic_arith(算数函数)
--std_logic_signed(符号算数函数)
--std_logic_unsigned(无符号算数函数)

std_logic_1164封装中定义的类型
-STD_LOGIC:9逻辑值系统('U','X','0','1','Z','W','L','H','-')
'1':逻辑高电平
'0':逻辑低电平
'X':未知
'Z':注意大写,三态
'-':不重要
'H':弱逻辑高电平
'L':弱逻辑低电平
'W':弱未知

-确定类型:支持带有多驱动的信号
-STD_ULOGIC
和STD_LOGIC相同的9值系统
未确定类型:不支持多信号驱动,将出现错误。

体系结构建模基础
-常量
-信号
-算子
-信号赋值
-进程
-顺序声明
-变量
-用户定义的类型

常量
-命名相关值
-常量声明
CONSTANT <name>:<DATA_TYPE>:=<value>;
CONSTANT bus_width:INTEGER:=16;

-执行代码不能改变它
-提高代码的可读性
-提高代码的灵活性

信号
-表示物理互联(线)的信号,实现进程之间的通信(函数)
-信号可以在封装,实体和体系结构中进行声明

为信号赋值
SIGNAL temp:STD_LOGIC_VECTOR(7 DOWNTO 0);
-所有比特:
temp<="10101010";
temp<=x"AA"; (IEEE1076-1993)
-单比特:
temp(7)<='1';
-比特分割:
temp(7 DOWNTO 4)<="1010";
-单比特:单引号(')
-多比特:双引号(")

信号赋值
-信号赋值的表示:<=
-信号赋值是一个隐含的过程(函数),过程综合至硬件
-信号分配<=隐含进程

VHDL算子
算子类型 算子名称/符号
逻辑 NOT AND OR NAND NOR XOR XNOR
关系 = /= < <= > >=
算数& + -
算数乘 * / mod rem
其他 ** abs

算子加载
-VHDL只为内置数据类型定义算数和布尔函数(在标准封装中定义)
+,-,<,>,<=,>=等算数算子只能定义为INTEGER类型
AND,OR,NOT等布尔算子只定义为BIT类型

-算术&布尔函数怎样和其他数据类型一起用?
算子加载-定义算数&布尔其他数据类型
-通过定义名称和算子本身一样的函数来加载算子
由于算子和函数名称相同,因此,函数名称必须在双引号内,以便和实际VHDL算子区分
函数一般在封装中进行声明,这样,在任何设计中都可以实现全局可视


算子加载函数/封装
-可以在LIBRARY IEEE中找到定义这些算子加载函数的封装
std_logic_arith(算术函数)
std_logic_signed(符号算术函数)
std_logic_unsigned(无符号算术函数)
numeric_std(符号和无符号算术)


同时信号赋值
-用于向使用表达式的信号赋值
-表示并行执行的隐含过程,对赋值读(右侧)一侧敏感的进程

-三种类型,简单信号分配,条件信号分配,选择信号分配


VHDL算子用于描述进程

简单信号赋值
格式:<signal_name> <= <expression>;

例:

qa <= r or t;

qb <= (qa and not(g xor h));

条件信号赋值
格式:<signal_name> <= <signal/value> when <condition1> else
<signal/value> when <condition2> else
.
.
<signal/value> when <condition3> else
<signal/value>;

例:

q <= a WHEN sela = '1' ELSE

b WHEN selb = '1' ELSE
c;



选择信号赋值
格式:WITH <expression> select
<signal_name> <= <signal/value> when <condition1>,
<signal/value> when <condition2>,
.
.
<signal/value> when OTHERS;

例:

WITH sel SELECT

q <= a WHEN "00",
q <= b WHEN "01",
q <= c WHEN "10",
q <= d WHEN OTHERS;



信号赋值-两类延迟
-惯性延迟(默认):不传输延迟时间短语传播延迟的脉冲。
例如:a <= b AFTER 10 ns;
-传送延迟:不论多短都要传输的脉冲
例如:a <= TRANSPORT b AFTER 10 ns


显示进程声明
-一直执行进程声明,除非被WAIT声明或者敏感时间列表打断
敏感事件列表在进程的最后隐含了一个WAIT声明
进程可以用多个WAIT声明
进程不能同时有敏感时间列表和WAIT声明

-内部含顺序声明
-同时声明
一个体系结构都可以由多个进程声明
所有显式进程并行执行

label:PROCESS(sensitivity_list)
Constant declaration
.
Variable declaration
BEGIN Type declaration
-- Sequential statement #1;
-- ......
-- Sequential statement #n;
END PROCESS

PS:进程如果有参数(敏感列表)的话,那么参数变化时候,执行进程。如果进程没有参数,那么该进程在仿真开始的时候立即执行。
如果有WAIT ON(sensitivity_list),那么在进程中等待WAIT ON中的参数变化才继续执行。


顺序声明
-指示行为和表达顺序
-必须用在显示进程内部
-顺序声明
简单信号赋值
IF-THEN声明
CASE声明
循环声明
WAIT声明

IF-THEN声明
格式:
IF <condition1> THEN
{sequence of statement(s)}
ELSIF <condition2> THEN
{sequence of statement(s)}
.
.
ELSE
{sequence of statement(s)}
END IF;


CASE声明
格式:
CASE {expression} IS
WHEN <condition1> =>
{sequence of statements}
WHEN <condition2> =>
{sequence of statements}
.
.
WHEN OTHERS => --(optional)
{sequence of statements}
END CASE;


三种顺序循环
-LOOP声明,无限循环,除非出现EXIT声明
[loop_label]LOOP
--sequential statement
NEXT loop_label WHEN ...;
EXIT loop_label WHEN ...;
END LOOP;


-WHILE循环,条件测试循环结束
WHILE <condition> LOOP
--sequential statement
END LOOP;


-FOR循环,反复循环
FOR <identifier> IN <range> LOOP
--sequential statement
END LOOP;


PS:所有循环支持NEXT,EXIT

WAIT声明
-WAIT ON <signal>:暂停,直到信号事件发生
例:WAIT ON a,b;
-WAIT UNTIL <boolean_expression>:暂停,直到表达式为真
例:WAIT UNTIL (int < 100);
-WAIT FOR <time_expression>:暂停,直到经过了表达式指定的时间
例:WAIT FOR 20 ns;
-可以组合使用
例:WAIT UNTIL (a='1') FOR 5 us;

VHDL仿真
信号初始化->执行所有进程->时间推进->执行敏感进程->更新信号->重复运行

等价函数与非等价函数
c <= a AND b;
y <= c;

等价 不等价
Process1:PROCESS (a,b)
BEGIN
c <= a AND b;
END PROCESS process1;
Process2:PROCESS (c)
BEGIN
y <= c;
END PROCESS process1;
Process1:PROCESS (a,b)
BEGIN
c <= a AND b;
y <= c;
END PROCESS process1;

PS:这里感觉有点奇怪,由于显示进程中,所有的表达式都是并行运行。信号为在当前周期的最后才更新数值。
故等价为首先计算c=a&b,然后进行y=c,PROCESS括号内为敏感列表,只有其中的值发生改变才运行内部。
不等价由于同时并行计算c=a&b与y=c,所有会造成C值无法在变化后才更新。


变量声明
-在进程内部声明变量
-变量赋值表示为:=
-变量声明
VARIABLE <name> : <DATA_TYPE> := <value>;
VARIABLE temp : std_logic_vector (7 DOWNTO 0);

-立即更新变量赋值
-不会出现延迟

为变量赋值
VARIABLE temp : std_logic_vector(7 DOWNTO 0)
-所有比特:
temp:="10101010";
temp:=x"AA"; (IEEE1076-1993)

-单比特:
temp(7) := '1';
-比特分割:
temp(7 DOWNTO 4) := "1010";
其中单比特使用单引号('),多比特使用多引号(")

比较-信号和变量
信号(<=) 变量(:=)
赋值 assignee <= assignment assignee := assignment
功能 表示电路互联 表示逻辑存储
范围 全局范围(进程间通信) 本地范围(在进程内部)
行为 在当前周期最后更新数值 立即更新

用户定义类型
-数组
-枚举数组

数组
-建立2维数据类型以存储数值,必须建立该类型的常量,信号或者变量
-用于建立存储器和存储仿真矢量
-数组类型声明
TYPE <array_type_name> IS ARRAY (<integer_range>) OF <data_type>;

枚举数据类型
-使用户能够建立数据类型名称和数值,必须建立该类型的常量,信号或者变量
-用于使代码更具可读性,有限状态机
-枚举类型声明
TYPE <your_data_type> IS (data type items or values separated by commas);
例:
TYPE enum IS (idle,fill,heat_w,wash,drain);

两类进程声明
-组合进程:对组合逻辑中使用的所有输入敏感
例:
PROCESS(a,b,sel) --敏感事件列表含有组合逻辑中使用的所有输入
-顺序进程:对时钟以及控制信号敏感
PS:这个顺序进程在verilog里面叫做时钟进程,意思感觉还是差不多的
VHDL中PROCESS有点像Verilog中的always

例:
PROCESS(clr,clk) --敏感时间列表不包含输入,只有时钟和控制信号

组件声明
-用于声明底层设计端口的端口类型和数据类型
COMPONENT <lower-level_design_name>
PORT(
<port_name>:<port_type><data_type>;
.
.
<port_name>:<port_type><data_type>;
);
END COMPONENT;


组件例化
-同时声明,用于把底层设计的端口映射到当前层设计
<instance_name>:<lower-level_design_name>
PORT MAP(<lower-level_port_name> => <current_level_port_name>,
...,
<lower-level_port_name> => <current_level_port_name>

);


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics