Forum: FPGA, VHDL & Co. Array-Länge flexibel


von zu Gast (Gast)


Lesenswert?

Ich würde gerne mehr Struktur in meine Programme bekommen. Gestern habe 
ich an der Initialisierung von angeschlossener Hardware gesessen. Also 
Sachen die an i2c oder spi hängen und am Anfang erst eingestellt werden 
müssen.
Da hatte ich bis jetzt ewig lange statemachines. Ich versuche das über 
ein record, wo die init-Daten übersichtlich drin sind und was von einer 
viel kleineren statemachine benutzt wird.

Mein Problem ist aber, dass ich keine Ahnung habe, ob und wie ich die 
Länge der init_daten automatisch an die vorgegebenen Konstanten anpassen 
kann.
1
type t_init_data is
2
  record
3
     slv8_adr  : unsigned(7 downto 0);
4
     slv8_dat   : unsigned(7 downto 0);
5
     i_delay     : integer range 0 to 100; --in clocks. ms wäre auch ne option?
6
  end record;
7
8
type t_init_datas is array (0 to 2) of t_init_data;
9
10
type t_init_states is ( init_idle, init_busy );
11
-------------------------------------------------------
12
signal i_init_length   : integer range 0 to t_init_datas'length;
13
oder so Pause zwischen Werten
14
signal init_state   : t_init_states := init_idle;
15
signal init_datas    : t_init_datas := ((slv8_adr=>x"00", slv8_dat=>x"42", i_delay=>3), --0
16
            (slv8_adr=>x"01", slv8_dat=>x"14", i_delay=>0), --1
17
            (slv8_adr=>x"42", slv8_dat=>x"23", i_delay=>5) --2
18
          );


Ich hoffe ihr versteht, was ich für ein Problem habe.
1
type t_init_datas is array (0 to 2) of t_init_data;
soll nicht fest auf Länge 3 stehen sondern ich möchte das alles nur über 
die Initialisierung des Record machen. Henne und Ei.

Gibt es da eine elegante und übersichtliche Methode?

von Andreas (Gast)


Lesenswert?

Erste Frage, Simulation oder Synthese?


zu Gast schrieb:
> Ich würde gerne mehr Struktur in meine Programme bekommen.

Naja mittels VHDL beschreibt man und programmiert nicht. Beim 
Programmieren nutzt du den durch den Prozessorhersteller vorgegeben 
Befehlssatz. Beim FPGA hingegen kannst du z.B. genau solch einen 
Befehlssatz definieren.

zu Gast schrieb:
> Ich hoffe ihr versteht, was ich für ein Problem habe.type t_init_datas
> is array (0 to 2) of t_init_data;

Wer hindert dich daran einen kleinen Spezial Prozessor zu entwerfen. 
Daten bekommt er aus einem ROM (IP Generator deines FPGAs) und dann 
arbeitet die FSM genau diesen ROM ab und initialisiert Device für 
Device.

Wie gut sind deine VHDL Kenntnisse, was waren deine Projekte bis jetzt?

von Pat A. (patamat)


Lesenswert?

Unconstraint Array:

type t_init_datas is array (natural range <>) of t_init_data;

von zu Gast (Gast)


Lesenswert?

Kenntnisse würde ich sagen über das Anfangsstadium hinaus, aber kein 
Experte. Sonst würde ich ja auch so was nicht fragen müssen ;-)))
Aber auch so weit, dass die reflexartige Erwähnung von HDL und Software 
nicht unbedingt hilfreich ist.
Es geht um die Sythese, denn ich will ja die angeschlossene Hardware 
etwas übersichtlicher initialisieren.
Das ganze auch als unabhängig synthetisierbarer rtl Code.

type t_init_datas is array (natural range <>) of t_init_data;. Kannst du 
das an meinem Beispiel etwas weiter konkretisieren? Denn damit habe ich 
versucht ans Ziel zu kommen und bin gescheitert, denn muss ich nicht 
trotzdem die Gesamtlänge im vorraus wissen?

von Pat A. (patamat)


Lesenswert?

zu Gast schrieb:
> denn muss ich nicht
> trotzdem die Gesamtlänge im vorraus wissen?

Nein, das ist ja gerade der Trick an der Sache.

Ändere mal Deinen Code in dieser einen Zeile und Du wirst sehen, er 
funktioniert genauso wie vorher.

Und noch ein Tipp: An die Größe des Arrays kommst Du über das Attribut 
'length', wie z.B.:
1
constant my_array_length: integer := init_datas'length;

von zu Gast (Gast)


Lesenswert?

Hmm. Also nicht dass wir aneinander vorbeireden mal ganz konkret (s.u.): 
:-)
Wenn ich bei

signal init_datas    : t_init_datas(0 to 2) := ((slv8_adr=>x"00", 
slv8_dat=>x"42", i_delay=>3), --0
                (slv8_adr=>x"01", slv8_dat=>x"14", i_delay=>0), --1
                 (slv8_adr=>x"42", slv8_dat=>x"23", i_delay=>5) --2
              );

nicht angebe wie groß das Array denn nun ist, gibt es "init_datas" does 
not have an index constraint"
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity initialize is
6
  port(   isl_clk    : in std_logic;
7
    isl_rst    : in std_logic;
8
    oslv8_data   : out std_logic_vector(7 downto 0); --hier nur auf leds nachher spi
9
    isl_init_start  : in std_logic; --initialisierung starten
10
    osl_init_busy  : out std_logic := '0' );
11
  
12
end initialize;
13
14
15
architecture rtl of initialize is
16
-------------------------------------------------------
17
--package?
18
-------------------------------------------------------
19
type t_init_data is
20
  record
21
     slv8_adr  : unsigned(7 downto 0);
22
     slv8_dat   : unsigned(7 downto 0);
23
     i_delay     : integer range 0 to 100; --in clocks. ms wäre auch ne option?
24
  end record;
25
26
type t_init_datas is array (natural range <>) of t_init_data;
27
28
29
type t_init_states is ( init_idle, init_busy );
30
-------------------------------------------------------
31
32
signal i_delay_counter   : integer range 0 to 1000; --maximal 1000 Takte/ms oder so Pause zwischen Werten
33
signal init_state   : t_init_states := init_idle;
34
signal init_datas    : t_init_datas(0 to 2) := ((slv8_adr=>x"00", slv8_dat=>x"42", i_delay=>3), --0
35
                (slv8_adr=>x"01", slv8_dat=>x"14", i_delay=>0), --1
36
                 (slv8_adr=>x"42", slv8_dat=>x"23", i_delay=>5) --2
37
              );
38
signal i_init_length   : integer range 0 to init_datas'length;
39
begin
40
41
init_hardware : process (isl_rst,isl_clk) 
42
begin
43
  if( isl_rst = '1' ) then
44
    init_state   <= init_idle;
45
    osl_init_busy <= '0';  --oder lieber '1'????
46
  elsif( isl_clk'event and isl_clk = '1' ) then
47
    case init_state is
48
      when init_idle =>
49
        i_init_length <= 0;
50
        i_delay_counter <= 0;
51
        if( isl_init_start = '1') then
52
          init_state <= init_busy;
53
          osl_init_busy <= '1';  --hm doppelt?
54
        end if;
55
56
      when init_busy =>        
57
        if( i_delay_counter = 0) then
58
          oslv8_data <= std_logic_vector(init_datas(i_init_length).slv8_adr); --ist ja nur zum ausprobieren. Hier auf spi schicken
59
          i_delay_counter <= init_datas(i_init_length).i_delay;
60
          if( i_init_length < init_datas'length ) then
61
            i_init_length <= i_init_length + 1;
62
          else
63
            init_state <= init_idle;   
64
            osl_init_busy <= '0';  --initialisierung ist durch  
65
          end if;
66
        else
67
          i_delay_counter <= i_delay_counter - 1;
68
        end if;
69
    end case;
70
  end if;
71
end process init_hardware;
72
73
end rtl;

von Pat A. (patamat)


Lesenswert?

Tatsächlich, funktioniert mit Signalen nicht. Aber mit dem Umweg über 
eine Konstante geht's:
1
constant c_init_datas: t_init_datas := (
2
    (slv8_adr=>x"00", slv8_dat=>x"42", i_delay=>3), --0
3
    (slv8_adr=>x"01", slv8_dat=>x"14", i_delay=>0), --1
4
    (slv8_adr=>x"42", slv8_dat=>x"23", i_delay=>5)  --2
5
);
6
7
signal init_datas : t_init_datas(c_init_datas'range) := c_init_datas;

von zu Gast (Gast)


Lesenswert?

Sehr schön!
Allerbesten Dank! Hatte auch mit einem constanten Block rum probiert, 
war aber wohl etwas zu doof - offensichtlich.

von Pat A. (patamat)


Lesenswert?

Dass es mit Signalen so direkt nicht funktioniert, hatte ich auch noch 
nicht gewusst ;-)

Aber da Du auf das Signal 'init_datas' sowieso nur lesend zugreifst, 
kannst Du auch gleich die Konstante 'c_init_datas' anstatt verwenden.

Und noch eine Falle lauert: das Attribut 'length' gibt die Länge an; in 
diesem Fall 3. Dein Indexsignal 'i_init_length' sollte also nur von 0 
bis 'length' -1 laufen:
1
signal i_init_length   : integer range 0 to c_init_datas'length -1;

Sonst kann es passieren, dass Du auf das 4. Arrayelement zugreifst, was 
jedoch nicht existiert. Die Synthese geht darüber in der Regel großzügig 
hinweg, obwohl es ein undefiniertes Verhalten bedeutet. Die Simulation 
ist da strenger; die haut Dir das, so wie es sich gehört, um die Ohren 
;-)

von zu Gast (Gast)


Lesenswert?

Logischer, doch hier weiser Einwand von dir. :-)
Werde heute abend mal mit dem Wissensschub weiter werkeln.

von Weltbester FPGA-Pongo (Gast)


Lesenswert?

Pat A. schrieb:
> Dass es mit Signalen so direkt nicht funktioniert, hatte ich auch noch
> nicht gewusst ;-)
Die können ja beliebige Breiten annehmen und Ich glaube, dass die 
Synthese so viel Variable Information nicht handhaben kann. Das gibt es 
ja auch noch an anderer Stelle, wo sie aussteigt und Deklarationen nicht 
auflösen kann.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.