1.信号
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity xor_sig is
Port ( A : in STD_LOGIC;
B : in STD_LOGIC;
C : in STD_LOGIC;
X : out STD_LOGIC;
Y : out STD_LOGIC);
end xor_sig;
architecture Behavioral of xor_sig is
signal D: STD_LOGIC;
begin
SIG:process (A,B,C)
begin
D <= A; -- ignored !!
X <= C xor D;
D <= B; -- overrides !!
Y <= C xor D;
end process;
end Behavioral;
2.变量
等效的逻辑图是这样的:
显然,综合器将信号A给忽略了,这跟我们希望的是不一致的.仔细观察综合过程发现,在综合时会产生一条WARNING:
Input is never used. This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved.
大意是说输入从未使用,如果是顶层程序或者属于一个子模块并且该子模块有这个端口时,会被保留,其余情况下端口会被忽略掉.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity xor_sig is
Port ( A : in STD_LOGIC;
B : in STD_LOGIC;
C : in STD_LOGIC;
X : out STD_LOGIC;
Y : out STD_LOGIC);
end xor_sig;
architecture Behavioral of xor_sig is
begin
VAR:process (A,B,C)
variable D: STD_LOGIC;
begin
D := A;
X <= C xor D;
D := B;
Y <= C xor D;
end process;
end Behavioral;
这段程序的本意与上面是一样的:X <= A xor C; Y <= B xor C.在利用ISE 10.1综合以后得到的结果如下图:
等效的逻辑图是这样的:
在一个进程中,如果对一个信号多次复制,那么,只有最后一个值才是有效的。如果对变量多次赋值,那么每次赋值都是有效的,
并且,变量的值在再次赋值之前一直保持不变。信号跟硬件有点类似,并且是在进程结束的时候才更新;变量是立即更新的,因此
可以影响程序的功能,但变量的好处是仿真速度更快。
基于以下几点原因,我们建议,编程时还是应以信号为主,尽量减少变量的使用。
(1)变量赋值无延时是针对进程运行而言的,只是一个理想值,对于变量的操作往往被综合成为组合逻辑的形式,而硬件上的组合逻辑必然存在输入到输出延时。当进程内关于变量的操作越多,其组合逻辑就会变得越大越复杂。假设在一个进程内,有关于变量的3个 级连操作,其输出延时 分别为5ns,6ns,7ns,则其最快的时钟只能达到18ns。相反,采用信号编程,在时钟控制下,往往综合成触发器的形式,特别是对于FPGA芯片而言,具有丰富的触发器结构,易形成流水作业,其时钟频率只受控于延时最大的那一级,而不会与变量一样层层累积。假设某个设计为3级流水作业,其每一级延时分别为10ns,11ns,12ns,则其最快时钟可达12ns。因此,采用信号反而更能提高设计的速度。
(2)由于变量不具备信息的相关性,只有当前值,因此也无法在仿真时观察其波形和状态改变情况,无法对设计的运行情况有效验证,而测试验证工作量往往会占到整个设计70%~80%的工作量,采用信号则不会存在这类问题。
(3)变量有效范围只能局限在单个进程或子程序中,要想将其值带出与其余进程、子模块之间相互作用,必须借助信号,这在一定程度上会造成代码不够简洁,可读性下降等缺点。
4.实际应用
使用变量
process(INTClk ,GPIO8)
begin
if (GPIO8 = '1') then
INTState <= X"0";
counter <= X"00000000";
elsif (INTClk'event and INTClk = '1') then
counter <= counter + 1;
case INTState is
when X"0" => IRQ7 <= '1';
if counter > X"72BF00" then-- (94ms)
counter <= X"00000000";
INTState <= X"1";
else
INTState <= X"0";
end if;
when X"1" => IRQ7 <= '0';
if counter > X"3A" then
coun ter <= X"00000000";
INTState <= X"0";
else
INTState <= X"1";
end if;
when others => null;
end case;
end if;
end process;
注意:counter<=counter+1;的位置顺序一定要放counter复位前。
使用变量
process(INTClk ,GPIO8)
variable counter : std_logic_vector(31 downto 0);
begin
if (GPIO8 = '1') then
INTState <= X"0";
counter := X"00000000";
elsif (INTClk'event and INTClk = '1') then
case INTState is
when X"0" => IRQ6 <= '1';
--if counter > X"70F760" then--7403360
if counter > X"50" then--7403360
INTState <= X"1";
counter := X"00000000";
else
INTState <= X"0";
end if;
when X"1" => IRQ6 <= '0';
--if counter > X"E380" then --58240
if counter > X"10" then --58240
counter := X"00000000";
INTState <= X"0";
else
INTState <= X"1";
end if;
when others => null;
end case;
counter := counter + 1;
end if;
end process;