vhdl手动时钟小时设置

时间:2014-11-29 22:10:06

标签: vhdl clock intel-fpga

我正在尝试为我的一个课程中的最终项目制作一个闹钟。我正在使用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;

1 个答案:

答案 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; secmin计数器的范围。秘密是在递增之前进行评估,您可以使用同步负载拦截终端计数。

还切换到与特定值进行相等比较,将它们分开以通过使用elsif设置一组并通过时钟操作优先按下按钮来减少硬件。

所以现在按钮不会在几分钟和几小时内造成范围错误,并且与实际时钟时间无关。

我不认为使用按钮递增分钟时重置秒数是有效的。当clock_set为真时,将秒保持为0可能是有效的,这将在设置时停止运行时钟。但是,如果您只修复夏令时或更改时区,那么这不起作用。

我还没有模拟过这个。它分析和阐述。分配中的范围误差将在模拟过程中显示。

我将hr作为类型位,但确实使用almr_indct作为警报指示的条件。