vhdl
D-flip-flops (DFF) en vergrendelingen
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:
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 simpeleif clock'event and clock = '1' then
. De standaardrising_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
enfalling_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 inieee.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
ofreset
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.