I am trying to implement something as simple as the controller for one single traffic light by using two counters (one for green/red and one for yellow), but I don't seem to be getting the timing right.
My first counter looked something like
entity counter is
generic (
max_count : integer := 50
);
port (
clk : in std_ulogic;
rst : in std_ulogic;
count_value : out integer := '0';
flag : out std_ulogic := '0'
);
end entity;
architecture behav of counter is
signal count : natural := 0;
begin
count_value <= count
process (rst, clk)
begin
if rst = '0' then
flag <= '0';
count <= 0;
elsif rising_edge(clk) then
count <= (count + 1) mod max_count;
if count = 0 then
-- set flag value for one cycle
flag <= '1';
else
flag <= '0';
end if;
end if;
end process;
end architecture behav;
which also sets the flag value when it starts to count.
When I tried to implement the traffic light (simply a state machine) by means of this counter, I got stuck. When I just start the red/green counter c_redgreen
once, i.e. the counter is never reset. The problem with this approach is of course that the time where the traffic light is yellow is not taken into account (e.g. the light starts with red and stays in that state for 50 cycles, then it becomes yellow for 5 cycles, but then there are only 45 cycles green, because the counter was not paused during the yellow time etc…). I thought this could be simply worked around by resetting c_redgreen
while the light is yellow, but immediately after the reset, the flag is immediately set and therefore I can't use something like if rising_edge(rg_flag) then ...
, because the rising edge comes immediately (because the counter sets the flag as it starts).
After these troubles, I thought it would be better to reformulate my counter as follows
...
elsif rising_edge(clk) then
temp := (count + 1) mod max_count;
count <= temp
if temp = 0 then
...
to avoid the flag being set when starting, but when I start the clock (in the testbench) with 0, the first red light does not last 50 cycles, but only 49. Also I am not sure whether it is a good idea for a counter to do nothing until it has reached max_count
.
My question is thus how I can combine two counters (with or without start-flag) so that I can make my red/green lights shine for n
cycles and my yellow light for m
cycles. I hope I have been clear enough. If the code for my traffic light would be necessary, I can add it (I just didn't want to make this question even longer). I also don't necessarily need a traffic light, I just want to have these counters running in parallel in some way. Thanks in advance
Best Answer
You're way over-thinking this. There's no reason to make the counter a separate entity; you just end up writing a lot of code to do explicitly what the synthesis tools can do for you implicitly.
Also, for the example of traffic lights, you really only need one counter, because you only need one delay at a time. The same counter can handle different delays for different states.
Just make the counter part of the main state machine, something like this: