"Preprozessor" Berechnungen in VHDL möglich?

OP #6064146
Lesenswert?

Hallo zusammen

Ich möchte ein Array mit Konstanten füllen.
Diese Konstanten sollen möglichst automatisch berechnet und befüllt 
werden.

Dazu habe ich momentan sowas:
1
  type t_boundaries_x is array (0 to led_count_x) of integer range 0 to display_width + 10;
2
  type t_boundaries_y is array (0 to led_count_y) of integer range 0 to display_heigth + 10;
3

4

5
  signal boundaries_x : t_boundaries_x;
6
  signal boundaries_y : t_boundaries_y;
7
....
8
  genboundsX :
9
  for I in 1 to led_count_x generate
10
    boundaries_x(I-1) <= ((display_width) / led_count_x + 1) * I;
11
  end generate;
12

13
  genboundsY :
14
  for I in 1 to led_count_y generate
15
    boundaries_y(I-1) <= ((display_heigth) / led_count_y + 1) * I;
16
  end generate;

Funktioniert grundsätzlich ganz gut. Aber...
Ich hätte gerne die Berechnung mit Komma.

Daher: die Berechnung: ((display_width) / led_count_x + 1) * I

Sollte mit hoher Genauigkeit durchgeführt werden.
Jedoch nur vor der Syntheze und nicht im FPGA selbst.

Gibt es dazu eine entsprechende Möglichkeit?

Danke
Moderator (Firma: Titel) Persönliche Seite #6064176
Lesenswert?

Holger K. schrieb:
> Gibt es dazu eine entsprechende Möglichkeit?
Nimm das math_real Package und die darin enthaltene Konvertierung zum 
integer. Etwa so wie dort zum Schluss die Tabelle berechnet wird:
http://www.lothar-miller.de/s9y/categories/31-DDFS

> Sollte mit hoher Genauigkeit durchgeführt werden.
Generell ist ein 32-Bit Float wegen der Mantisse, die nur 24 Bits hat, 
ungenauer als ein 32 Bit Integer. Allerdings hat der Float dank des 
Exponenten mehr Dynamik...
Gast #6064190
Lesenswert?

Ich verstehe die Frage in Richtung der Syntax die man braucht, um das 
Array per Präprozessor zu initialisieren.

Schreibe die Berechnung in einer VHDL function und weise die dann bei 
der Signaldefinition zu.
1
function meine_berechnung (display_width: integer, led_count: integer) return t_boundaries_x;
2

3
...
4

5
constant boundaries_x : t_boundaries_x := meine_berechnung(display_width, led_count);
OP #6064203
Lesenswert?

Vielen Dank für eure Antworten.

Wird das dann ins FPGA synthetisiert?
Ich möchte eigentlich die Berechnung quasi auf dem PC durchführen und 
das Array mittels aggregat funktion (generate section) vorfüllen so, 
dass das synthesetool nur noch konstanten vorfindet, ohne kommas.

Die Kommas sollen nur der Berechnung auf dem PC dienen.
#6064297
Lesenswert?

VHDL hotline schrieb im Beitrag #6064190:
> Schreibe die Berechnung in einer VHDL function und weise die dann bei
> der Signaldefinition zu.
> function meine_berechnung (display_width: integer, led_count: integer)
> return t_boundaries_x;
>
> ...
>
> constant boundaries_x : t_boundaries_x :=
> meine_berechnung(display_width, led_count);

Die Berechnung dieser Konstanten wird vom Synthesetool bzw. dem 
Simulator gemacht. Es gibt keinen Präprozessor.

Das Place & Route Tool bekommt vom Synthesetool eine Netzliste wo nur 
noch der Wert der Konstante drinsteht.

Um zu kontrollieren, was da so berechnet wurde, kannst du diesen Wert in 
deiner Function auch ausgeben lassen (landet dann in der Konsole bzw. 
dem Logfile) ohne das FPGA Ressourcen dazu nötig werden:
1
report "The display boundry in X direction is:" & LF & integer'image(boundaries_x) severity note;
#6064446
Lesenswert?

In VHDL gibt es den Begriff der "static expression".

Das klingt zwar so ähnlich wie das C-Schlüsselwort, ist aber etwas 
anderes (eher vergleichbar zu constexpr in C++).

Letzendlich heisst es nichts anderes, als daß ein VHDL-Konstrukt 
(eigentlich) nicht synthesitierbare Elemente enthalten darf, solange es 
so geschrieben wird, daß diese zur Synthesezeit vollständig (in 
synthesitierbare Elemente) evaluiert werden können:
1
architecture rtl of sintab is
2
    type sinus_table_type is array(natural range <>) of signed(31 downto 0);
3
    function sinus_table(start_value, end_value, step : real) return  sinus_table_type is
4
        constant table_size     : natural := 
5
                                  integer(ieee.math_real.ceil(
6
                                          end_value - start_value) / step);
7
        variable sintab : sinus_table_type(0 to table_size - 1);
8
    begin
9
        for i in sintab'low to sintab'high loop
10
            sintab(i) := to_signed(integer(
11
                              ieee.math_real.sin(start_value + real(i) * step) *
12
                              32767.0), sintab(i)'length);
13
        end loop;
14
        return sintab;
15
    end function sinus_table;
16

17
    function isin(sintab : sinus_table_type; us : signed) return signed is
18
        variable ret : signed(us'range);
19
    begin
20
        ret := sintab(to_integer(us mod sintab'length));
21
        return ret;
22
    end function isin;
23

24
    constant PI             : real := 3.1415926;
25
    constant stab           : sinus_table_type := sinus_table(0.0, 2.0 * PI, 0.01);
26
begin
27
    calc : process
28
    begin
29
        wait until rising_edge(clk);
30
        res <= isin(stab, arg);
31
    end process calc;
32
end architecture rtl;

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren