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 има 2xрегистъра на срез означава, че имате нужда от 2 допълнителни среза).

Докато логическата функция, изпълнявана от кода, е идентична, те няма да се държат по същия начин. Ако/когато свържете изходите към входове на други блокове, резултатът ще бъде наличен 1 цикъл по-рано за версия 2. Ако приемем, че блокът надолу по веригата приема тези входове и прилага малко повече логика, ще видите, че версия 2 води до по-дълги пътища и следователно до постижимата честота е по-нисък.

Някои насоки гласят, че обикновено трябва да регистрирате изходите в блокове, за да подобрите времето. Понякога искате да можете да свържете няколко блока заедно комбинаторно, така че при всички насоки винаги има някои изключения. Добра практика е да коментирате в декларацията, ако някакви изходи се управляват комбинаторно. Ако се чувствате особено запалени, можете да направите изходния регистър незадължителен, като използвате генеричен.

person Chiggs    schedule 14.04.2014