数电 vhdl速成
vhdl速成
速成用,省略了很多。
注意,实体名要与文件名一致。
文章目录
- vhdl速成
- 1. 简介
- 1. 端口模式
- 2. 标识符
- 3. 数据对象
- 4. 数据类型
- 5. 操作符
- 2. 基本语句
- 1. 转向控制语句
- 2. 七段数码管
- 3. 信号属性函数event
- 4. 边沿JK触发器
1. 简介
VHDL结构包含实体,结构体,配置(configuration),程序包和库五部分。
实体是一个设计对象的表层设计单元,对这个设计对象与外部电路进行接口描述。
结构体用于描述设计对象的内部结构以及实体端口间的逻辑关系。
-- 相关库和软件包 library and package
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL; --库名.程序包名.项目名
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
-- 实体 entity
ENTITY e_name is -- 实体名与文件名相同
PORT( --端口
in1,in2,in3: IN STD_LOGIC;
out1,out2: OUT STD_LOGIC --注意这里没分号
);
END ENTITY e_name;
-- 结构体 architecture
ARCHITECTURE ar_name of e_name is
--这里写说明语句
BEGIN --下面写功能描述语句
out1 <= in1 and in2; --赋值
out2 <= in1 or in3;
END ARCHITECTURE ar_name;
1. 端口模式
端口方向 | 含义 | 端口方向 | 含义 |
---|---|---|---|
in | 输入 | inout | 双向 |
out | 输出 | buffer | 带反馈功能的输出 |
2. 标识符
标识符必须英文字母开头,不区分大小写,有效字符包括英文字母,数字0-9,下划线。
siganl a,b,c:bit_vector(0 to 7);
signal z:bit;
z<=b(3); -- 标识符(表达式)
c(0 to 3)<= a(4 to 7); --以段的方式赋值
表达式的数值必须在数组元素下标范围内,且是可计算的。to表示从低到高,downto表示从高到低(区间左右都是闭合的)。
3. 数据对象
数据对象有三种:常量,变量,信号。
变量是一个局部量,只能在进程和子程序中使用,赋值属于立即赋值。
信号作为电路中的信号连线,使用和定义的范围是实体,结构体和程序包。在进程和子程序中不能定义,但在进程中可以使用,其赋值算是进程最后赋值。
constant 常量名:数据类型:=表达式;
variable 变量名:数据类型[:=初值];
变量名 := 表达式; --变量立即赋值
signal 信号名:数据类型[:=初始值];
signal s1:STD_LOGIC :=0;--定义一个标准逻辑位的单值信号s1,初始值为低电平
signal s2,s3:bit;--定义两个数据信号
process(a,b,c,d) --进程
begin
d<=a;x<=b+d;d<=c;y<=b+d;
--信号量的赋值将进程语句最后带入的值作为最终值
--x<=b+c;y<=b+c;
end process;
4. 数据类型
预定义数据类型
数据类型 | 说明 |
---|---|
boolean | 布尔类型,取值true和false |
bit | 位数据类型 |
bit_vector | 位矢量类型signal a:bit_vector(0 to 7) |
character | 字符类型,区分大小写 |
integer | 整数类型,-(231-1)~(231-1),variable sum:integer range 0 to 13; |
natural | 自然数类型,0和正整数 |
real | 实数类型 |
string | 字符串类型variable str:string(1 to 4); |
time | 时间类型 |
IEEE预定义数据类型
在IEEE的STD_LOGIC_1164中定义了两个非常重要和常用的数据类型,即标准逻辑位STD_LOGIC
和标准矢量STD_LOGIC_VECTOR
。
STD_LOGIC定义为type STD_LOGIC('U','X','0','1','Z','W','L','H','-')
各值的含义分别是
U-未初始化的 X-强未知的 0-强0 1-强1 Z-高阻态 W-弱未知的
L-弱0 H-弱1 -
-忽略
其中只有0,1,Z,-
可以综合,其他只对仿真有意义。
STD_LOGIC_VECTOR只有同位宽,同数据类型的矢量间才可进行赋值。
--多人表决部分代码
...
port(
vt:in STD_LOGIC_VECTOR(13 downto 1);
result:out STD_LOGIC
);
...
process(vt)
variable sum:integer range 0 to 13;
begin
sum:=0;
for i in 1 to 13 loop
if (vt(i)='1') then
sum:=sum+1;
if sum>=7 then
result <='1';
else
result<='0';
end if;
end if;
end loop;
...
5. 操作符
* * | 乘方 |
---|---|
& | 对一维数组并置 |
abs | 求绝对值 |
rem | 求余 |
SLA | 算数左移 |
SRA | 算数右移 |
= | 等于 |
/= | 不等于 |
nand | 逻辑与非 |
nor | 或非 |
xor | 异或 |
xnor | 同或 |
SLL | 逻辑左移 |
SRL | 逻辑右移 |
ROR | 循环右移 |
ROL | 循环左移 |
2. 基本语句
感觉顺序语句和并行语句有部分重了,应该不影响设计。
顺序语句只能出现在进程(process)和子程序(过程procedure和函数function)中。
顺序语句一般包括赋值语句,转向控制语句,wait,null,return,子程序调用语句。
return;--用于结束过程process,不带返回值
return 表达式; --用于结束函数,必须带返回值
null;
并行语句在结构体中的执行是同步进行的,执行方式与书写顺序无关。
并行语句一般包括并行信号赋值(不能写在进程中),进程语句,并行过程调用语句,并行断言语句,元件例化语句,生成语句,块语句。
并行信号赋值分为简单信号赋值,条件信号赋值和选择信号赋值。
信号名 <= 表达式; --简单信号赋值
信号名 <= 表达式1 when 条件1 else --条件信号赋值
表达式2 when 条件2 else
表单式3;
with 选择表达式 select --选择信号赋值
信号名 <= 表达式1 when 选择值1,
表达式2 when 选择值2,
表达式3 when 选择值3;
1. 转向控制语句
转向控制语句一共五种:if,case,loop,next,exit。
if ... then ...; elsif ... then ...; else ...; end if;
case ... is when ...=>...; when ...=>...; when others =>...; end case;
for ... in ... loop ... ; end loop;
while ... loop ...; endloop;
next; --相当于C语言的continue
exit; --相当于C语言的break
2. 七段数码管
-- 相关库和软件包 library and package
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
-- 实体 entity
ENTITY e_name is -- 实体名与文件名相同
PORT(
en: IN STD_LOGIC; -- 使能端
dat:in std_logic_vector(3 downto 0);
display:out std_logic_vector(7 downto 0) --这里没分号
);
END ENTITY e_name;
-- 结构体 architecture
ARCHITECTURE shumaguan of e_name is
BEGIN
process(en,dat) -- 七段数码管
begin
if en='1' then
display<="ZZZZZZZZ"; --高阻态
else
case dat is
when "0000" =>display<="11111100"; -- 数组用双引号
when "0001" =>display<="01100000";
when "0010" =>display<="11011010";
when "0011" =>display<="11110010";
when "0100" =>display<="01100110";
when "0101" =>display<="10110110";
when "0110" =>display<="10111110";
when "0111" =>display<="11100100";
when "1000" =>display<="11111110";
when "1001" =>display<="11110110";
when others => display <="00000000";
end case;
end if;
end process;
END ARCHITECTURE shumaguan;
分离器byte_splitter
library ieee;
use ieee.std_logic_1164.all;
entity byte_splitter is
port(
byte_in : in std_logic_vector(7 downto 0); -- 输入的8位字节
bit0 : out std_logic; -- 输出的最低位
bit1 : out std_logic;
bit2 : out std_logic;
bit3 : out std_logic;
bit4 : out std_logic;
bit5 : out std_logic;
bit6 : out std_logic;
bit7 : out std_logic -- 输出的最高位
);
end byte_splitter;
architecture Behavioral of byte_splitter is
begin
bit0 <= byte_in(0);
bit1 <= byte_in(1);
bit2 <= byte_in(2);
bit3 <= byte_in(3);
bit4 <= byte_in(4);
bit5 <= byte_in(5);
bit6 <= byte_in(6);
bit7 <= byte_in(7);
end Behavioral;
四路输入合成一路
library ieee;
use ieee.std_logic_1164.all;
entity four_to_one_vector is
port(
in0 : in std_logic; -- 第一路输入
in1 : in std_logic; -- 第二路输入
in2 : in std_logic; -- 第三路输入
in3 : in std_logic; -- 第四路输入
out_vector : out std_logic_vector(3 downto 0)-- 4位宽的vector输出
);
end four_to_one_vector;
architecture Behavioral of four_to_one_vector is
begin
out_vector <= in0 & in1 & in2 & in3; -- 使用&操作符组合输入到vector中
end Behavioral;
3. 信号属性函数event
vhdl中专门用于检测时钟信号的表达式clk'event and clk ='1'
,它由信号名和信号属性函数event组成。
时钟检测表达式 | 功能及注解 |
---|---|
信号名’event and 信号名=‘1’ RISING_EDGE(信号名) | 信号出现上升沿(信号发生正跳变)时为TRUE,否则为FALSE |
信号名’event and 信号名=‘0’ FALSE_EDGE(信号名) | 信号出现下降沿(信号发生负跳变)时为TRUE,否则为FALSE |
4. 边沿JK触发器
RDN为低电平有效的异步置0端,SDN为低电平有效的异步置1端,C1端带非门则下降沿触发,不带非门则上升沿触发。
下面展示不带非门的边沿jk触发器。
-- 相关库和软件包 library and package
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
-- 实体 entity
ENTITY myjkff is -- 实体名与文件名相同
PORT(
clk,j,k,rdn,sdn: IN STD_LOGIC;
q:buffer STD_LOGIC --若buffer不支持,可以在结构体里定义一个信号,对信号操作最后把信号赋值给q
);
END ENTITY myjkff;
-- 结构体 architecture
ARCHITECTURE bhv of myjkff is
BEGIN
process(clk,rdn,sdn)
begin
if rdn='0' then
q<='0';
elsif sdn='0' then
q<='1';
elsif (clk'event and clk='1') then --上升沿跳变
if (j='1' and k='0') then
q<='1';
elsif (j='0' and k='1') then
q<='0';
elsif (j='1' and k='1') then
q <= not q;
else
q <=q;
end if;
end if;
end process;
end ARCHITECTURE bhv;