写在前面
HDL是硬件语言,我没有学过硬件语言,我很感兴趣。 另外,也可以用于小组的实验。 花了时间学习和整理了VHDL的基本语法,使之容易看到。 这个blog中使用的所有图像都是
VHDL语言的基本语法参考文档
一、VHDL语言基本语法1、VHDL语言书写
2、VHDL的数字2.1数字型字符156E2的含义为156(times10210^2102;
下划线可以连接数字。
2.2以数字基数表示的字符
2.3字符串型字符
2.4下标和下标
downto和to有什么区别
例如,向生命提供长度为8的向量的信号
signals 1: STD _ logic _ vector (7向下到0 ); 该生成的排列下标的值从右开始依次为7、6、5、4、3、2、1、0
signals 2: STD _ logic _ vector (0to 7; 该生成的数组的下标值从右开始依次为0、1、2、3、4、5、6、7
所以区别只是显示方向不同。
二、VHDL语言的数据对象1、常量
2、变量
3、信号(信号)。
三. VHDL的数据类型
1、VHDL预定义的数据类型
1.1布尔(布尔)。
1.2位(位)。
1.3位向量(BIT_VECTOR ) )
1.4个字符(tdhmgsjx ) )。
1.5整数(整数) )
1.6实数(真)
1.7字符串(字符串)
1.8小时(时间)数据类型
1.9错误级别(SEVERITY_LEVEL ) )。
2、IEEE预定义标准逻辑位和向量
2.1标准逻辑位STD_LOGIN数据类型
2.2标准逻辑向量(STD_LOGIC_VECTOR )。
2.3其他预定义的标准数据类型
(1)无符号数据类型(未指定类型) )。
(2)有符号数据类型(SIGNED TYPE ) )。
2.4用户定义的数据类型方法
)1) TYPE语句的使用方法
)2) SUBTYPE语句的使用方法
)3)枚举类型
)4)数组类型
)5)记录类型
)6)数据类型转换
四、VHDL In Quartus 一章中的部分参考旁边朋友hayroc的笔记,方便放在一起看。
1、VHDL入门(1) VHDL设计配置;库和软件包(libary,package ) ) ) )。
实体(实体) )
结构(architecture )
配置(配置)
通俗地说:
库和包-材料、工具箱
实体-硬件外部接口
结构-硬件内部的具体实现
)2)语法实体
实体名称is generic (定名:数据类型:初始值)端口信号名称:数据类型)用end实体名称结构体) vhdl语句描述实体的具体操作和逻辑功能
architecture结构体名称of实体名称is说明部分(可选,数据类型常数constand信号signal元件component过程pocedure变量variable和过程process等(begin功能说明部分end结构体名称33333333
if条件then --do something; else if条件then --do something; else --do something; 结束If;逻辑
for x in 0 to n loop --do something; 结尾环路;
g>运算符赋值运算:
<= 信号赋值
:= 变量赋值
=> 数组内部分元素赋值
逻辑运算:
not 非
and 与
or 或
nand 与非
nor 或非
xor 异或
注意:对数组类型,参与运算的数组位数要相等,运算为对应位进行
算术运算:
+ 加
- 减
* 乘
/ 除
mod 模
rem 取余
** 指数
abs 绝对值
注意:尽量只使用加减
关系运算:
=> 大于等于
<= 小于等于
大于
< 小于
/= 不等于
= 等于
连接运算:
& 连接运算结果为同类型构成的数组
注意:从本质上讲,VHDL代码是并发执行的。只有PROCESS,FUNCTION或者PROCEDURE内部的代码才是顺序执行的。值得注意的是,尽管这些模块中的代码是顺序执行的,但是当它们作为一个整体是,与其他模块之间又是并发的。IF,WAIT,CASE,LOOP语句都是顺序代码,用在PROCESS,FUNCTION和PROCEDURE内部。
2、代码实例 (1)半加器 --halfadderlibrary ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity halfadder is port(a, b : in std_logic; s, c : out std_logic --s -> sum, c -> carry );end halfadder;architecture f_halfadder of halfadder is begin s <= a xor b; c <= a and b;end f_halfadder; (2)一位全加器 --fulladderlibrary ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity fulladder is port(a, b, c0 : in std_logic; s, c1 : out std_logic );end fulladder;architecture f_fulladder of fulladder is begin s <= a xor b xor c0; c1 <= (a and b) or (c0 and (a xor b)); end f_fulladder; (3)四位加法器 --add4library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity add4 is port(a, b : in std_logic_vector(3 downto 0); s : out std_logic_vector(3 downto 0); c0 : in std_logic; c1 : out std_logic );end add4;architecture f_add4 of add4 is begin --模拟手算加法 process(a, b, c0) variable t : std_logic; begin t := c0; for x in 0 to 3 loop s(x) <= a(x) xor b(x) xor t; t := (a(x) and b(x)) or (t and (a(x) xor b(x))); end loop; c1 <= t; end process;end f_add4; (4)四位不带符号乘法器直接使用 ”+“ 号要结果的存储要多加一位。
---mul4library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity mul4 is port(n0, n1 : in std_logic_vector(3 downto 0); a0 : out std_logic_vector(7 downto 0) ); end mul4;architecture f_mul4 of mul4 is signal t0, t1, t2, t3 : std_logic_vector(3 downto 0);begin process(n0, n1, t0, t1, t2, t3) begin --模拟手算乘法 if n1(0) = '1' then t0 <= n0; else t0 <= "0000"; end if; if n1(1) = '1' then t1 <= n0; else t1 <= "0000"; end if; if n1(2) = '1' then t2 <= n0; else t2 <= "0000"; end if; if n1(3) = '1' then t3 <= n0; else t3 <= "0000"; end if; a0 <= ("0000" & t0) + ("000" & t1 & '0') + ("00" & t2 & "00") + ('0' & t3 & "000"); end process;end f_mul4; (5)五位带符号数的补码阵列乘法器最后的原理图。
comp4(四位求补器)
mult_array(四位乘法阵列)
--这里实现的是没有符号的乘法阵列library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity mult_array isport(num1, num2: in std_logic_vector(3 downto 0); -- num1是被乘数,舗um2是成乘数 res : out std_logic_vector(7 downto 0); test: out std_logic_vector(7 downto 0));end mult_array;architecture f_mult_array of mult_array isTYPE mult_array is Array(3 downto 0) of std_logic_vector(6 downto 0);Signal m: mult_array;beginprocess(m,num1,num2)Variable tmp_num2:std_logic_vector(3 downto 0);beginfor i in 0 to 3 loopm(i)<="0000000";if num2(i)='1' then m(i)(3+i downto i)<=num1(3 downto 0);end if;end loop;--test(7 downto 4 ) <= num2(3 downto 0);res<=('0' & m(0)) + ('0' & m(1)) + ('0' & m(2)) + ('0' & m(3));end process;end f_mult_array;comp8(八位求补器)
library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity comp8 is port (e, c0 : in std_logic;num : in std_logic_vector (7 downto 0);result : out std_logic_vector(7 downto 0));end comp8;architecture f_comp8 of comp8 isbeginprocess(num,e,c0)Variable tmp_ci:std_logic;begintmp_ci:='0';for i in 0 to 7 loopresult(i)<=(num(i) xor (tmp_ci and e));tmp_ci:=num(i) or tmp_ci;end loop;end process;end f_comp8; 3、Debug日志1、同一个项目文件有两个vhd文件时,如果要对不同的vhd文件进行仿真的话需要对先把要仿真的文件置于top entity,然后把这个文件编译一遍,这样才能在node finder里边找到对应的引脚。
2、信号的赋值操作只有在进程结束后才会进行,所以如果信号在进程内被多次赋值的话,只有最后一次赋值操作才会起作用,所以在进程内写算法一般都是用variable,signal和variable的区别具体可以看这篇blog => VHDL中信号与变量的区别及赋值的讨论
3、当自己制作的组件的某一个接口是一个数组,这时候要用总线连接,具体的连法可以看这篇blogquartus总线怎样连接
4、在用vhdl写组件的的时候,在定义process的时候,一定要把用到的input的端口写进porcess定义时的括号里边,否则可能导致的后果就是你把你写好的这个组件生成出来之后,结果永远对不上!
错误请指出,不定时更新,ths!
May you give me a like?