我正在尝试为我的一个课程中的最终项目制作一个闹钟。我正在使用DE1 Altera板上的按钮手动增加小时和分钟。分钟工作,但我无法手动增加时间。所有引脚分配都是正确的。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity ClkMain is port (
clk,pb_hr,pb_min,clk_set,almr_enbl: in std_logic;
almr_hr: in integer range 0 to 23;
almr_min: in integer range 0 to 59;
clk_min : out integer range 0 to 59;
clk_hr : out integer range 0 to 23;
almr_indct : out bit
);
end ClkMain;
architecture Behavioral of ClkMain is
signal sec, min: integer range 0 to 60 :=0;
signal hr: integer range 0 to 24 := 0;
begin
clk_min <= min;
clk_hr <= hr;
process(clk) --normal clock operation
begin
if(clk'event and clk='1') then
sec <= sec + 1;
if(sec + 1 = 60 or (pb_min = '1' and clk_set = '1') ) then
sec <= 0;
min <= min + 1;
if (min + 1 = almr_min and hr = almr_hr and almr_enbl = '1') then
almr_indct <= '1';
else
almr_indct <= '0';
end if;
if(min + 1 = 60 ) then
hr <= hr + 1;
min <= 0;
if(hr + 1 = 24) then
hr <= 0;
if (clk'event and clk='1' and pb_hr = '1' and clk_set = '1')then
hr <= hr + 1;
end if;
end if;
end if;
end if;
end if;
end process;
end Behavioral;
答案 0 :(得分:1)
您可以通过正确缩进来查看错误的位置:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_arith.all;
-- use ieee.std_logic_unsigned.all;
entity ClkMain is
port (
clk,pb_hr,pb_min,clk_set,almr_enbl: in std_logic;
almr_hr: in integer range 0 to 23;
almr_min: in integer range 0 to 59;
clk_min: out integer range 0 to 59;
clk_hr: out integer range 0 to 23;
almr_indct : out bit
);
end ClkMain;
architecture Behavioral of ClkMain is
signal sec, min: integer range 0 to 60 :=0;
signal hr: integer range 0 to 24 := 0;
begin
clk_min <= min;
clk_hr <= hr;
process(clk) --normal clock operation
begin
if clk'event and clk = '1' then
sec <= sec + 1;
if sec + 1 = 60 or (pb_min = '1' and clk_set = '1') then
sec <= 0;
min <= min + 1;
if min + 1 = almr_min and hr = almr_hr and almr_enbl = '1' then
almr_indct <= '1';
else
almr_indct <= '0';
end if;
if min + 1 = 60 then
hr <= hr + 1;
min <= 0;
if hr + 1 = 24 then
hr <= 0;
if clk'event and clk = '1' and pb_hr = '1' and clk_set = '1' then
hr <= hr + 1;
end if;
end if;
end if;
end if;
end if;
end process;
end Behavioral;
clk
条件包含在最外面的if语句中,并且没有必要:
if clk'event and clk = '1' and pb_hr = '1' and clk_set = '1' then
应该是
if pb_hr = '1' and clk_set = '1' then
这让我们知道了什么是错的。 pb_hr
仅在晚上11点进行评估:
if hr + 1 = 24 then
hr <= 0;
if pb_hr = '1' and clk_set = '1' then
hr <= hr + 1;
end if;
end if;
这两个if语句至少需要处于相同的嵌套级别。
不幸的是,它还会让你查看if语句的嵌套级别,你注意到你只能在23:59:59设置小时,或者你还要按住pb_min
和{{1是真的。
另请注意,无论您做什么,clk_set
都是正确的。我建议将具有时钟条件的封闭if语句移动到集合和警报检测之外(将它们保持在相同的过程中)。当almr_indct
为真时,它也应该无效。
再往前看:
clk_set
我们看到按钮按下可以达到60。这一切都需要修复。它也可以在计数器外部移动警报比较,并在时钟设置期间禁用。
所以你可以操纵流程声明:
if sec + 1 = 60 or (pb_min = '1' and clk_set = '1') then
sec <= 0;
min <= min + 1;
有机会我修改了architecture foo of clkmain is
signal sec, min: integer range 0 to 59 := 0;
signal hr: integer range 0 to 23 := 0;
signal sec_neq_59: std_logic;
signal min_neq_59: std_logic;
signal hr_neq_23: std_logic;
begin
clk_min <= min;
clk_hr <= hr;
sec_neq_59 <= '0' when sec = 59 else '1';
min_neq_59 <= '0' when min = 59 else '1';
hr_neq_23 <= '0' when hr = 23 else '1';
CLOCK_PROCESS:
process(clk)
begin
if clk'event and clk = '1' then
ALARM_INDICATON:
if min = almr_min and hr = almr_hr and almr_enbl = '1' then
almr_indct <= to_bit(not clk_set);
else
almr_indct <= '0';
end if;
SET_MINUTES:
if pb_min = '1' and clk_set = '1' then
if min_neq_59 = '1' then
min <= min + 1;
else
min <= 0;
end if;
SET_HOURS:
elsif pb_hr = '1' and clk_set = '1' then
if hr_neq_23 = '1' then
hr <= hr + 1;
else
hr <= 0;
end if;
INCREMENT_SECONDS:
elsif sec_neq_59 = '1' then
sec <= sec + 1;
else -- sec = 59
sec <= 0;
INCREMENT_MINUTES:
if min_neq_59 = '1' then
min <= min + 1;
else -- :59:59
min <= 0;
INCREMENT_HOURS:
if hr_neq_23 = '1' then
hr <= hr + 1;
else -- 23:59:59
hr <= 0;
end if;
end if;
end if;
end if;
end process;
end architecture foo;
,sec
和min
计数器的范围。秘密是在递增之前进行评估,您可以使用同步负载拦截终端计数。
还切换到与特定值进行相等比较,将它们分开以通过使用elsif设置一组并通过时钟操作优先按下按钮来减少硬件。
所以现在按钮不会在几分钟和几小时内造成范围错误,并且与实际时钟时间无关。
我不认为使用按钮递增分钟时重置秒数是有效的。当clock_set为真时,将秒保持为0可能是有效的,这将在设置时停止运行时钟。但是,如果您只修复夏令时或更改时区,那么这不起作用。
我还没有模拟过这个。它分析和阐述。分配中的范围误差将在模拟过程中显示。
我将hr
作为类型位,但确实使用almr_indct
作为警报指示的条件。