已经有几年没有接触过VDHL或者Verilog了,在大二时,对VHDL是如此的热爱,疯狂得不用看仿真只通过看代码就能知道问题所在,在那一年,我喜欢FPGA,喜欢了VHDL。
就在那一年,老师给我的项目失败了,可能是自己技术不到家(那时连SDRAM工作原理还不懂,却说要用VHDL实现SDRAM读写,当年还是有很多东西不了解,也没有自己的一套学习方法),为了不让老师失望,我决意转向ARM,从此,我与FPGA、VHDL失去了交集,渐渐地,我把VHDL遗忘了。。。。。
其中在那一年,虽然主攻VHDL,但对Verilog也有作过少许学习(毕竟Verilog学习资料多),只是随着时间的推移,Verilog与VHDL的转换已成为过去。
今年,我又有机会与VHDL产生交集,其实是我主动向上司要求,我想研究FPGA、VHDL,可以减轻团队的压力。
好了,费话了一堆。现在的我又要从头开始捡起VHDL了。
VHDL中的库文件包含:
在VHDL中,少不了一些标准库,如:std_logic这类声明,都是来源于ieee这个库的。
library ieee; use ieee.std_logic_1164.all;
VHDL中实体声明:
和高级语言一样,VHDL也要声明,这时有点不同的是,这种声明是用于对外的接口,即输入/输出都在这里声明的。
entity CRC_Unit is port( iBitVal : in std_logic; iClock : in std_logic; iClear : in std_logic; oCRC : out std_logic_vector(4 downto 0) ); end CRC_Unit;
VHDL结构功能:
有了对外的接口外,还得有内部的处理,这样才能算是一个整体。architecture 就是对实体的内部功能的描述。
architecture ClacCRC of CRC_Unit is signal inv : std_logic; signal CRC : std_logic_vector(4 downto 0); begin inv <= iBitVal xor CRC(4); process(iClock,iClear) begin if iClear = '1' then CRC <= (others =>'0'); elsif falling_edge(iClock) then CRC(4) <= CRC(3); CRC(3) <= CRC(2) xor inv; CRC(2) <= CRC(1); CRC(1) <= CRC(0) xor inv; CRC(0) <= inv; end if; end process; oCRC <= CRC; end ClacCRC;
到此,就把VHDL的结构简述完毕。
别急,我还没有说完,下面还会对各个部分进行分析。由于代码已经在上文给出,下文将不会再重复代码。
VHDL中的库
VHDL中的库有哪些?
std_logic_1164
std_logic_arith
std_logic_unsigned
std_logic_signed
除了系统自带的库外,自己也可以编写自己的,编写格式如下:
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; package PackageName is component Component1 is PORT ( ... ); end component; component Component2 is PORT ( ... ); end component; end package;
格式和写一个普通的VHDL文件差不多,不同的是,这个没有实体,也没有结构,只有包(component后面将描述)。
VHDL如何使用库?
库可以分为二大类,一类是系统自带的标准库,另一类的用户自己编写的,两种类调用方式不太一样。
上面代码讲到如何调用库,如果使用标准库,一般如下:
library ieee; --表示使用什么库 use ieee.std_logic_1164.all; --表示使用库中的具体的库
其中std_logic_1164是在ieee库中的,一般情况下,上而两行代码是必需的。
如果使用的是用户自编写库,就要:
use work.PackageName.all; --work表示当前工作目录
使用用户自编写的库看起来就简单多了,只要使用use就可以了,值得注意的是,work是指当前工作目录,而PackageName就是包的名字,前面的讲述到。
VHDL中的实体
VHDL中的实体就简单多了,主要是对引脚(或接口)的输入、输出或者双向作定义。
其中port();中的为对外引脚。
引脚分三种:
输入使用关键字:in
输出使用关键字:out
双向使用关键字:inout
对不同引脚要定义具体类型,引脚常用只有两种类型,一种是单点引脚,一种是多点引脚。(单点、多点引脚是我的说法,不一定正常,但能表示其意思)
单点引脚使用:std_logic
多点引脚使用:std_logic_vertor(x downto 0)
有点类似普通变量和数组变量,一个表示单线、一个表示集合了多条单线(类似总线)。
注:在port();中,最后一个引脚不要加分号!
VHDL中的architecture
在architecture中且在begin前声明
1、信号。信号如其名,就是传递信号用的。
2、组件(component),组件就是其他已经写好的VHDL,组件只是把其引脚复述一遍,用于后期数据处理。
architecture XXX of XXX_Unit is signal One:std_logic; --声明信号 component Component1 is --声明组件 port ( ... --具体一个实体的引脚 ); end component; begin ... end XXX;
组件是将一个已经写好的VHDL模块(实现某一功能的VHDL文件) ,加入本VHDL中的方式,但加入还不够,还要使用port map,下文将描述。
在architecture中且在begin后
在begin后常用的有语句不多,主要有if...else...end if,if...elsif...elsif...end if,process,port map等(这些语句能实现大部分逻辑)。
architecture XXX of XXX_Unit is component CRC_Unit is port( iBitVal : in std_logic; iClock : in std_logic; iClear : in std_logic; oCRC : out std_logic_vector(4 downto 0) ); end component; signal bitVal : std_logic; signal clock : std_logic; signal clr : std_logic; signal crc : std_logic_vector(4 downto 0); begin oOut <= One; process(rst) --敏感信号列表 begin if rst = '0' then ... elsif ... end if; end process; u1:CRC_Unit port map(iBitVal => bitVal ,iClock => clock ,iClear => clr ,oCRC =>crc); end XXX;
在VHDL中,只要在architecture中的语句都会被同时执行,但process一点特别,同时执行的是整个process,而不是process里面的各行语句。process其实更像是一个块,一个对外同时执行,对内顺序执行的一个单元。
在process的括号中的rst,被称为敏感信号列表,只要放在这括号中的数据发生变化,就会同时执行期间触发process内部操作。即oOut <= One、process及port map同时执行。
port map是将原来component进architecture的组件进行使用,port map 后,会将对应的信号输入或输出。
VHDL architecture中的变量
变量需要声明在process中,而且只能在process中被赋值,被调用。变量声明在process中begin前。
process(rst) variable val : integer ; begin val := 10; end process;
VHDL architecture中的赋值
VHDL中有两种赋值方式,一种是直接赋值,一种是延时赋值。还有一种不太像赋值,而是像指向的方式,port map (符号是"=>"),这里不把此方式当作赋值。
直接赋值:(赋值符号为":=" )
variable 就是直接的代表,当赋值后,左值将等于右值。
延时赋值:(赋值符号为"<=“ )
所有信号、引脚被赋值都是延时赋值。那什么是延时赋值?个人认为可以与实际电路理解(虽然不知是否正确)。信号可以看成一条线(引脚也是),当我在线的右端给出高电平的瞬间,左端的电平还没有变化,因为从右到左需要一定的时间(那时间是光速),所以在同一周期作出了操作,但信号的值还没有来得及改变,所以出现了延时赋值。
在VHDL中只有两种赋值操作,如果想和高级语言一样使用"="一般会出错,因为在VHDL中"="是比较操作。
总结:
由于边幅太长不利浏览,因此对VHDL、Verilog将以一个系列来讲述。局限于本人技术有限,可能上文会有表达不通,或者表达不清的情况,如果有看不懂的,或者找出错处的,欢迎大家提出。