Как сделать VHDL выходной сигнал без сохранения состояния - PullRequest
0 голосов
/ 01 мая 2011

У меня есть следующий код, который является частью моих цифровых часов:

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 ]

2 голосов
/ 01 мая 2011

Вы присваиваете значения секундам за пределами предложения rise_edge (clk).И вы ничего не назначаете sec, если s_enable = 0 и s_load = 0.Любой из этих фактов делает sec асинхронным сигналом.Если вы исправите оба, то описанная проблема должна исчезнуть.

И у Оли Чарльзуорта есть хорошее замечание о проверке 59, а не 60. Тогда вам не нужно искусственно включать несуществующие 60 в свой диапазон,И инициализация sec для значения не имеет смысла.Вы должны инициализировать его в предложении сброса.

У вас могут быть другие проблемы, так как вы читаете s_enable, s_load и s_input асинхронно.Обычно это делается только для сигнала сброса.

1 голос
/ 01 мая 2011

[Отказ от ответственности: я не очень разбираюсь в VHDL, поэтому не могу посоветовать синтаксис.]

Я думаю, что вы хотите утверждать s_wrap, когда sec достигает 59 , а не 60 . Таким образом, на следующем фронте тактового счетчика минут будет отображаться 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';
0 голосов
/ 30 апреля 2013

Что бы я сделал, это объявил бы 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 каждый раз, когда sec равен 0, за исключением первого раза, когда условие сброса устанавливает его равным 0.

...