简体   繁体   中英

Quartus II : simple counter but weird behaviour

First of all I'm sorry to bother you guys with my very noob question, but I can't find any sense to what's happening with my (ModelSim simulated) circuit.

Here's my code, simple as can be :

LIBRARY ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

ENTITY Counter IS
    PORT(
    enable  : in std_logic;
    clk     : in std_logic;
    count       : out integer range 0 to 255);
END Counter;

ARCHITECTURE LogicFunction OF Counter IS

    signal count_i : integer range 0 to 255;

begin

    cnt : process(clk, enable, count_i)
    begin
        count <= count_i;
        if (enable = '0') then
            count_i <= 0;
        else
            count_i <= count_i + 1;
        end if;
    end process;

end LogicFunction;

My problem is : when I perform a timing simulation with ModelSim, with a clock signal, "enabled" is first '0' and then '1', the output ("count") stays at zero all the time. I tried a lot of different things, like setting the "count" out as a vector, doing all sorts of casts, but it still stays the same.

The increment "count_i <= count_i + 1;" seems to be the problem : I tried to replace it with something like "count_i <= 55", and then the output changes (to "55" in the previous example).

I've seen the exact same increment in the code on that webpage for example : http://surf-vhdl.com/how-to-connect-serial-adc-fpga/ I've created a project, simulated it and... it works ! I really don't get what the guy did that I didn't, excepted for a bunch of "if" that I don't need in my code.

Any help would be greatly appreciated, I've spent like 3 hours of trial and errors...

Thanx in advance !

In addition to not using a clock edge to increment i_count you're using enable as a clear because it's both in the sensitivity list and encountered first in an if statement condition.

library ieee;
use ieee.std_logic_1164.all;
-- use ieee.numeric_std.all;

entity counter is
    port(
    enable  : in std_logic;
    clk     : in std_logic;
    count       : out integer range 0 to 255);
end counter;


architecture logicfunction of counter is

    signal count_i : integer range 0 to 255;

begin

    cnt : process (clk) -- (clk, enable, count_i)
    begin
        -- count <= count_i;   -- MOVED 
        -- if (enable = '0') then  -- REWRITTEN
        --     count_i <= 0;
        -- else
        --     count_i <= count_i + 1;
        -- end if;
        if rising_edge(clk) then
            if enable = '1' then
                count_i <= count_i + 1;
            end if;
        end if;
    end process;

    count <= count_i;  -- MOVED TO HERE

end architecture logicfunction;

Your code is modified to using the rising edge of clk and require enable = '1' before i_count increment. The superfluous use clause referencing package numeric_std has been commented out. The only numeric operation you're performing is on an integer and those operators are predefined in package standard.

Note the replacement if statement doesn't surround it's condition with parentheses. This isn't a programming language and they aren't needed.

The count assignment is moved to a concurrent signal assignment. This removes the need of having i_count in the sensitivity list just to update count.

Throw in a testbench to complete a Miminal Complete and Verifiable Example :

library ieee;
use ieee.std_logic_1164.all;

entity counter_tb is
end entity;

architecture foo of counter_tb is
    signal enable:  std_logic := '0';
    signal clk:     std_logic := '0';
    signal count:   integer range 0 to 255;
begin
DUT:
    entity work.counter
        port map (
            enable => enable,
            clk => clk,
            count => count
        );
CLOCK:
    process
    begin
        wait for 5 ns;  -- 1/2 clock period
        clk <= not clk;
        if now > 540 ns then
            wait;
        end if;
    end process;
STIMULUS:
    process
    begin
        wait for 30 ns;
        enable <= '1';
        wait for 60 ns;
        enable <= '0';
        wait for 30 ns;
        enable <= '1';
        wait;

    end process;
end architecture;

And that gives:

counter_tb.png

Which shows that the counter doesn't counter when enable is '0' nor does enable = '0' reset the value of i_count.

The Quartus II Handbook Volume 1 Design and Synthesis doesn't give an example using a clock edge and an enable without an asynchronous clear or load signal.

The secret here is anything inside the if statement condition specified using a clock edge will be synchronous to the clock. Any condition outside will be asynchronous.

The form of synthesis eligible sequential logic is derived from the now withdrawn IEEE Std 1076.6-2004 IEEE Standard for VHDL Register Transfer Level (RTL) Synthesis. Using those behavioral descriptions guarantees you can produce hardware through synthesis that matches simulation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM