这是我的代码,非常简单。我要在Altera Cyclone II板上循环显示字母表的前8个字母。
entity lettercycle is
port(
SW : in std_logic; -- toggle switch
HEX0 : out std_logic_vector(6 downto 0) -- 7-segment display
);
end lettercycle;
architecture behavioural of lettercycle is
signal counter : integer range 0 to 7 := 0;
begin
process
type SEGMENT_ARRAY is array (0 to 7) of std_logic_vector(6 downto 0);
variable SEVENSEG : SEGMENT_ARRAY := ("0001000","0000011","1000110","0100001","0000110","0001110","0010000","0001001");
begin
HEX0 <= SEVENSEG(counter);
wait until SW = '0';
counter <= counter + 1;
end process;
end behavioural;
这很好用,它循环但最初它在我的七段显示器上不显示“A”。它显示“8”(所以基本上没有)。一旦我按下逻辑0开关SW,它就会变为'A'并正确循环到'B','C'等。它也正确循环。它没做的是最初设置为'A'。如果我强迫
HEX0 <= SEVENSEG(0);
然后它会显示'A',所以我想出了主意。这可能与弹跳有关吗?
答案 0 :(得分:1)
综合工具使用下降沿触发器实现该过程
wait until SW = '0';
的结果,因此counter
和HEX0
都在里面
该过程在SW
的下降沿更新(因此HEX0
不是锁存器。)
然而,综合工具不会传播counter
的初始0值
基于HEX0
的映射,SEVENSEG
上的初始值,因此您不会获胜
看到最初的&#39; A&#39;在输出上。
合成输出如下图所示,其中触发器打开 输出也可以看出。
通过更新流程并HEX0
分配给:
process (SW) is
begin
if falling_edge(SW) then
counter <= counter + 1;
end if;
end process;
HEX0 <= SEVENSEG(counter);
这也将删除HEX0
输出中不必要的触发器。
请注意,SEVENSEG
将移至架构级别声明为常量。
答案 1 :(得分:1)
Morten对HEX0的下降治疗是对的。
另一种方法是将SEVENSEG声明为架构声明区域中的常量,并将分配从计数器(这是一个信号)移动到进程外的HEX0:
library ieee;
use ieee.std_logic_1164.all;
entity lettercycle is
port(
SW : in std_logic; -- toggle switch
HEX0 : out std_logic_vector(6 downto 0) -- 7-segment display
);
end lettercycle;
architecture behavioural of lettercycle is
signal counter : integer range 0 to 7 := 0;
type SEGMENT_ARRAY is array (0 to 7) of std_logic_vector(6 downto 0);
constant SEVENSEG : SEGMENT_ARRAY :=
("0001000","0000011","1000110","0100001",
"0000110","0001110","0010000","0001001");
begin
process
-- type SEGMENT_ARRAY is array (0 to 7) of std_logic_vector(6 downto 0);
-- variable SEVENSEG : SEGMENT_ARRAY :=
-- ("0001000","0000011","1000110","0100001",
-- "0000110","0001110","0010000","0001001");
begin
-- HEX0 <= SEVENSEG(counter);
wait until SW = '0';
if counter = 7 then
counter <= 0;
else
counter <= counter + 1;
end if;
end process;
HEX0 <= SEVENSEG(counter);
end behavioural;
library ieee;
use ieee.std_logic_1164.all;
entity lettercycle_tb is
end entity;
architecture foo of lettercycle_tb is
signal SW: std_logic := '1';
signal HEX0: std_logic_vector(6 downto 0);
begin
DUT:
entity work.lettercycle
port map (
SW => SW,
HEX0 => HEX0
);
STIMULUS:
process
begin
wait for 60 ms;
SW <= '0';
wait for 60 ms;
SW <= '1';
wait for 60 ms;
SW <= '0';
wait for 60 ms;
SW <= '1';
wait for 60 ms;
SW <= '0';
wait for 60 ms;
SW <= '1';
wait for 60 ms;
SW <= '0';
wait for 60 ms;
SW <= '1';
wait for 60 ms;
SW <= '0';
wait for 60 ms;
SW <= '1';
wait for 60 ms;
SW <= '0';
wait for 60 ms;
SW <= '1';
wait for 60 ms;
SW <= '0';
wait for 60 ms;
SW <= '1';
wait for 60 ms;
SW <= '0';
wait for 60 ms;
SW <= '1';
wait for 60 ms;
SW <= '0';
wait for 60 ms;
SW <= '1';
wait for 60 ms;
wait;
end process;
end architecture;
关于if counter = 7 then...
的位是因为整数&#34; +&#34;有它的数学意义,添加的输出可能超出范围,并给你一个讨厌的运行时消息:
ghdl -r lettercycle_tb --wave = lettercycle_tb.ghw
./lettercycle_tb:error:lettercycle.vhdl:29的绑定检查失败 ./lettercycle_tb:error:模拟失败ghdl:编译错误
这表示模拟可能会失败,并且应该鼓励对计数器和其他正在进行算术运算的值使用基于std_ulogic的数组值,这会有计数器翻转。 0到7的范围恰好适合3位,而在合成产品中,您期望反转。
现已撤销的IEEE Std 1076.6(寄存器传输级综合)中有验证方法的描述:
使用模拟验证综合结果的过程包括 将等效输入应用于原始模型和 合成模型然后比较它们的输出以确保它们 是等价的。在此上下文中的等价意味着综合工具 应产生一个在输入,输出和电路中等效的电路 模型的双向端口。由于合成一般不会 识别与模拟器相同的延迟,输出不能 在每个模拟时间进行比较。相反,它们只能进行比较 在所有瞬态延迟已经解决的特定模拟时间 并且已超出所有活动的超时子句。如果输出 在所有可比较的时间都不匹配,合成工具不应该 兼容。任何人都不得有任何匹配的要求 内部节点。
基本上,合成结果应该与VHDL模拟除了忽略元值事务之外的其他方式相匹配。所以你的综合结果尽可能多。
答案 2 :(得分:0)
这不是开关反弹问题(尽管您的设计很容易受到影响)。在你的设计中HEX0
是一个闩锁。您从未将其设置为初始值,这就是为什么它在指定初始状态为&#34; 0000000&#34;的工具中启动的原因。请注意,这不是VHDL的固有属性,它可以用&#34; UUUUUUU&#34; (所有未初始化的)在模拟中,但在实际硬件中实现9值逻辑时,综合工具会有一些自由。
SEVENSEG
不需要变量,因此您可以将其转换为体系结构级别常量,并将赋值转换为HEX0
到流程外的连续赋值,作为一种简单的方法它按照需要启动。