Zoeken…


Opmerkingen

D-flip-flops (DFF) en vergrendelingen zijn geheugenelementen. Een DFF bemonstert zijn invoer op de ene of de andere rand van zijn klok (niet beide), terwijl een vergrendeling transparant is op het ene niveau van inschakelen en op het andere opslaan. De volgende afbeelding illustreert het verschil:

DFF versus vergrendelingsgedrag

Het modelleren van DFF's of vergrendelingen in VHDL is eenvoudig, maar er zijn een paar belangrijke aspecten waarmee rekening moet worden gehouden:

  • De verschillen tussen VHDL-modellen van DFF's en vergrendelingen.

  • Hoe de randen van een signaal te beschrijven.

  • Hoe synchrone of asynchrone set of resets te beschrijven.

D-flip-flops (DFF)

In alle voorbeelden:

  • clk is de klok,
  • d is de invoer,
  • q is de uitvoer,
  • srst is een actieve hoog synchrone reset,
  • srstn is een actieve lage synchrone reset,
  • arst is een actieve hoge asynchrone reset,
  • arstn is een actieve lage asynchrone reset,
  • sset is een actieve hoog synchrone set,
  • ssetn is een actieve laag synchrone set,
  • aset is een actieve hoge asynchrone set,
  • asetn is een actieve lage asynchrone set

Alle signalen zijn van het type ieee.std_logic_1164.std_ulogic . De gebruikte syntaxis is degene die leidt tot correcte syntheseresultaten met alle logische synthesizers. Zie het Voorbeeld van klokranddetectie voor een discussie over alternatieve syntaxis.

Rising edge klok

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

Vallende klok

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

Stijgende flankklok, synchrone actieve hoge reset

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

Klok met stijgende flank, asynchrone actieve hoge reset

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

Falling edge klok, asynchrone actieve lage reset, synchrone actieve hoge set

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;

Stijgende flankklok, asynchroon actief hoog reset, asynchroon actief laag ingesteld

Opmerking: set heeft een hogere prioriteit dan 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;

Klinken

In alle voorbeelden:

  • en is het vrijgavesignaal,
  • d is de invoer,
  • q is de uitvoer,
  • srst is een actieve hoog synchrone reset,
  • srstn is een actieve lage synchrone reset,
  • arst is een actieve hoge asynchrone reset,
  • arstn is een actieve lage asynchrone reset,
  • sset is een actieve hoog synchrone set,
  • ssetn is een actieve laag synchrone set,
  • aset is een actieve hoge asynchrone set,
  • asetn is een actieve lage asynchrone set

Alle signalen zijn van het type ieee.std_logic_1164.std_ulogic . De gebruikte syntaxis is degene die leidt tot correcte syntheseresultaten met alle logische synthesizers. Zie het Voorbeeld van klokranddetectie voor een discussie over alternatieve syntaxis.

Actief hoog inschakelen

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

Actief laag inschakelen

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

Actief hoog inschakelen, synchroon actief hoog reset

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

Actief hoog inschakelen, asynchroon actief hoog reset

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

Actief laag vrijgeven, asynchroon actief laag reset, synchroon actief hoog ingesteld

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;

Actief hoog vrijgave, asynchroon actief hoog reset, asynchroon actief laag ingesteld

Opmerking: set heeft een hogere prioriteit dan 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;

Klokrand detectie

Het korte verhaal

Met VHDL 2008 en als het ieee.std_logic_1164.std_ulogic bit , boolean , ieee.std_logic_1164.std_ulogic of ieee.std_logic_1164.std_logic , kan een ieee.std_logic_1164.std_logic worden gecodeerd voor stijgende flank

  • 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

en voor vallende rand

  • 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

Dit zal zich gedragen zoals verwacht, zowel voor simulatie als synthese.

Opmerking: de definitie van een stijgende flank op een signaal van het type std_ulogic is een beetje ingewikkelder dan de simpele if clock'event and clock = '1' then . De standaard rising_edge functie heeft bijvoorbeeld een andere definitie. Zelfs als het waarschijnlijk geen verschil zal maken voor synthese, zou het er een kunnen maken voor simulatie.

Het gebruik van de standaardfuncties rising_edge en falling_edge wordt sterk aangemoedigd. Met eerdere versies van VHDL kan het gebruik van deze functies vereisen dat het gebruik van standaardpakketten (bijv. ieee.numeric_bit voor type bit ) expliciet wordt aangegeven of zelfs in een aangepast pakket wordt gedefinieerd.

Opmerking: gebruik niet de standaardfuncties rising_edge en falling_edge om randen van niet-kloksignalen te detecteren. Sommige synthesizers kunnen concluderen dat het signaal een klok is. Hint: het detecteren van een flank op een niet-kloksignaal kan vaak worden gedaan door het signaal in een schuifregister te bemonsteren en de bemonsterde waarden in verschillende stadia van het schuifregister te vergelijken.

Het lange verhaal

Een juiste beschrijving van de detectie van de randen van een kloksignaal is essentieel bij het modelleren van D-Flip-Flops (DFF). Een rand is per definitie een overgang van de ene waarde naar de andere. We kunnen bijvoorbeeld de stijgende flank definiëren van een signaal van het type bit (het standaard VHDL-genummerde type dat twee waarden heeft: '0' en '1' ) als de overgang van '0' naar '1' . Voor type boolean kunnen we het definiëren als een overgang van false naar true .

Vaak worden complexere typen gebruikt. Het type ieee.std_logic_1164.std_ulogic is bijvoorbeeld ook een genummerd type, net als bit of boolean , maar het heeft 9 waarden in plaats van 2:

Waarde Betekenis
'U' geïnitialiseerd
'X' Dwingen onbekend
'0' Laag niveau forceren
'1' Hoog niveau forceren
'Z' Hoge impedantie
'W' Zwak onbekend
'L' Zwak laag niveau
'H' Zwak hoog niveau
'-' Maakt niet uit

Het definiëren van een stijgende flank op een dergelijk type is een beetje complexer dan voor bit of boolean . We kunnen bijvoorbeeld beslissen dat het een overgang is van '0' naar '1' . Maar we kunnen ook beslissen dat het een overgang is van '0' of 'L' naar '1' of 'H' .

Opmerking: het is deze tweede definitie die de standaard gebruikt voor de functie rising_edge(signal s: std_ulogic) is gedefinieerd in ieee.std_logic_1164 .

Bij het bespreken van de verschillende manieren om randen te detecteren, is het dus belangrijk om het type signaal te overwegen. Het is ook belangrijk om rekening te houden met het modelleringsdoel: alleen simulatie of logische synthese? Laten we dit illustreren aan de hand van enkele voorbeelden:

Stijgende rand DFF met type bit

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

Technisch gezien, vanuit een puur simulatie-semantiek oogpunt, verwerkt P1 een stijgende flank geactiveerd DFF. De opdracht q <= d wordt inderdaad alleen uitgevoerd als:

  • clock gewijzigd (dit is wat de gevoeligheidslijst aangeeft) en
  • de huidige waarde van clock is '1' .

Aangezien de clock van het type bit is en het type bit alleen de waarden '0' en '1' , is dit precies wat we definiëren als een stijgende flank van een signaal van het type bit. Elke simulator zal dit model verwerken zoals we verwachten.

Opmerking: Voor logische synthesizers zijn de dingen een beetje complexer, zoals we later zullen zien.

Opgaande flank DFF met asynchrone actieve hoge reset en type bit

Om een asynchrone actieve hoge reset toe te voegen aan onze DFF, zou men iets kunnen proberen als:

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;

Maar dit werkt niet . De voorwaarde voor de uit te voeren opdracht q <= d moet zijn: een stijgende flank van de clock terwijl reset = '0' . Maar wat we hebben gemodelleerd is:

  • clock of reset of beide gewijzigd en
  • reset = '0' en
  • clock = '1'

Dat is niet hetzelfde: als reset verandert van '1' naar '0' terwijl clock = '1' de toewijzing uitgevoerd terwijl het geen stijgende flank van de clock .

In feite is er geen manier om dit in VHDL te modelleren zonder de hulp van een signaalattribuut:

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;

De clock'event is het signaalattribuut event toegevoerd aan signaal clock . Het evalueert als boolean en het is true als en slechts als het signaal clock tijdens het signaal updatefase die net vooraf aan de huidige uitvoeringsfase veranderd. Hierdoor P2_OK nu perfect wat we willen in simulatie (en synthese).

Synthese semantiek

Veel logische synthesizers identificeren signaalranddetecties op basis van syntactische patronen, niet op basis van de semantiek van het VHDL-model. Met andere woorden, ze overwegen hoe de VHDL-code eruit ziet, niet welk gedrag deze modelleert. Een van de patronen die ze allemaal herkennen is:

if clock = '1' and clock'event then

Dus zelfs in het voorbeeld van proces P1 moeten we het gebruiken als we willen dat ons model door alle logische synthesizers kan worden gesynthetiseerd:

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;

Het and clock'event deel van de conditie is volledig overbodig met de gevoeligheidslijst maar zoals sommige synthesizers het nodig hebben ...

Rising edge DFF met asynchrone actieve hoge reset en type std_ulogic

In dit geval kan het uitdrukken van de stijgende flank van de klok en de reset-toestand ingewikkeld worden. Als we de definitie van een stijgende flank behouden die we hierboven hebben voorgesteld en als we van mening zijn dat de reset actief is als deze '1' of 'H' , wordt het model:

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;

Opmerking: 'last_value is een ander signaalkenmerk dat de waarde retourneert die het signaal had vóór de laatste waardeverandering.

Helper functies

De VHDL 2008-standaard biedt verschillende helperfuncties om de detectie van signaalranden te vereenvoudigen, vooral bij typen met meerdere waarden, zoals std_ulogic . Het pakket std.standard definieert de functies rising_edge en falling_edge op typen bit en boolean en het pakket ieee.std_logic_1164 definieert ze op typen std_ulogic en std_logic .

Opmerking: bij eerdere versies van VHDL kan het gebruik van deze functies vereisen dat het gebruik van standaardpakketten (bijv. Ieee.numeric_bit voor type bit) expliciet wordt aangegeven of zelfs in een gebruikerspakket wordt gedefinieerd.

Laten we de vorige voorbeelden opnieuw bekijken en de helperfuncties gebruiken:

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;

Opmerking: in dit laatste voorbeeld hebben we ook de test op de reset vereenvoudigd. Zwevende, hoge impedantie, resets zijn vrij zeldzaam en in de meeste gevallen werkt deze vereenvoudigde versie voor simulatie en synthese.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow