如何使VHDL输出信号无状态

时间:2011-05-01 01:15:07

标签: state signals vhdl

我有以下代码,这是我的数字时钟的一部分:

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

-- Seconds counter
entity SecCounter is
    port( 
            s_enable: in std_logic;
            s_load: in std_logic; -- When high, sets this counter to the value in the     data inputs
            s_clk: in std_logic; -- Clock
            s_input: in std_logic_vector(5 downto 0); -- Data inputs
            s_output: out std_logic_vector(5 downto 0); --Outputs
            s_wrap: out std_logic
        );
    end SecCounter;

architecture imp of SecCounter is
    -- Intermediate signal to mainpulate the seconds as integer
    signal sec: integer range 0 to 60 := 22;

    begin
        s_output <= std_logic_vector(to_unsigned(sec,6)); -- Assign the input to the binary     value of sec

        process(s_clk, s_load, s_enable) -- If clk, enable, or load is changed
        begin
            s_wrap <= '0'; -- Clear the wrap

            if (s_enable = '0' and s_load = '1') then -- Set the clock
                sec <= to_integer(unsigned(s_input));
            elsif (s_enable = '1' and rising_edge(s_clk)) then -- Increment the counter
                sec <= sec + 1;
            end if;

            if sec = 60 then -- Restart counter and toggle the next counter
                sec <= 0;
                s_wrap <= '1';
            end if;
        end process;
end imp;

s_wrap充当下一个计数器的启用。我想要做的是,如果这个计数器等于60,我想为一个时钟边沿启用下一个计数器。我试图通过将s_wrap设置为true然后在下一个时钟边缘设置为false来执行此操作;但是,它没有改变。有没有办法让is_wrap无国籍?如果没有,我该如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

您要将值分配给rising_edge(clk)子句之外的sec。如果s_enable = 0且s_load = 0,则不会将任何内容分配给sec。这些事实中的任何一个都使得sec成为异步信号。如果你修复了这两个问题,那么所描述的问题就会消失。

Oli Charlesworth对于检查59而不是60来说有一个很好的观点。然后你不必人为地将你不存在的60包括在你的范围内。将sec初始化为一个值没有意义。您应该在reset子句中初始化它。

由于您正在异步读取s_enable,s_load和s_input,因此可能还有其他问题。这通常仅针对复位信号进行。

答案 1 :(得分:1)

[免责声明:我对VHDL不太满意,所以我无法就语法提出建议。]

我认为您希望在s_wrap达到 59 而非 60 时断言sec。这样,在下一个时钟边沿,分钟计数器将看到s_wrap = 1并递增,同时此计数器输出再次变为0。

你想要这样的东西:

process(s_clk, s_load, s_enable) -- If clk, enable, or load is changed
begin

    if (s_enable = '0' and s_load = '1') then -- Set the clock
        sec <= to_integer(unsigned(s_input));
    elsif (s_wrap = '1') then -- Wrap
        sec <= 0;
    elsif (s_enable = '1' and rising_edge(s_clk)) then -- Increment the counter
        sec <= sec + 1;
    end if;

end process;

s_wrap <= '1' when sec = 59 else '0';

答案 2 :(得分:0)

我会做的是将sec声明为流程中的变量,因为变量会立即更新:

process(s_clk, s_load, s_enable)
variable v_sec : integer range 0 to 60;
begin
if reset = '1' then
    v_sec := 0;
    s_sec <= (others => '0');
    s_wrap <= '0';
elsif rising_edge(s_clk) then
   s_output <= std_logic_vector(to_unsigned(v_sec,6));
   if s_enable = '1' then
     v_sec := v_sec +1;
     if v_sec = 60 then
        v_sec:= 0;
        s_wrap <= '1';
     else
        s_wrap <= '0';
     end if;
   else
   s_wrap <= '0';
   end if;
end if;

如果你在modelsim中模拟这个,那么sec将会变为0,1,2,.... 58,59,0,1,2,并且s_wrap将等于1每次秒等于0,除了第一次,当复位条件将其设置为0时。