Квадратурный декодер VHDL: последовательная/комбинаторная логика

Я реализую квадратурный декодер в VHDL и придумал два решения.

В методе 1 вся логика помещается в один процесс, чувствительный к часам и сбросу. На Spartan-3A для этого используются четыре слайса, семь FF и четыре входных LUT.

Код 1

architecture Behavioral of quadr_decoder is
    signal chan_a_curr : std_logic;
    signal chan_a_prev : std_logic;
    signal chan_b_curr : std_logic;
    signal chan_b_prev : std_logic;
begin
    process (n_reset, clk_in) begin
        if (n_reset = '0') then
            -- initialize internal signals
            chan_a_curr <= '0';
            chan_a_prev <= '0';
            chan_b_curr <= '0';
            chan_b_prev <= '0';
            -- initialize outputs
            count_evt <= '0';
            count_dir <= '0';
            error_evt <= '0';
        elsif (clk_in'event and clk_in = '1') then
            -- keep delayed inputs
            chan_a_prev <= chan_a_curr;
            chan_b_prev <= chan_b_curr;
            -- read current inputs
            chan_a_curr <= chan_a;
            chan_b_curr <= chan_b;
            -- detect a count event
            count_evt <= ((chan_a_prev xor chan_a_curr) xor
                          (chan_b_prev xor chan_b_curr));
            -- determine count direction
            count_dir <= (chan_a_curr xor chan_b_prev xor 
                          count_mode);
            -- detect error conditions
            error_evt <= ((chan_a_prev xor chan_a_curr) and 
                          (chan_b_prev xor chan_b_curr));
        end if;
    end process;
end Behavioral;

Метод 2 разбивает логику на отдельные последовательные и комбинаторные процессы. Он использует два слайса, четыре FF и четыре входных LUT.

Код 2

architecture Behavioral of quadr_decoder is
    signal chan_a_curr : std_logic;
    signal chan_a_prev : std_logic;
    signal chan_b_curr : std_logic;
    signal chan_b_prev : std_logic;
begin
    process (n_reset, clk_in) begin
        if (n_reset = '0') then
            -- initialize internal signals
            chan_a_curr <= '0';
            chan_a_prev <= '0';
            chan_b_curr <= '0';
            chan_b_prev <= '0';
        elsif (clk_in'event and clk_in = '1') then
            -- keep delayed inputs
            chan_a_prev <= chan_a_curr;
            chan_b_prev <= chan_b_curr;
            -- read current inputs
            chan_a_curr <= chan_a;
            chan_b_curr <= chan_b;
        end if;
    end process;

    process (chan_a_prev, chan_a_curr, chan_b_prev, chan_b_curr) begin
            -- detect a count event
            count_evt <= ((chan_a_prev xor chan_a_curr) xor 
                          (chan_b_prev xor chan_b_curr));
            -- determine count direction
            count_dir <= (chan_a_curr xor chan_b_prev xor count_mode);
            -- detect error conditions
            error_evt <= ((chan_a_prev xor chan_a_curr) and 
                         (chan_b_prev xor chan_b_curr));
    end process;
end Behavioral;

Когда я моделирую код (поведенческий), оба результата выглядят нормально. Но я не могу поверить, что оба метода одинаково верны. Может ли кто-нибудь пролить свет на то, какой метод следует предпочесть другому?


person seir    schedule 14.04.2014    source источник


Ответы (1)


Ваша версия кода 2 управляет выходными данными комбинаторно, тогда как версия кода 1 регистрирует выходные данные:

  • count_evt
  • count_dir
  • error_evt

Это составляет 3 дополнительных триггера (а поскольку Spartan 3 имеет 2 регистра на слайс, это означает, что вам нужно 2 дополнительных слайса).

Хотя логическая функция, выполняемая кодом, идентична, они не будут вести себя одинаково. Если/когда вы соедините выходы с входами других блоков, результат будет доступен на 1 цикл раньше для версии 2. Предполагая, что нижестоящий блок принимает эти входы и применяет некоторую логику, вы увидите, что версия 2 приводит к более длинным путям и, следовательно, к достижимой частоте. ниже.

В некоторых рекомендациях говорится, что вы должны обычно регистрировать выходные данные в блоках, чтобы улучшить синхронизацию. Иногда вы хотите иметь возможность объединять несколько блоков вместе комбинаторно, чтобы из всех рекомендаций всегда были некоторые исключения. Хорошей практикой является комментирование в объявлении, если какие-либо выходные данные управляются комбинаторно. Если вы чувствуете себя особенно заинтересованным, вы можете сделать выходной регистр необязательным, используя общий.

person Chiggs    schedule 14.04.2014