vhdl
D-Flip-Flops (DFF) och spärrar
Sök…
Anmärkningar
D-Flip-Flops (DFF) och spärrar är minneselement. En DFF samplar sin ingång på den ena eller den andra kanten av sin klocka (inte båda) medan en spärr är transparent på en nivå av dess aktivering och memorering på den andra. Följande figur illustrerar skillnaden:
Det är enkelt att modellera DFF: er eller spärrar i VHDL men det är några viktiga aspekter som måste beaktas:
Skillnaderna mellan VHDL-modeller av DFF: er och spärrar.
Hur man beskriver kanterna på en signal.
Hur man beskriver synkron eller asynkron uppsättning eller återställning.
D-Flip-Flops (DFF)
I alla exempel:
-
clkär klockan, -
där ingången, -
qär utgången, -
srstär en aktiv hög synkron återställning, -
srstnär en aktiv lågsynkron återställning, -
arstär en aktiv hög asynkron återställning, -
arstnär en aktiv låg asynkron återställning, -
ssetär en aktiv högsynkronuppsättning, -
ssetnär en aktiv lågsynkronuppsättning, -
asetär en aktiv hög asynkron uppsättning, -
asetnär en aktiv låg-asynkron uppsättning
Alla signaler är av typen ieee.std_logic_1164.std_ulogic . Syntaxen som används är den som leder till korrekta syntesresultat med alla logiska synteser. Se exempel på klockkantdetektering för en diskussion om alternativ syntax.
Stigande klocka
process(clk)
begin
if rising_edge(clk) then
q <= d;
end if;
end process;
Fallande kantklocka
process(clk)
begin
if falling_edge(clk) then
q <= d;
end if;
end process;
Stigande klocka, synkron aktiv hög återställning
process(clk)
begin
if rising_edge(clk) then
if srst = '1' then
q <= '0';
else
q <= d;
end if;
end if;
end process;
Stigande klocka, asynkron aktiv hög återställning
process(clk, arst)
begin
if arst = '1' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
Fallande kantklocka, asynkron aktiv låg återställning, synkron aktiv höguppsättning
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;
Stigande klocka, asynkron aktiv hög återställning, asynkron aktiv låg inställning
Obs: set har högre prioritet än återställning
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;
Latches
I alla exempel:
-
enär aktiveringssignalen, -
där ingången, -
qär utgången, -
srstär en aktiv hög synkron återställning, -
srstnär en aktiv lågsynkron återställning, -
arstär en aktiv hög asynkron återställning, -
arstnär en aktiv låg asynkron återställning, -
ssetär en aktiv högsynkronuppsättning, -
ssetnär en aktiv lågsynkronuppsättning, -
asetär en aktiv hög asynkron uppsättning, -
asetnär en aktiv låg-asynkron uppsättning
Alla signaler är av typen ieee.std_logic_1164.std_ulogic . Syntaxen som används är den som leder till korrekta syntesresultat med alla logiska synteser. Se exempel på klockkantdetektering för en diskussion om alternativ syntax.
Aktiv hög aktivering
process(en, d)
begin
if en = '1' then
q <= d;
end if;
end process;
Aktiv låg aktivering
process(en, d)
begin
if en = '0' then
q <= d;
end if;
end process;
Aktiv hög aktivering, synkron aktiv hög återställning
process(en, d)
begin
if en = '1' then
if srst = '1' then
q <= '0';
else
q <= d;
end if;
end if;
end process;
Aktiv hög aktivering, asynkron aktiv hög återställning
process(en, d, arst)
begin
if arst = '1' then
q <= '0';
elsif en = '1' then
q <= d;
end if;
end process;
Aktiv låg aktivering, asynkron aktiv låg återställning, synkron aktiv hög uppsättning
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;
Aktiv hög aktivering, asynkron aktiv hög återställning, asynkron aktiv låg inställning
Obs: set har högre prioritet än återställning
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;
Klockkantdetektering
Den korta historien
Med VHDL 2008 och om klocktypen är bit , boolean , ieee.std_logic_1164.std_ulogic eller ieee.std_logic_1164.std_logic , kan en ieee.std_logic_1164.std_logic kodas för stigande kant
-
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
och för fallande kant
-
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
Detta kommer att bete sig som förväntat, både för simulering och syntes.
Obs: definitionen av en stigande kant på en signal av typen
std_ulogicär lite mer komplex än den enklaif clock'event and clock = '1' then. Standardenrising_edgefunktion, till exempel, har en annan definition. Även om det förmodligen inte kommer att göra någon skillnad för syntesen, kan det göra en för simulering.
Användning av rising_edge och falling_edge uppmuntras starkt. Med tidigare versioner av VHDL användningen av dessa funktioner kan kräva att uttryckligen förklara användningen av standardpaket (t.ex. ieee.numeric_bit för typ bit ) eller till och med att definiera dem i en anpassad paket.
Obs:
rising_edgefalling_edgestandardfunktionernarising_edgeochfalling_edgeför att upptäcka kanter på icke-klocksignaler. Vissa synthesizers kan dra slutsatsen att signalen är en klocka. Tips: detektering av en kant på en icke-klocksignal kan ofta göras genom att sampla in signalen i ett skiftregister och jämföra samplade värden i olika steg i skiftregistret.
Den långa berättelsen
Att korrekt beskriva detekteringen av kanterna på en klocksignal är avgörande vid modellering av D-Flip-Flops (DFF). En kant är per definition en övergång från ett visst värde till ett annat. Till exempel kan vi definiera stigningen på en signal av bit (den standardiserade VHDL-typen som tar två värden: '0' och '1' ) som övergången från '0' till '1' . För typ boolean vi definiera det som en övergång från false till true .
Ofta används mer komplexa typer. ieee.std_logic_1164.std_ulogic är till exempel också en uppräknad typ, precis som bit eller boolean , men har 9 värden istället för 2:
| Värde | Menande |
|---|---|
'U' | oinitierad |
'X' | Tvinga okänt |
'0' | Tvinga låg nivå |
'1' | Tvinga hög nivå |
'Z' | Hög impedans |
'W' | Svag okänd |
'L' | Svag låg nivå |
'H' | Svag hög nivå |
'-' | Bryr sig inte |
Att definiera en stigande kant på en sådan typ är lite mer komplex än för bit eller boolean . Vi kan till exempel bestämma att det är en övergång från '0' till '1' . Men vi kan också bestämma att det är en övergång från '0' eller 'L' till '1' eller 'H' .
Obs: det är denna andra definition som standarden använder för den
rising_edge(signal s: std_ulogic)-funktionen definierad iieee.std_logic_1164.
När man diskuterar olika sätt att upptäcka kanter är det alltså viktigt att beakta signalens typ. Det är också viktigt att ta hänsyn till modelleringsmålet: endast simulering eller logisk syntes? Låt oss illustrera detta med några exempel:
Rising edge DFF med typbit
signal clock, d, q: bit;
...
P1: process(clock)
begin
if clock = '1' then
q <= d;
end if;
end process P1;
Tekniskt sett, på ren simuleringssemantik synvinkel, process P1 modellerar en stigande kant utlöst DFF. Faktum är att q <= d tilldelningen utförs om och bara om:
-
clockändrats (detta är vad känslighetslistan uttrycker) och -
clocknuvarande värde är'1'.
Eftersom clock är av typbit och typbit har bara värden '0' och '1' , är det exakt vad vi definierade som en stigande kant av en signal av typbit. Varje simulator hanterar den här modellen som vi förväntar oss.
Obs: För logiska synthesizers är sakerna lite mer komplexa, som vi kommer att se senare.
Rising edge DFF med asynkron aktiv hög återställning och typbit
För att lägga till en asynkron aktiv hög återställning till vår DFF kan man prova något som:
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;
Men detta fungerar inte . Villkoret för att q <= d tilldelningen ska utföras ska vara: en stigande clock medan reset = '0' . Men det vi modellerade är:
-
clockellerreseteller båda ändrade och -
reset = '0'och -
clock = '1'
Vilket är inte detsamma: om reset ändras från '1' till '0' medan clock = '1' kommer tilldelningen att utföras medan det inte är en stigande clock .
Det finns faktiskt inget sätt att modellera detta i VHDL utan hjälp av ett signalattribut:
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;
Den clock'event är signalattribut event tillämpas på clock . Det utvärderas som en boolean och det är true om och endast om clock ändras under signaluppdateringsfasen som bara föregick den nuvarande genomförandefasen. Tack vare detta P2_OK process P2_OK nu perfekt vad vi vill ha i simulering (och syntes).
Syntesemantik
Många logiska syntetisatorer identifierar signalkantsdetekteringar baserade på syntaktiska mönster, inte på semantiken i VHDL-modellen. Med andra ord överväger de hur VHDL-koden ser ut, inte vilket beteende den modellerar. Ett av mönstren som de alla känner igen är:
if clock = '1' and clock'event then
Så även i exemplet med process P1 bör vi använda den om vi vill att vår modell ska syntetiseras av alla logiska synteser:
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;
Den and clock'event delen av tillståndet är helt överflödigt med känslighetslistan men eftersom vissa synthesizers behöver det ...
Rising edge DFF med asynkron aktiv hög återställning och typ std_ulogic
I detta fall kan det bli komplicerat att uttrycka klockans stigande kant och återställningstillståndet. Om vi behåller definitionen av en stigande kant som vi föreslog ovan och om vi anser att återställningen är aktiv om den är '1' eller 'H' blir modellen:
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;
Obs:
'last_valueär ett annat'last_valuesom returnerar värdet som signalen hade innan den senaste värdeförändringen.
Hjälparfunktioner
VHDL 2008-standarden erbjuder flera hjälpfunktioner för att förenkla upptäckten av signalkanter, särskilt med flera värderade uppräknade typer som std_ulogic . std.standard paketet definierar rising_edge och falling_edge på typer bit och boolean och paketet ieee.std_logic_1164 definierar dem på typerna std_ulogic och std_logic .
Obs: med tidigare versioner av VHDL kan användningen av dessa funktioner kräva att de uttryckligen förklarar användningen av standardpaket (t.ex. ieee.numeric_bit för typbit) eller till och med för att definiera dem i ett användarpaket.
Låt oss gå igenom de tidigare exemplen och använda hjälpfunktionerna:
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;
Obs! I detta sista exempel förenklar vi också testet på återställningen. Flytande, hög impedans, återställningar är ganska sällsynta och i de flesta fall fungerar denna förenklade version för simulering och syntes.
