I am trying to make an alarm clock for a final project in one of my classes. I am using push buttons on a DE1 Altera board to manually increment hours and mins. The mins work but I can not get the hours to increment manually. All pin assignments are correct.
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;
You can see where the error is by indenting properly:
The
clk
condition is enclosed in the outermost if statement and isn't necessary:Should be
And that brings us to what's wrong.
pb_hr
is only evaluated at 11 PM:At a minimum these two if statements need to be at the same nesting level.
Unfortunately it also makes you take a look up the if statement nesting levels where you notice you can only set hours at 23:59:59, or you're also holding down
pb_min
andclk_set
is true.Also notice you
almr_indct
is true for a minute no matter what you do. I'd suggest moving the sets and alarm detection outside the enclosing if statement with the clock condition (keep them in the same process). It should also be invalidated whenclk_set
is true.Looking even further back:
We see you could reach 60 for a button push. That all needs to be fixed. It's also possible to move the alarm comparison outside of the counters and disable during clock set.
So you could manipulate the process statement:
And with the opportunity I fixed the range for the
sec
,min
andhr
counters. The secret is evaluating before incrementing, you intercept a terminal count with a synchronous load.Also switched to equality comparisons to specific values, separated them to reduce hardware by having one set and prioritized the push buttons over the clock operation by using elsif.
So now push buttons can't cause range errors in minutes and hours, and are independent of actual clock time.
I don't think it's valid to reset seconds when incrementing minutes with the push button. It might be valid to keep seconds at 0 while clock_set is true, which would stop the clock from running when being set. That doesn't work if you're only fixing daylight savings time or changing time zones, though.
I haven't simulated this. It analyzes and elaborates. Range errors in assignment would show up during simulation.
I left
almr_indct
as type bit, but did useclk_set
as a condition for the alarm indication.