I was given a task to try and make a three way traffic light junction in VHDl using a Preset CountDown Timer, the junction looks like the picture below. The blue rectangle is a car for which the light should turn on if it is there.

The problem that I am having is that the output signal of the CountDown Timer is always 1 after it finished its first cycle with no way of resetting it aside from the input reset signal. Is there any way I could make it so that I know when each consecutive count is over? Here is the code for the counter. Do note that I cannot change the code of the counter, only of the traffic light system:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity PresetDownCounter is
generic(
TIMER_BITS : natural := 4
);
port(
clk : in std_logic;
reset : in std_logic;
timer_preset : in unsigned(TIMER_BITS-1 downto 0);
timer_start : in std_logic;
timer_finished : out std_logic
);
end entity PresetDownCounter;
architecture rtl of PresetDownCounter is
-- Counting Register
signal count_ff : unsigned(TIMER_BITS-1 downto 0) := (others => '0');
signal count_nxt : unsigned(TIMER_BITS-1 downto 0);
begin
-- Sequential process (Register)
seq : process(clk, reset)
begin
if reset = '1' then
count_ff <= (others => '0');
elsif rising_edge(clk) then
count_ff <= count_nxt;
end if;
end process seq;
-- Combinatorial process
comb : process(count_ff, timer_start, timer_preset)
begin
-- Standard assigment
count_nxt <= count_ff;
timer_finished <= '0';
if count_ff /= 0 then
-- Counting down until 0 is reached
count_nxt <= count_ff - 1;
else
-- When 0 is reached, set the timer_finished output to 1
timer_finished <= '1';
end if;
if timer_start = '1' then
-- Input new value when timer is started again.
count_nxt <= timer_preset;
end if;
end process comb;
end architecture rtl;
And here is the code for the traffic junction, to highlight the problem with the counter, note the logic may still not be completely correct:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity AmpelSteuerung4 is
generic (
CLK_HZ : natural := 7
);
port (
clk : in std_logic;
reset : in std_logic;
haupt : out std_logic_vector(2 downto 0);
neben : out std_logic_vector(2 downto 0);
neben_anforderung : in std_logic
);
end AmpelSteuerung4;
architecture rtl of AmpelSteuerung4 is
component PresetDownCounter is
generic (
TIMER_BITS : natural := 6
);
port(
clk : in std_logic;
reset : in std_logic;
timer_preset : in unsigned(TIMER_BITS-1 downto 0);
timer_start : in std_logic;
timer_finished : out std_logic
);
end component;
-- Declaration of internal Signals
signal preset_intern : unsigned(5 downto 0) := (others => '0');
signal start_intern : std_logic := '0';
signal finished_intern : std_logic := '0';
-- States for the State machine
type zustand_t is (RED, RED_YELLOW, GREEN, YELLOW);
signal zustand_ff, zustand_nxt : zustand_t;
constant C_RED : std_logic_vector(2 downto 0) := "100";
constant C_RED_YELLOW : std_logic_vector(2 downto 0) := "110";
constant C_GREEN : std_logic_vector(2 downto 0) := "001";
constant C_YELLOW : std_logic_vector(2 downto 0) := "010";
begin
PRESETDOWNCOUNTER1 : PresetDownCounter
generic map (
TIMER_BITS => 6
)
port map (
clk => clk,
reset => reset,
timer_preset => preset_intern,
timer_start => start_intern,
timer_finished => finished_intern
);
seq : process(clk)
begin
-- Reset Process
if(rising_edge(clk)) then
if reset = '1' then
zustand_ff <= RED;
else
zustand_ff <= zustand_nxt;
end if;
end if;
end process;
fsm : process (clk, zustand_ff, neben_anforderung)
begin
-- State machine
case zustand_ff is
when RED =>
haupt <= C_RED;
neben <= C_GREEN;
preset_intern <= to_unsigned(7 * 4, 6); -- RED for 4 Seconds, multiply by 7 because of the 7 Hz tick rate of the clk input, to get 4 seconds
start_intern <= '1';
if(finished_intern = '1') then
start_intern <= '0';
zustand_nxt <= RED_YELLOW;
end if;
when RED_YELLOW =>
haupt <= C_RED_YELLOW;
neben <= C_YELLOW;
preset_intern <= to_unsigned(7, 6); -- RED_YELLOW for 1 Seconds
start_intern <= '1';
if(finished_intern = '1') then
start_intern <= '0';
zustand_nxt <= GREEN;
end if;
when GREEN =>
haupt <= C_GREEN;
neben <= C_RED;
-- Checking for the neben_anforderung input (blue car on the side)
if neben_anforderung = '1' then
preset_intern <= to_unsigned(7 * 5, 6); -- GREEN for 5 Seconds
start_intern <= '1';
if(finished_intern = '1') then
start_intern <= '0';
zustand_nxt <= YELLOW;
end if;
else
preset_intern <= to_unsigned(7 * 5, 6); -- GREEN for 5 Seconds
start_intern <= '1';
if(finished_intern = '1') then
start_intern <= '0';
zustand_nxt <= GREEN;
end if;
end if;
when YELLOW =>
haupt <= C_YELLOW;
neben <= C_RED_YELLOW;
preset_intern <= to_unsigned(7, 6); -- YELLOW for 1 Second
start_intern <= '1';
if(finished_intern = '1') then
start_intern <= '0';
zustand_nxt <= RED;
end if;
end case;
end process fsm;
end architecture rtl;
Here is a part of the Waveform as well, as you can see the start_intern is high for only one tick of the clk input and the finished_intern(output of the counter) is high all the time after that, even though the timer should be started again.
