vhdl
Beschermde types
Zoeken…
Opmerkingen
Voorafgaand aan VHDL 1993 konden twee gelijktijdige processen alleen communiceren met signalen. Dankzij de simulatie-semantiek van de taal die alleen signalen tussen simulatiestappen bijwerkt, was het resultaat van een simulatie deterministisch: het was niet afhankelijk van de volgorde gekozen door de simulatieplanner om de processen uit te voeren.
[In feite is dit niet 100% waar. Processen kunnen ook communiceren met behulp van bestandsinvoer / -uitvoer. Maar als een ontwerper het determinisme in gevaar zou brengen door bestanden te gebruiken, zou het niet echt een vergissing kunnen zijn.]
De taal was dus veilig. Behalve met opzet was het bijna onmogelijk om niet-deterministische VHDL-modellen te ontwerpen.
VHDL 1993 introduceerde gedeelde variabelen en het ontwerpen van niet-deterministische VHDL-modellen werd heel eenvoudig.
VHDL 2000 introduceerde beschermde types en de beperking dat gedeelde variabelen van het beschermde type moeten zijn.
In VHDL lijken beschermde typen het meest op het concept van objecten in Object Oriented (OO) -talen. Ze implementeren de inkapseling van gegevensstructuren en hun methoden. Ze garanderen ook de exclusieve en atomaire toegang tot hun gegevensleden. Dit voorkomt niet-determinisme niet volledig, maar voegt tenminste exclusiviteit en atomiciteit toe aan de gedeelde variabelen.
Beschermde typen zijn erg handig bij het ontwerpen van VHDL-modellen op hoog niveau die alleen voor simulatie zijn bedoeld. Ze hebben verschillende zeer goede eigenschappen van OO-talen. Door ze vaak te gebruiken, wordt de code beter leesbaar, onderhoudbaar en herbruikbaar.
Opmerkingen:
- Sommige ketens van simulatietools geven standaard alleen waarschuwingen wanneer een gedeelde variabele niet van een beschermd type is.
- Sommige synthesetools ondersteunen geen beschermde types.
- Sommige synthesetools bieden beperkte ondersteuning voor gedeelde variabelen.
- Je zou kunnen denken dat gedeelde variabelen niet bruikbaar zijn om hardware te modelleren en gereserveerd moeten worden voor code-instrumentatie zonder bijwerkingen. Maar de VHDL-patronen die door verschillende EDA-leveranciers worden geadviseerd om het geheugenvlak van RAM-geheugen met meerdere poorten te modelleren, gebruiken gedeelde variabelen. Dus ja, gedeelde variabelen kunnen in bepaalde omstandigheden worden gesynthetiseerd.
Een pseudo-willekeurige generator
Peudo-willekeurige generatoren zijn vaak handig bij het ontwerpen van simulatieomgevingen. Het volgende VHDL-pakket laat zien hoe u beveiligde typen kunt gebruiken om een pseudo-willekeurige generator van boolean
, bit
en bit_vector
te ontwerpen. Het kan eenvoudig worden uitgebreid om ook willekeurige std_ulogic_vector
te genereren, signed
, unsigned
. Uitbreiden om willekeurige gehele getallen met willekeurige grenzen en een uniforme verdeling te genereren, is een beetje lastiger maar uitvoerbaar.
De pakketverklaring
Een beschermd type heeft een verklaring waarin alle openbare subprogramma-accessors worden gedeclareerd. Voor onze random generator zullen we één seed-initialisatieprocedure en drie onzuivere functies openbaar maken die een willekeurige boolean
, bit
of bit_vector
retourneren. Merk op dat de functies niet puur kunnen zijn, omdat verschillende aanroepen van elk van hen, met dezelfde parameters, verschillende waarden kunnen retourneren.
-- 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;
Het pakket lichaam
Het beschermde type body definieert de interne datastructuren (leden) en de subprogramma-body's. Onze willekeurige generator is gebaseerd op een 128-bits Lineair Feedback Shift Register (LFSR) met vier tikken. De state
variabele slaat de huidige stand van de LFSR. Een prive- throw
procedure verschuift de LFSR elke keer dat de generator wordt gebruikt.
-- 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;
De willekeurige generator kan vervolgens worden gebruikt in een OO-stijl zoals in:
-- 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