Szukaj…


Uwagi

D-Flip-Flops (DFF) i zatrzaski są elementami pamięci. DFF próbkuje dane wejściowe na jednej lub drugiej krawędzi swojego zegara (nie na obu), podczas gdy zatrzask jest przezroczysty na jednym poziomie jego aktywacji i zapamiętywany na drugim. Poniższy rysunek ilustruje różnicę:

Zachowanie DFF vs. zatrzaskiwania

Modelowanie DFF lub zatrzasków w VHDL jest łatwe, ale należy wziąć pod uwagę kilka ważnych aspektów:

  • Różnice między modelami DFF i zatrzasków VHDL.

  • Jak opisać krawędzie sygnału.

  • Jak opisać synchroniczny lub asynchroniczny zestaw lub resety.

Klapki D (DFF)

We wszystkich przykładach:

  • clk to zegar,
  • d jest wejściem,
  • q jest wyjściem,
  • srst to aktywny reset synchroniczny wysokiego poziomu,
  • srstn to aktywny niski synchroniczny reset,
  • arst to aktywny wysoki asynchroniczny reset,
  • arstn to aktywny niski asynchroniczny reset,
  • sset jest aktywnym zestawem wysokiej synchronizacji,
  • ssetn to aktywny niski zestaw synchroniczny,
  • aset to aktywny wysoki zestaw asynchroniczny,
  • asetn jest aktywnym niskim zestawem asynchronicznym

Wszystkie sygnały są typu ieee.std_logic_1164.std_ulogic . Zastosowana składnia prowadzi do poprawnych wyników syntezy we wszystkich syntezatorach logicznych. Zobacz przykład wykrywania krawędzi zegara, aby uzyskać dyskusję na temat alternatywnej składni.

Zegar wschodzącej krawędzi

process(clk)
begin
  if rising_edge(clk) then
    q <= d;
  end if;
end process;

Falling edge clock

process(clk)
begin
  if falling_edge(clk) then
    q <= d;
  end if;
end process;

Zegar narastający, synchroniczny aktywny wysoki reset

process(clk)
begin
  if rising_edge(clk) then
    if srst = '1' then
      q <= '0';
    else
      q <= d;
    end if;
  end if;
end process;

Zegar narastający, asynchroniczny aktywny wysoki reset

process(clk, arst)
begin
  if arst = '1' then
    q <= '0';
  elsif rising_edge(clk) then
    q <= d;
  end if;
end process;

Zegar opadającego zbocza, asynchroniczny aktywny niski reset, wysoki synchroniczny aktywny wysoki

process(clk, arstn)
begin
  if arstn = '0' then
    q <= '0';
  elsif falling_edge(clk) then
    if sset = '1' then
      q <= '1';
    else
      q <= d;
    end if;
  end if;
end process;

Zegar narastającego zbocza, asynchroniczny aktywny wysoki reset, asynchroniczny aktywny niski poziom

Uwaga: zestaw ma wyższy priorytet niż reset

process(clk, arst, asetn)
begin
  if asetn = '0' then
    q <= '1';
  elsif arst = '1' then
    q <= '0';
  elsif rising_edge(clk) then
    q <= d;
  end if;
end process;

Zatrzaski

We wszystkich przykładach:

  • en jest sygnałem zezwolenia,
  • d jest wejściem,
  • q jest wyjściem,
  • srst to aktywny reset synchroniczny wysokiego poziomu,
  • srstn to aktywny niski synchroniczny reset,
  • arst to aktywny wysoki asynchroniczny reset,
  • arstn to aktywny niski asynchroniczny reset,
  • sset jest aktywnym zestawem wysokiej synchronizacji,
  • ssetn to aktywny niski zestaw synchroniczny,
  • aset to aktywny wysoki zestaw asynchroniczny,
  • asetn jest aktywnym niskim zestawem asynchronicznym

Wszystkie sygnały są typu ieee.std_logic_1164.std_ulogic . Zastosowana składnia prowadzi do poprawnych wyników syntezy we wszystkich syntezatorach logicznych. Zobacz przykład wykrywania krawędzi zegara, aby uzyskać dyskusję na temat alternatywnej składni.

Aktywne wysokie zezwolenie

process(en, d)
begin
  if en = '1' then
    q <= d;
  end if;
end process;

Aktywne niskie zezwolenie

process(en, d)
begin
  if en = '0' then
    q <= d;
  end if;
end process;

Aktywne wysokie zezwolenie, synchroniczny aktywny wysoki reset

process(en, d)
begin
  if en = '1' then
    if srst = '1' then
      q <= '0';
    else
      q <= d;
    end if;
  end if;
end process;

Aktywne wysokie zezwolenie, asynchroniczny aktywny wysoki reset

process(en, d, arst)
begin
  if arst = '1' then
    q <= '0';
  elsif en = '1' then
    q <= d;
  end if;
end process;

Aktywne niskie zezwolenie, asynchroniczne aktywne zerowanie niskie, synchroniczne aktywne wysokie ustawienie

process(en, d, arstn)
begin
  if arstn = '0' then
    q <= '0';
  elsif en = '0' then
    if sset = '1' then
      q <= '1';
    else
      q <= d;
    end if;
  end if;
end process;

Aktywne wysokie zezwolenie, asynchroniczny aktywny wysoki reset, asynchroniczny aktywny niski poziom

Uwaga: zestaw ma wyższy priorytet niż reset

process(en, d, arst, asetn)
begin
  if asetn = '0' then
    q <= '1';
  elsif arst = '1' then
    q <= '0';
  elsif en = '1' then
    q <= d;
  end if;
end process;

Wykrywanie krawędzi zegara

Krótka historia

Whith VHDL 2008 i jeśli typ zegara jest bit , boolean , ieee.std_logic_1164.std_ulogic lub ieee.std_logic_1164.std_logic , wykrywanie krawędzi zegara mogą być kodowane za zboczem narastającym

  • if rising_edge(clock) then
  • if clock'event and clock = '1' then -- type bit, std_ulogic or std_logic
  • if clock'event and clock then -- type boolean

i do opadania krawędzi

  • if falling_edge(clock) then
  • if clock'event and clock = '0' then -- type bit, std_ulogic or std_logic
  • if clock'event and not clock then -- type boolean

Będzie to działać zgodnie z oczekiwaniami, zarówno w przypadku symulacji, jak i syntezy.

Uwaga: definicja zbocza narastającego na sygnale typu std_ulogic jest nieco bardziej złożona niż proste, if clock'event and clock = '1' then . Na przykład standardowa funkcja rising_edge ma inną definicję. Nawet jeśli prawdopodobnie nie będzie to miało znaczenia dla syntezy, może to zrobić dla symulacji.

Zdecydowanie zalecane jest korzystanie ze standardowych funkcji rising_edge i falling_edge . W poprzednich wersjach VHDL użycie tych funkcji może wymagać jawnego zadeklarowania użycia standardowych pakietów (np. ieee.numeric_bit dla bit typu) lub nawet zdefiniowania ich w pakiecie niestandardowym.

Uwaga: nie używaj standardowych funkcji rising_edge i falling_edge do wykrywania krawędzi sygnałów innych niż zegarowe. Niektóre syntezatory mogą wnioskować, że sygnał jest zegarem. Wskazówka: wykrywanie zbocza sygnału nie zegara może być często wykonywane przez próbkowanie sygnału w rejestrze przesuwnym i porównywanie próbkowanych wartości na różnych etapach rejestru przesuwnego.

Długa historia

Prawidłowe opisanie wykrycia krawędzi sygnału zegara jest niezbędne podczas modelowania D-Flip-Flops (DFF). Krawędź jest z definicji przejściem od jednej konkretnej wartości do drugiej. Na przykład, możemy zdefiniować zbocze narastające sygnału typu bit (standardowy typ wyliczany VHDL, który przyjmuje dwie wartości: '0' i '1' ) jako przejście z '0' na '1' . Dla typu boolean możemy zdefiniować go jako przejście od false do true .

Często stosuje się bardziej złożone typy. Na ieee.std_logic_1164.std_ulogic typ ieee.std_logic_1164.std_ulogic jest również typem wyliczonym, podobnie jak bit lub boolean , ale ma 9 wartości zamiast 2:

Wartość Znaczenie
'U' Niezainicjowany
'X' Wymuszanie nieznane
'0' Wymuszanie niskiego poziomu
'1' Wymuszając wysoki poziom
'Z' Wysokiej impedancji
'W' Słaby nieznany
'L' Słaby niski poziom
'H' Słaby wysoki poziom
'-' Nie obchodzi mnie to

Definiowanie zbocza narastającego na takim typie jest nieco bardziej złożone niż dla bit lub boolean . Możemy na przykład zdecydować, że jest to przejście z '0' na '1' . Możemy jednak zdecydować, że jest to przejście z '0' lub 'L' na '1' lub 'H' .

Uwaga: jest to druga definicja, której standard używa dla funkcji ieee.std_logic_1164 rising_edge(signal s: std_ulogic) zdefiniowanego w ieee.std_logic_1164 .

Przy omawianiu różnych sposobów wykrywania krawędzi ważne jest zatem rozważenie rodzaju sygnału. Ważne jest również wzięcie pod uwagę celu modelowania: tylko symulacja czy synteza logiczna? Zilustrujmy to na kilku przykładach:

Narastająca krawędź DFF z bitem typu

signal clock, d, q: bit;
...
P1: process(clock)
begin
  if clock = '1' then
    q <= d;
  end if;
end process P1;

Technicznie, z punktu widzenia czystej semantyki symulacji, proces P1 modeluje DFF wyzwalający zbocze narastające. Rzeczywiście, przypisanie q <= d jest wykonywane wtedy i tylko wtedy, gdy:

  • clock zmieniony (tak wyraża się lista czułości) i
  • aktualna wartość clock to '1' .

