简述VHDL语言基本结构

简述VHDL语言基本结构,第1张

VHDL语言的基本结构

VHDL语言通常包括库说明、实体说明、结构体说明3个部分。

library ieee

use ieee.std_logic_1164.all--库说明

entity dff1 is

port(clk,d:in std_logic

q:out std_logic)

end dff1 --实体说明

architecture rtl of dff1 is

begin

process(clk)

begin

if(clk'event and clk='1')then

q<=d

end if

end process

end rtl --结构体说明

VHDL提供5个库,IEEE库,STD库,VITAL库,自定义库和WORK库

IEEE库包含的常用程序包有:

std_logic_1164:常用数据类型(其中有std_logic、std_logic_vector数据类型)和函数的定义、各种类型转换 函滚皮数及逻辑运算。

std_logic_arith:它在std_logic_1164的基础上定义了无符段让号数unsigned、有符号数signed数据类型并为其定义了相应的算术运算、比较,无符号数unsigned、有符号数signed及整数integer之间转换函数。

std_logic_unsigned和std_logic_signed:定义了integer数据类型和std_logic及std_logic_vector数据类型混合运算的运算符,并定义了一个由std_logic_vector型到integer型的转换函数。其中std_logic_signed中定义的运算符是有符号数运算符。

STD库是标准库,包含两个程序包:

standard:定义了基本数据类型、子类型和函数及各种类型的转换函数等。

textio文本程序包:定义了支持文本文件 *** 作的许多类型和子程序等。在使用textio程序包之前,需要先写上use语句use std.txtio.all。

VITAL库:使用VITAL可以提高门级时序仿真的精度,一般在VHDL语言程序进行仿真时使用。主要包含两个程序包。

VITAL_timing:时序仿真包

VITAL_primitives:基本单元程序包

WORK库,是现行的工作库,设计人员设计的VHDL语言程序的编译结果不需任何说明,都将存放在WORK库中。WORK库可以是设计者个人使用,也可提供给设计组多人使用。

库说明的语法结构

library 库名;

use 库名.程序包名.项目名;

###########################################################################################

实体说明

实体的电路意义相当于器件,在电路原理图上相当于握备局元件符号,他是完整的、独立的语言模块

实体说明语句的语法:

entity 实体名 is

port(端口1: 端口方式1 端口类型1;

端口2: 端口方式2 端口类型2;......);

end 实体名

端口方式有五种:

in 输入类型 信号从该端口进入实体

out 输出类型 信号从实体内部经该端口输出

inout 输入输出类型 信号既可以从该端口输入也可以输出

buffer 缓冲型 与out类似但在结构体内部可以作反馈

linkage 无制定方向,可以与任何方向的信号连接

############################################################################################

结构体说明

结构体会给模块的具体实现,指定输入与输出之间的行为。

结构体语法如下:

architecture 结构体名称 of 实体名 is

结构体说明部分;

begin

结构体并行语句部分;

end 结构体名称;

结构体说明:对结构体内部所使用的信号、常数、数据类型和函数进行定义。

结构体并行语句:具体确定各个输入、输出之间的关系,描述了结构体的行为,是一组并行处理语句。

结构体对实体的输入输出关系可以用3中方式进行描述,即行为描述(基本设计单元的数学模型描述)、寄存器传输描述(数据流描述)、和结构描述(逻辑元器件连接描述)。不同的描述方式,只体现在描述语句上,而框架是完全一样的

一开头 应该要有library ieee

接着就要包括你程序中要用到的库,比如说最经常的use ieee.std_logic_1164.all

接着是实体返散备entity,通俗点就是所对应的输入输出端口

最后是结构体architecture ,,就是你要实掘洞现的功能

结构体中还经常包括进程process,但不是一定要包括进程的,进程语句是在有用到顺序语句,比如说If else case when的时候就得用上

必不可少的部分就漏毁是头文件library ieee要用到的库,实体,结构体

VHDL系统设计的基本点:

(1)与其他硬件描述语言相比,VHDL具有以下特点:

(2)功能强大、设计灵活。

(3)强大的系统硬件描述能力。

(4)易于共享和复用。

2.举例说明FPGA是如何通过查找表实现其逻辑功能的?

参考答案:在计算机科学中,查找表是用简单的查询 *** 作替换运行时计算的数组或者 associative array 这样的数据结构。由于从内存中提取数值经常要比复杂的计算速度快很多,所以这样得到的速度提升是很显著的。

一个经典的例子就是三角表。每次计算所需的正弦值在一些应用中可能会慢得无法忍受,为了避免这种情况,应用程序可以在刚开始的一段时间计算一定数量的角度的正弦值,譬如计算每个整数角度的正弦值,在后面的程序需要正弦值的时候,使用查找表从内存中提取临近角度的正弦值而不是使用数学公式进行计算。

在计算机出现之前,人们使用类似的表格来加快手工计算的速度。非常流行的表格有三角、对数、统计 density 函数。另外一种用来加快手工计算的工具是滑动计算尺。

一些折衷的方法是同时使用查找表和插值这样需要少许计算量的方法,这种方法对于两个预计算的值之间的部分能够提供更高的精度,这样稍微地增加了计算量但是大幅度地提高了应用程序所需的精度。根据预先计算的数值,这种方法在保持同样精度的前提下也减小了查找表的尺寸/

在图像处理中,查找表经常称为LUT,它们将索引号与输出值建立联系。颜色表作为一种普通的 LUT 是用来确定特定图像所要显示的颜色和强度。

另外需要注意的一个问题是,尽管查找表经常效率很高,但是如果所替换的计算相当简单的话就会得不偿失,这不仅仅因为从内存中提取结果需要更多的时间,而且因为它增大了所需的内存并且破坏了高速缓存。如果查找表太大,那么几乎每次访问查找表都回倒置 cache miss,这在处理器速度超过内存速度的时候愈发成为一个问题。在编译器优化的 rematerialization 过程中也会出现类似的问题。在一些环境如Java 编程语言中,由于强制性的边界检查带来的每次查找的附加比较和分支过程,所以查找表可能开销更大。

何时构建查找表有两个基本的约束条件,一个是可用内存的数量;不能构建一个超过能用内存空间的表格,尽管可以构建一个以查找速度为代价的基于磁盘的查找表。另外一个约束条件是初始计算查找表的时间——尽管这项工作不需要经常做,但是如果耗费的时间不可接受,那么也不适合使用查找表。

[编辑本段]

例子

[编辑本段]

计算正弦值

许多计算机只能执行基本的算术运算,而不能直接计算给定值的正弦值,它们使用如下面泰勒级数(en:Taylor series)这样的复杂公式计算相当高精度的正弦值:

(x 接近 0)

然而,这样的计算费用可能是非常大的,尤其是在低速的处理器上。有许多的应用程序,尤其是传统的计算机图形每秒需要几千次的正弦值计算。一个常用的解决方案就是在刚开始计算许多均匀分布数值的正弦值,然后在表中查找最接近所需 x 的正弦值,这个值非常接近于正确的数值,这是因为正弦函数是一个有限变化率的连续函数。例如:

real array sine_table[-1000..1000]

for x from -1000 to 1000

sine_table[x] := sine(x/1000/pi)

function lookup_sine(x)

return sine_table[round(x/1000/pi)]

Image:Interpolation example linear.png

部分正弦函数的线性插值不幸的是,查找表需要一定的空间:如果使用 IEEE 双精度浮点数的话,将会需要 16,000 字节。如果使用较少的采样点,那么精度将会大幅度地下降。一个较好的解决方案是线性插值,在表中待计算点左右两侧两个点的值之间连直线,这个点对应的直线上的值就是所计算点的正弦值。这种方法计算速度也很快,对于如正弦函数这样的平滑函数来说也有更高的精度。这里是使用线性插值的一个例子:

function lookup_sine(x)

x1 := floor(x/1000/pi)

y1 := sine_table[x1]

y2 := sine_table[x1+1]

return y1 + (y2-y1)*(x/1000/pi-x1)

当使用插值的时候,可以得益于不均匀采样,也就是说在接近直线的地方,使用较少的采样点,在变化较快的地方使用较多的采样点以最大限度地接近实际的曲线。更多的信息请参考插值。

[编辑本段]

计算 1 的位数

population function。例如,数字 37 的二进制形式是 100101,所以它包含有三个设置成 1 的位。一个计算 32 位整数中 1 的位数的简单c语言程序是:

int count_ones(unsigned int x) {

int i, result = 0

for(i=0i<32i++) {

result += x &1

x = x >>1

}

return result

}

不幸的是,这个简单的算法在现代的架构上将需要数以百计的时钟周期才能完成,这是因为它造成了许多分支和循环,而分支的速度是很慢的。这可以使用 loop unrolling 和其它一些聪明的技巧进行改进,但是最简单快捷的解决方案是查找表:简单地构建一个 包含每个字节可能值包含的 1 的个数的256 个条目的表。然后使用这个表查找整数中每个字节包含的 1 的个数,并且将结果相加。没有分支、四次内存访问、几乎没有算术运算,这样与上面的算法相比就可以大幅度地提升速度。

int count_ones(unsigned int x) {

return bits_set[x &255] + bits_set[(x >>8) &255]

+ bits_set[(x >>16) &255] + bits_set[(x >>24) &255]

}

[编辑本段]

硬件查找表

在数字逻辑中,n位查找表可以使用多路复用器来实现,它的选择线是 LUT 的输入,它的输入是常数。n 位 LUT 通过将布尔逻辑函数建模为真值表从而可以编码任意 n 位输入,这是编码布尔逻辑函数的一个有效途径,4 位 LUT 实际上是现代 FPGAs 的主要元件。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/12446378.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-23
下一篇2023-05-23

发表评论

登录后才能评论

评论列表(0条)

    保存