vhdl
Skyddade typer
Sök…
Anmärkningar
Före VHDL 1993 kunde två samtidiga processer endast kommunicera med signaler. Tack vare simuleringssemantiken för språket som endast uppdaterar signaler mellan simuleringssteg, var resultatet av en simulering deterministisk: det berodde inte på den ordning som valts av simuleringsschemaläggaren för att utföra processerna.
[Faktum är att detta inte är 100% sant. Processer kan också kommunicera med filinmatning / -utgång. Men om en designer kompromissade med determinismen genom att använda filer, kan det inte riktigt vara ett misstag.]
Språket var således säkert. Förutom avsiktligt var det nästan omöjligt att designa icke-deterministiska VHDL-modeller.
VHDL 1993 introducerade delade variabler och att designa icke-deterministiska VHDL-modeller blev mycket enkelt.
VHDL 2000 införde skyddade typer och begränsningen att delade variabler måste vara av skyddad typ.
I VHDL är skyddade typer det som liknar mest begreppet objekt på objektorienterade (OO) språk. De implementerar inkapslingen av datastrukturer och deras metoder. De garanterar också exklusiv och atomisk åtkomst till sina dataledamöter. Detta förhindrar inte helt icke-determinism men åtminstone tillför exklusivitet och atomicitet till de delade variablerna.
Skyddade typer är mycket användbara vid utformning av VHDL-modeller på hög nivå endast avsedda för simulering. De har flera mycket bra egenskaper hos OO-språk. Att använda dem gör koden ofta läsbar, underhållbar och återanvändbar.
Anmärkningar:
- Vissa simuleringsverktygskedjor ger som standard bara varningar när en delad variabel inte är av en skyddad typ.
- Vissa syntesverktyg stöder inte skyddade typer.
- Vissa syntesverktyg har ett begränsat stöd för delade variabler.
- Man kan tro att delade variabler inte är användbara för att modellera hårdvara och ska reserveras för kodinstrumentation utan biverkningar. Men VHDL-mönstren som rekommenderas av flera EDA-leverantörer att modellera minnesplanet för flera portar Random Access Memories (RAM) använder delade variabler. Så, ja, delade variabler kan vara syntetiserbara under vissa omständigheter.
En pseudo-slumpmässig generator
Peudo-slumpmässiga generatorer är ofta användbara vid utformning av simuleringsmiljöer. Följande VHDL-paket visar hur man använder skyddade typer för att designa en pseudo-slumpmässig generator av boolean
, bit
och bit_vector
. Det kan enkelt utökas till att även generera slumpmässig std_ulogic_vector
, signed
, unsigned
. Att utöka det för att generera slumpmässiga heltal med godtyckliga gränser och en enhetlig distribution är lite svårare men genomförbart.
Paketdeklarationen
En skyddad typ har en deklaration där alla offentliga underprogramtillträdare deklareras. För vår slumpmässiga generator kommer vi att offentliggöra ett fröinitieringsförfarande och tre orena funktioner som returnerar en slumpmässig boolean
, bit
eller bit_vector
. Observera att funktionerna inte kan vara rena eftersom olika samtal för någon av dem, med samma parametrar, kan returnera olika värden.
-- file rnd_pkg.vhd
package rnd_pkg is
type rnd_generator is protected
procedure init(seed: bit_vector);
impure function get_boolean return boolean;
impure function get_bit return bit;
impure function get_bit_vector(size: positive) return bit_vector;
end protected rnd_generator;
end package rnd_pkg;
Paketet kroppen
Det skyddade organet definierar de inre datastrukturerna (medlemmarna) och delprogramorganen. Vår slumpmässiga generator är baserad på ett 128-bitars Linear Feedback Shift Register (LFSR) med fyra kranar. Den state
variabel lagrar nuvarande tillståndet för LFSR. En privat throw
förfarande skiftar LFSR varje gång generatorn används.
-- file rnd_pkg.vhd
package body rnd_pkg is
type rnd_generator is protected body
constant len: positive := 128;
constant default_seed: bit_vector(1 to len) := X"8bf052e898d987c7c31fc71c1fc063bc";
type tap_array is array(natural range <>) of positive range 1 to len;
constant taps: tap_array(0 to 3) := (128, 126, 101, 99);
variable state: bit_vector(1 to len) := default_seed;
procedure throw(n: positive := 1) is
variable tmp: bit;
begin
for i in 1 to n loop
tmp := '1';
for j in taps'range loop
tmp := tmp xnor state(taps(j));
end loop;
state := tmp & state(1 to len - 1);
end loop;
end procedure throw;
procedure init(seed: bit_vector) is
constant n: natural := seed'length;
constant tmp: bit_vector(1 to n) := seed;
constant m: natural := minimum(n, len);
begin
state := (others => '0');
state(1 to m) := tmp(1 to m);
end procedure init;
impure function get_boolean return boolean is
constant res: boolean := state(len) = '1';
begin
throw;
return res;
end function get_boolean;
impure function get_bit return bit is
constant res: bit := state(len);
begin
throw;
return res;
end function get_bit;
impure function get_bit_vector(size: positive) return bit_vector is
variable res: bit_vector(1 to size);
begin
if size <= len then
res := state(len + 1 - size to len);
throw(size);
else
res(1 to len) := state;
throw(len);
res(len + 1 to size) := get_bit_vector(size - len);
end if;
return res;
end function get_bit_vector;
end protected body rnd_generator;
end package body rnd_pkg;
Den slumpmässiga generatorn kan sedan användas i en OO-stil som i:
-- file rnd_sim.vhd
use std.env.all;
use std.textio.all;
use work.rnd_pkg.all;
entity rnd_sim is
end entity rnd_sim;
architecture sim of rnd_sim is
shared variable rnd: rnd_generator;
begin
process
variable l: line;
begin
rnd.init(X"fe39_3d9f_24bb_5bdc_a7d0_2572_cbff_0117");
for i in 1 to 10 loop
write(l, rnd.get_boolean);
write(l, HT);
write(l, rnd.get_bit);
write(l, HT);
write(l, rnd.get_bit_vector(10));
writeline(output, l);
end loop;
finish;
end process;
end architecture sim;
$ mkdir gh_work
$ ghdl -a --std=08 --workdir=gh_work rnd_pkg.vhd rnd_sim.vhd
$ ghdl -r --std=08 --workdir=gh_work rnd_sim
TRUE 1 0001000101
FALSE 0 1111111100
TRUE 1 0010110010
TRUE 1 0010010101
FALSE 0 0111110100
FALSE 1 1101110010
TRUE 1 1011010110
TRUE 1 0010010010
TRUE 1 1101100111
TRUE 1 0011100100
simulation finished @0ms