在 VHDL 中实现反向计数器

Implementing a reversing counter in VHDL

我是 VHDL 的新手,我正在尝试实现一个从 0 到最大值的计数器,然后在达到最大值后自动开始倒计时。这是我的实体和架构:

entity Rev_Counter is   -- self-reverting counter
    generic (
    counter_steps: integer:=256;                -- number of steps of the counter
    counter_output_size: integer:=8     -- smallest nr of bits to represent the biggest value of the counter
    );
    port (
    clock: in std_logic;                -- input clock signal
    output: out std_logic_vector (counter_output_size-1 downto 0)
    );
end Rev_Counter; 
architecture Arh_Rev_Counter of Rev_Counter is
   signal count_sig: std_logic_vector (counter_output_size-1 downto 0) := (others => '0');
   signal count_dir: std_logic := '0';      -- 0 = count up, 1 = count down  
begin

Count: process (clock)
begin

    if (clock'event and clock = '1') then
        if (count_sig = counter_steps-1) then   -- revert the counting direction
            count_dir <= '1';       -- reached highest value, count down 
            count_sig <= count_sig - 1;
        elsif (count_sig = 0) then  -- revert the counting direction
            count_dir <= '0';       -- reached lowest value, count up  
            count_sig <= count_sig + 1;
        end if;

        if (count_dir = '0') then   -- perform count up
            count_sig <= count_sig + 1;
        elsif (count_dir = '1') then    -- preform count down
            count_sig <= count_sig - 1;
        end if;
    end if;
end process;
output <= count_sig;

end architecture; 

我的问题是:在模拟这段代码时,我的计数器正常计数到 FF,然后它开始表现得很奇怪。数到 FF 后,它直接到 00,然后是 FF,然后是 00 等等,中间没有数字。如果能帮我弄清楚为什么会这样,我将不胜感激。

我找到了另一种方法。我将 Count 过程编辑为如下所示。但是,我一开始并不完全明白哪里出了问题,因此我仍然希望您能提供一些见解。

    Count: process (clock)
    begin

        if (clock'event and clock = '1') then  
            if (count_dir = '0') then   
                count_sig <= count_sig + 1;
                if (count_sig = counter_steps - 1) then
                    count_sig <= count_sig - 1;
                    count_dir <= '1';
                end if;
            elsif (count_dir = '1') then
                count_sig <= count_sig - 1;
                if (count_sig = 0) then
                    count_dir <= '0';
                end if;
            end if;
        end if;
    end process;

你正在改变 count_dir 两端都晚了一个刻度。

因为它是一个注册值,改变它的效果有 1 个时钟周期的延迟。因此,在达到 0xFF count_sig 时,将在反转方向之前再增加一次 (0x00)。然后它会计数'down'到0xFF,再次反转方向,导致值在0x00和0xFF之间不断闪烁。

改变条件以将方向改变为 count_sig = counter_steps - 2count_sig = 1 分别为您提供所需的行为。