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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow