信号与变量
VHDL提供了信号(signal)和变量(variable)两种对象来处理非静态数据,同时提供了常数(constant)和属性(generic)两种对象来处理静态数据
常量和信号是全局的,既可以用在顺序执行的1代码中,也可以用在并发执行的代码中。
变量是局部的,只能用在顺序代码中(包括process,function或procedure的内部),并且他们的值不能直接向外传递。
常量
--格式
CONSTANT 常量名: type := 值;
--例
constant set_bit: bit := '1';
constant datamemory : memory := (('0','0','0','0'),
('0','0','0','1'),
('0','0','1','1'));
常量可以在包集,实体或结构体中声明。在包集中声明的常量是真正全局的,可以被所有调用该包集的实体使用。定义在实体中的常量对于该实体全部结构体而言是全局的。定义在结构体内的常量仅在结构体内是全局的。
信号
VHDL中的信号代表的是逻辑电路中的“硬”连线,既可以用于电路单元的输入输出端口,也可以用电路内各单元之间的连接。实体中的所有端口都被默认为信号。
--格式
SIGNAL name: type [range] [:= initial_value];
--例
signal control: bit := '0'; --对信号赋初值的操作不可综合,只能用来仿真
signal count: integer range 0 to 100;
signal y: std_logic_vector (7 downto 0);
对于信号,赋值符号为<=
当信号用在顺序描述语句(如process内部)时,其值不是立刻更新的,信号值是在相应的进程,函数或过程完成之后才进行更新。
变量
与信号和常量相比,变量仅用于局部电路的描述。它只能在process,function或procedure内部使用,而且它是立即生效的,所以新的值可以在下一行代码中立即使用。
--格式
VARIABLE name: type [range][:= 初始值];
--例
variable control: bit := '0'; --与信号相同,对变量赋初值的操作不可综合,只能用在仿真中
variable count: integer range 0 to 100;
variable y: std_logic_vector (7 downto 0) := "10001000";
对于变量,赋值符号为:=
信号和变量的比较
信号 | 变量 | |
赋值符号 | := | |
功能 | 表示电路内部连接 | 表示局部信息 |
范围 | 全局 | 局部(仅在进程,函数或过程中使用) |
行为 | 在顺序代码中,信号值不是立即更新的,更新要在进程,函数或过程完成之后才有效 | 即使更新(新的值在代码的下一行就生效) |
用途 | 由于包集,实体或结构体中。在实体中,所有端口默认为信号 | 仅用于描述代码中(进程,函数或过程中) |
寄存器的产生
当一个信号的赋值是以另一个信号的跳变为条件时,或者说当发生同步赋值时,该信号经过编译后就会生成寄存器。这样的同步赋值只能在进程,函数或过程中出现(一般跟在IF signal'EVENT...或WAIT UNTIL...等语句之后)。如果变量的值没有被进程(函数或过程)以外的代码调用,那么不一定会生成寄存器。如果一个变量是在一个信号跳变时被赋予的,并且该值最终又被赋给了另外的信号(信号是全局的,可以进行数值传递),那么综合后就会产生寄存器。如果一个变量在还没有进行赋值操作时已被使用,那么在综合时也会产生寄存器。
--------例1--------
process(clk)
begin
if(clk'event and clk = '1')then
output1 <= temp; --output1被存储,因为它是信号(clk)跳变时被赋值的
output2 <= a; --output2被存储,因为它是信号(clk)跳变时被赋值的
end if;
end process;
--------例2--------
process(clk)
begin
if(clk'event and clk = '1')then
output1 <= temp; --output1被存储,因为它是信号(clk)跳变时被赋值的
end if;
output2 <= a; --output2未被存储
end process;
--------例3--------
process(clk)
variable temp: bit;
begin
if(clk'event and clk = '1')then
temp := a;
end if;
x <= temp; --temp促使x被存储
end process;
实例
下面将展示两端代码,代码实现相同的功能,但是综合后产生的触发器数量不同
-----------------方案1,综合后的电路为图a---------------------
library ieee;
use ieee.std_logic_1164.all;
entity dff is
port(d, clk: in std_logic;
q: buffer std_logic;
qbat: out std_logic);
end dff;
architecure two_dff of dff is
begin
process(clk)
begin
if (clk'event and clk = '1')then
q <=d ; --此处产生一个寄存器
qbar <= not d; --此处产生一个寄存器
end if;
end process;
end two_dff;
-----------------方案2,综合后的电路为图b---------------------
library ieee;
use ieee.std_logic_1164.all;
entity dff is
port(d,clk: in std_logic;
q: buffer std_logic;
qbar: out std_logic);
end dff;
architecture one_dff of dff is
begin
process(clk)
begin
if(clk'event and clk = '1')then
q <= d; --此处产生一个寄存器
end if;
end process;
qbar <= not q; --此处产生一个逻辑门而非寄存器
end one_dff;