Ponieważ clock jest typu bitowego, a bit typu ma tylko wartości '0' i '1' , właśnie to zdefiniowaliśmy jako zbocze narastające sygnału typu bitowego. Każdy symulator obsłuży ten model zgodnie z oczekiwaniami.

Uwaga: w przypadku syntezatorów logicznych rzeczy są nieco bardziej złożone, co zobaczymy później.

Zbocze narastające DFF z asynchronicznym aktywnym wysokim resetem i bitem typu

Aby dodać asynchroniczny aktywny wysoki reset do naszego DFF, można spróbować czegoś takiego:

signal clock, reset, d, q: bit;
...
P2_BOGUS: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif clock = '1' then
    q <= d;
  end if;
end process P2_BOGUS;

Ale to nie działa . Warunkiem wykonania przypisania q <= d powinno być: narastające zbocze clock podczas reset = '0' . Ale modelowaliśmy:

  • clock lub reset lub oba zmienione i
  • reset = '0' i
  • clock = '1'

Co nie jest takie samo: jeśli reset zmieni się z '1' na '0' gdy clock = '1' przypisanie zostanie wykonane, gdy nie będzie rosnącą krawędzią clock .

W rzeczywistości nie ma możliwości modelowania tego w VHDL bez pomocy atrybutu signal:

P2_OK: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif clock = '1' and clock'event then
    q <= d;
  end if;
end process P2_OK;

clock'event to event atrybutu sygnału zastosowane do clock sygnału. Ocenia się jako wartość boolean i jest true wtedy i tylko wtedy, gdy clock sygnału zmienił się podczas fazy aktualizacji sygnału, która tuż przed bieżącą fazą wykonania. Dzięki temu proces P2_OK teraz doskonale modeluje to, czego chcemy w symulacji (i syntezie).

Semantyka syntezy

Wiele syntezatorów logicznych identyfikuje wykrywanie krawędzi sygnału na podstawie wzorców składniowych, a nie semantyki modelu VHDL. Innymi słowy, zastanawiają się, jak wygląda kod VHDL, a nie jakie zachowanie modeluje. Jednym z wzorców, które wszyscy rozpoznają, jest:

if clock = '1' and clock'event then

Tak więc, nawet w przykładzie procesu P1 powinniśmy go użyć, jeśli chcemy, aby nasz model był syntezowalny przez wszystkie syntezatory logiczne:

signal clock, d, q: bit;
...
P1_OK: process(clock)
begin
  if clock = '1' and clock'event then
    q <= d;
  end if;
end process P1_OK;

and clock'event część and clock'event jest całkowicie zbędna z listą czułości, ale ponieważ niektóre syntezatory tego potrzebują ...

std_ulogic krawędź DFF z asynchronicznym aktywnym wysokim resetem i wpisz std_ulogic

W takim przypadku wyrażenie rosnącego zbocza zegara i warunek resetowania mogą się skomplikować. Jeśli zachowamy definicję zbocza narastającego, którą zaproponowaliśmy powyżej i jeśli weźmiemy pod uwagę, że reset jest aktywny, jeśli jest to '1' lub 'H' , model staje się:

library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4: process(clock, reset)
begin
  if reset = '1' or reset = 'H' then
    q <= '0';
  elsif clock'event and
        (clock'last_value = '0' or clock'last_value = 'L') and
        (clock = '1' or clock = 'H') then
    q <= d;
  end if;
end process P4;

Uwaga: 'last_value to kolejny atrybut sygnału, który zwraca wartość sygnału, który miał przed ostatnią zmianą wartości.

Funkcje pomocnicze

Standard VHDL 2008 oferuje kilka funkcji pomocniczych, aby uprościć wykrywanie krawędzi sygnału, szczególnie w przypadku wielowartościowych wyliczanych typów, takich jak std_ulogic . std.standard pakiet określa rising_edge i falling_edge funkcje dotyczące rodzajów bit i boolean , a ieee.std_logic_1164 pakiet definiuje je na typy std_ulogic i std_logic .

Uwaga: w poprzednich wersjach VHDL użycie tych funkcji może wymagać jawnego zadeklarowania użycia standardowych pakietów (np. Ieee.numeric_bit dla bitu typu) lub nawet zdefiniowania ich w pakiecie użytkownika.

Powróćmy do poprzednich przykładów i skorzystaj z funkcji pomocniczych:

signal clock, d, q: bit;
...
P1_OK_NEW: process(clock)
begin
  if rising_edge(clock) then
    q <= d;
  end if;
end process P1_OK_NEW;
signal clock, d, q: bit;
...
P2_OK_NEW: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif rising_edge(clock) then
    q <= d;
  end if;
end process P2_OK_NEW;
library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4_NEW: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif rising_edge(clock) then
    q <= d;
  end if;
end process P4_NEW;

Uwaga: w tym ostatnim przykładzie uprościliśmy również test dotyczący resetu. Resety pływające, o wysokiej impedancji są dość rzadkie, aw większości przypadków ta uproszczona wersja działa do symulacji i syntezy.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow