I'm studying VHDL right now, and I have a pretty simple homework assignment - I need to build a synchronous BCD counter that will count from 0 to 9 and when it reaches 9, will go back to 0. I wanted to experiment a little so I decided not to do the code in a (at least the way I see it) traditional way (with if, elseif) but with the when-else statement (mostly due to the fact that counter is from 0 to 9 and has to go back to 0 once it hits 9).
library IEEE;
use IEEE.std_logic_1164.all;
Entity sync_counter is
port (rst, clk: in std_logic);
end Entity;
Architecture implement of sync_counter is
signal counter: integer range 0 to 10;
Begin
counter <= 0 when (rst = '1') else
counter + 1 when (clk='1' and clk'event) else
0 when (counter = 10);
end Architecture;
So everything compiles, but in the simulation, initially counter jumps from 0 to 2, but after a cycle (0-9 - 0) it is acting normal, meaning counter goes from 0 to 1 as it should be. Same if you force rst = '1'.
Simulation image:
Why does it jump from 0 to 2 in the start?
Thank you.
It may not explain why it goes from 0 to 2. Please post your testbench code on that front. However, your code is bad. This code translate to this, with comments:
process(rst, clk, counter)
begin
if rst = '1' then -- Asynchronous reset, so far so good
counter <= 0;
elsif clk'event and clk = '1' then -- Rising edge, we got an asynchronous flip-flop?
counter <= counter + 1;
elsif counter = 10 then -- What is this!?! not an asynchronous reset, not a synchronous reset, not a clock. How does this translate to hardware?
counter <= 0;
end if;
end process;
I'm not sure if this would work in hardware, but I can't quickly figure out how it would be implemented, what you want is this:
process(rst, clk)
begin
if rst = '1' then -- Asynchronous reset
counter <= 0;
elsif clk'event and clk = '1' then
if counter = 9 then -- Synchronous reset
counter <= 0;
else
counter <= counter + 1;
end if;
end if;
end process;
I leave the "when-else" statements for purely combinational code, or at most to the single line reg <= value when rising_edge(clk)
.