Search code examples
vhdlxilinx

5 bit D Flip Flop Counter in VHDL Results in undefined results


I am trying to create this 5 bit up counter using (rising edge) D Flip-Flops with Reset and CK enable using VHDL but the return value is always undefined no matter what I do. I can verify that the flip-flop operates perfectly. Inspect the code below:

DFF.vhd

library IEEE;
use IEEE.std_logic_1164.all;

entity DFFis
    port(
        D:  in std_logic; -- Data input
        C:  in std_logic; -- Clock input
        CE:     in std_logic; -- Clock enable
        CLR:    in std_logic; -- Asynchronous reset
        Q:  out std_logic -- Data output
    );
end DFF;


architecture arch of DFF is
    signal q_i: std_logic;
begin
    process(C, CE, CLR)
    begin
        if (CLR='1') then
            Q<='0';
        elsif (rising_edge(C)) and (CE ='1') then
            Q<=D;
        end if;
    end process;
end arch;

counter.vhd

library IEEE;
use IEEE.std_logic_1164.all;

entity counter is
    port (
        C:  in std_logic; 
        CLR:    in std_logic;
        bits: out std_logic_vector(4 downto 0)
    );
end counter;

architecture arch of counter is
    component DFF
        port(
            D:  in std_logic; -- Data input
            C:  in std_logic; -- Clock input
            CE:     in std_logic; -- Clock enable
            CLR:    in std_logic; -- Asynchronouse reset
            Q:  out std_logic -- Data output
        );
    end component;
    signal q: std_logic_vector(4 downto 0); 
    signal nq: std_logic_vector(4 downto 0);
    
begin
    
    bits<=q;
    
    q(0) <= '1';
    nq <= not q;
    
    DFF0: DFF port map (
        D=>nq(0),
        C=>C,
        CE=>'1',
        CLR=>CLR,
        Q=>q(0)
    );
    DFF1: DFF port map (
        D=>nq(1),
        C=>nq(0),
        CE=>'1',
        CLR=>CLR,
        Q=>q(1)
    );
    DFF2: DFF port map (
        D=>nq(2),
        C=>nq(1),
        CE=>'1',
        CLR=>CLR,
        Q=>q(2)
    );
    DFF3: DFF port map (
        D=>nq(3),
        C=>nq(2),
        CE=>'1',
        CLR=>CLR,
        Q=>q(3)
    );
    DFF4: DFF port map (
        D=>nq(4),
        C=>nq(3),
        CE=>'1',
        CLR=>CLR,
        Q=>q(4)
    );
end arch;

And for testing purposes, counter_TB.vhd

library IEEE;
use IEEE.std_logic_1164.all;

entity counter_TB is
end counter_TB;

architecture arch of counter_TB is
    component counter
        port(
            C:  in std_logic; 
            CLR:    in std_logic;
            bits: out std_logic_vector(4 downto 0)
        );
    end component;
    signal C: std_logic:='0';
    signal CLR: std_logic:='0';
    signal bits: std_logic_vector(4 downto 0);
begin
    test: counter port map (C=>C, CLR=>CLR, bits=>bits);
    
    process
    begin
        C<='1'; CLR<='0'; 
        wait for 1 us;
        C<='0'; CLR<='0'; 
        wait for 1 us;
        C<='1'; CLR<='0'; 
        wait for 1 us;
    end process;
end arch;

When running the test bench, I get the following result on loop (I know why it loops, that isn't the issue):

Result

I have tried initializing the signal q to "00000" and "00001" but the result was the same.


Solution

  • There are three observable errors in the code presented here.

    First, the DFF entity declaration is missing a separator (a space) between DFF and is.

    Second, there are two drivers for signal q(0) In architecture arch of counter. The concurrent assignment to q(0) should be removed.

    Third, the testbench doesn't provide a CLR = '1' condition for the clear in the DFF's. A 'U' inverted is 'U'.

        process
        begin
            C<='1'; -- CLR<='1';
            if now < 1 us then 
                CLR <= '1';
            end if;
            wait for 1 us;
            C<='0'; CLR<='0'; 
            wait for 1 us;
            -- C<='1'; CLR<='0';
            -- wait for 1 us;
        end process;
    

    This results in: counter_tb.jpg

    (This example change is not all inclusive as a method of providing a reset in a testbench.)