I'm trying to make a 3 digits BCD counter in VHDL for Cyclone V FPGA from intel. I have an module-k counter design and I instantiate four counters in top level module (structural design):
- One counter acts as frequency divider to get 1Hz signal for the enable of the first digit counter.
- The remaining counts the three digits.
The problem is that for example when test the circuit, I get the sequence: 018 -> 019 -> 010 -> 021 instead of 018 -> 019 -> 020 -> 021. Listings of code:
- counter_modK.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter_modK is
generic(
N : integer := 5;
K : integer := 20
);
port(
clk, reset, en : in std_logic;
Q : out std_logic_vector(N-1 downto 0);
rollover : out std_logic
);
end counter_modK;
architecture behavioral of counter_modK is
signal counter_state : unsigned(N-1 downto 0);
begin
process (clk, reset)
begin
if reset = '0' then
counter_state <= (others => '0');
rollover <= '0';
elsif rising_edge(clk) then
if en = '1' then
if counter_state = K-1 then
counter_state <= (others => '0');
rollover <= '1';
else
counter_state <= counter_state + 1;
rollover <= '0';
end if;
end if;
end if;
end process;
Q <= std_logic_vector(counter_state);
end behavioral;
- BCD_Counter.vhd
library ieee;
use ieee.std_logic_1164.all;
entity BCD_counter is
port(
clk, reset, en : in std_logic;
HEX0, HEX1, HEX2 : out std_logic_vector(6 downto 0)
);
end BCD_counter;
architecture structural of BCD_counter is
component counter_modK is
generic(
N : integer := 5;
K : integer := 20
);
port(
clk, reset, en : in std_logic;
Q : out std_logic_vector(N-1 downto 0);
rollover : out std_logic
);
end component;
component dec7segment is
port(
bin : in std_logic_vector(3 downto 0);
seg : out std_logic_vector(6 downto 0)
);
end component;
signal clk_1sec, enable0, enable1, enable2 : std_logic;
signal bcd_digit0, bcd_digit1, bcd_digit2 : std_logic_vector(3 downto 0);
signal dec_out0, dec_out1, dec_out2 : std_logic_vector(6 downto 0);
signal registered_output0, registered_output1, registered_output2 : std_logic_vector(6 downto 0);
begin
prescaler: counter_modK
generic map(N => 26, K => 50000000)
port map(
clk => clk,
reset => reset,
en => en,
Q => open,
rollover => clk_1sec
);
count_first_digit: counter_modK
generic map(N => 4, K => 10)
port map(
clk => clk,
reset => reset,
en => clk_1sec,
Q => bcd_digit0,
rollover => enable1
);
count_second_digit:
counter_modK
generic map(N => 4, K => 10)
port map(
clk => clk,
reset => reset,
en => enable1 and clk_1sec,
Q => bcd_digit1,
rollover => enable2
);
count_third_digit:
counter_modK
generic map(N => 4, K => 10)
port map(
clk => clk,
reset => reset,
en => enable2 and enable1 and clk_1sec,
Q => bcd_digit2,
rollover => open
);
disp0:
dec7segment port map(bin => bcd_digit0, seg => dec_out0);
disp1:
dec7segment port map(bin => bcd_digit1, seg => dec_out1);
disp2:
dec7segment port map(bin => bcd_digit2, seg => dec_out2);
-- synchronized outputs
process (clk, reset)
begin
if reset='0' then
registered_output0 <= (others => '0');
registered_output1 <= (others => '0');
registered_output2 <= (others => '0');
elsif rising_edge(clk) then
registered_output0 <= dec_out0;
registered_output1 <= dec_out1;
registered_output2 <= dec_out2;
end if;
end process;
HEX0 <= registered_output0;
HEX1 <= registered_output1;
HEX2 <= registered_output2;
end structural;
This glitched behaviour is due to Quartus register the output rollover with a flip-flop in counter_modK entity, as shown in the next picture:
I think that if rollover was a combinational output the problem will be solved because when the counter reach ninth value rollover will get high in the same clock cycle and not in the next cycle how it does now.
Does anyone know how to correct this failed behavior, without reimplement all as a behavioral description in a whole process ?
Thanks.
counter_modK
module will be confused with itsen
input pin. Therollover
signal is changed in sync withclk
, it goes to zero when rising clk (as defined in counter_modk codes). and then u use it like thisenable2 and enable1 and clk_1sec
as anen
signal for other modules. There's times whenen
has a falling edge and Clk has a rising edge at the same time. This can be the cause of problem. \$\endgroup\$