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


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow