Bereichsabfrage in Case

Gast #1517362
Lesenswert?

Hallo Leute,

habe folgende Frage an Euch: Ich möchte in einer Case-Abfrage einzelne
Adress-Werte abfragen, möchte aber gleichzeitig einen Adress-Bereich 
abfragen. Ist eine der drei folgenden Varianten zu bevorzugen ? Bin mir 
nicht sicher, ob die dritte Variante so überhaupt funktioniert ...
Oder gibt es gar eine elegantere Methode ? Vorab vielen Dank für Eure 
Meinungen und Vorschläge.

Grüsse,
Stefan123

1
-- Variante 1
2
process(clk)
3
begin
4
    wait until rising_edge(clk);
5
    
6
    case addr is
7
        when x"01" => ...
8
        when x"02" => ...
9
        when x"03" => ...
10
        when others => null;
11
    end case;
12
    
13
    if addr > x"07" and addr < x"0F" then
14
        ...
15
    end if;
16

17
end process;
18

19

20
-- Variante 2
21
process(clk)
22
begin
23
    wait until rising_edge(clk);
24
    
25
    case addr is
26
        when x"01" => ...
27
        when x"02" => ...
28
        when x"03" => ...
29
        when others => 
30
                if addr > x"07" and addr < x"0F" then
31
                    ...
32
                end if;
33
    end case; 
34

35
end process;
36

37

38
-- Variante 3
39
process(clk)
40
begin
41
    wait until rising_edge(clk);
42
    
43
    case addr is
44
        when x"01" => ...
45
        when x"02" => ...
46
        when x"03" => ...
47
        when (addr > x"07" & addr < x"0F") => ...
48
        when others => null;
49
               
50
    end case; 
51

52
end process;
Gast #1517514
Lesenswert?

Hi, also das ist eigendlich die eleganteste Methode:

process(clk)
begin
    if rising_edge(clk) then

        case addr is
            when x"01" => ...
            when x"02" => ...
            when x"03" => ...
            when x"07" | x"0F" => ...
            when others => null;

        end case;

    end if;

end process;
Gast #1517929
Lesenswert?

Das wäre noch evtl. eine Variante ?
1
-- Variante 4
2
process(clk)
3
begin
4
    wait until rising_edge(clk);
5
    
6
    case addr is
7
        when x"01" => ...
8
        when x"02" => ...
9
        when x"03" => ...
10
        when x"08" to x"0E" => ...
11
        when others => null;
12
               
13
    end case; 
14

15
end process;

Grüsse,
Stefan123
Moderator (Firma: Titel) Persönliche Seite #1517992
Lesenswert?

> when x"08" to x"0E" => ...
Das to geht nur, wenn addr ein Integer (oder ein Aufzählungstyp) 
ist.

Sowas ginge also:
1
signal seli : integer range 0 to 15;
2
:
3
  seli <= to_integer(unsigned(sel));
4
  process(seli, din) begin
5
    case seli is
6
      when 0 to 1  => dout1<=din(15 downto 12);
7
      when 2       => dout1<=din(11 downto  8);
8
      when 3 to 6  => dout1<=din( 7 downto  4);
9
      when 7 to 15 => dout1<=din( 3 downto  0);
10
      when others  => null;
11
    end case;
12
  end process;
Moderator (Firma: Titel) Persönliche Seite #1518803
Lesenswert?

> Funktioniert Variante 3 ?
Nein.
Siehe Beitrag "Re: Bereichsabfrage in Case"

>Welche der Varianten 1-3 würdest du verwenden?
Am lesbarsten dürfte Variante 2 sein.
Ich würde einfachh alle ausprobieren und dann die Laufzeiten und den 
Ressourcenbedarf ansehen...  ;-)

Sowas ginge evtl. auch:
1
-- Variante 5
2
process(clk)
3
begin
4
    wait until rising_edge(clk);  -- wozu hier der Takt? Das gibt einen Takt Latency!
5
    
6
    case to_integer(unsigned(addr)) is
7
        when to_integer(unsigned(x"01")) => ...
8
        when to_integer(unsigned(x"02")) => ...
9
        when to_integer(unsigned(x"03")) => ...
10
        when to_integer(unsigned(x"08")) to 
11
             to_integer(unsigned(x"0E")) => ...
12
        when others => null;
13
               
14
    end case; 
15

16
end process;

Variante 6 wäre, gleich alles mit if abzufragen...

BTW:
Wozu eigentlich der Takt im Prozess?
Gast #1518863
Lesenswert?

Variante 5 liefert folgende Fehlermeldung (Modelsim)
1
case to_integer(unsigned(addr)) is
2
        when to_integer(unsigned(x"01")) => ...

Error: Type conversion (to unsigned) can not have string literal 
operand.


Der Takt wird verwendet um aus der Adress-Dekodierung registrierte 
Signale (...) zu erzeugen.


Grüsse,
Stefan123
Moderator (Firma: Titel) Persönliche Seite #1518931
Lesenswert?

Mathi schrieb:
> Dann benutze einen hexint 16#Wert...
Ja, klar, warum nicht das naheliegendste zuerst... :-/
1
  process begin
2
    wait until rising_edge(clk);  
3
    case to_integer(unsigned(addr)) is
4
        when 16#01# => ...
5
        when 16#02# => ...
6
        when 16#03# => ...
7
        when 16#08# to 
8
             16#0E# => ...
9
        when others => null;
10
    end case; 
11
  end process;
Moderator (Firma: Titel) Persönliche Seite #1518960
Lesenswert?

Stefan123 schrieb:
> Frage mich nur, wieso der Compiler mit
>
1
> when to_integer(unsigned(x"01")) => ...
2
>
> nicht klar kommt. Ist doch eindeutig beschrieben.
Die Funktion unsigned() weiß nicht, welcher Typ x"01" denn genau ist. 
Es kann ja ein signed, ein unsigned, ein std_ulogic_vector oder was auch 
immer sein. 6 Typen stehen zur Auswahl.

Ein Qualifier hilft ein Stück weiter: to_integer( unsigned'(x"01") )
Hier wird der Funktion to_integer() explizit gesagt, dass x"01" ein 
unsigned-Vektor ist. Diese Umrechnung ginge also klar.
Aber case-when hat prinzipiell ein Problem mit der nicht statischen 
Funktion to_integer(), denn im case-when darf nur ein explizit 
statischer Wert stehen.
Gast #1518963
Lesenswert?

Naja, eine Sache ist ja nun doch noch etwas krückig:


Wenn man Adressen über Konstanten dekodieren möchte, dann wird das 
folgende Beispiel nicht funktionieren. Was kann man da machen ?

z.B.:

1
signal addr : unsigned(7 downto 0);
2

3
constant cAdd_x : unsigned(7 downto 0) := x"01";
4
constant cAdd_y : unsigned(7 downto 0) := x"02";
5
constant cAdd_z : unsigned(7 downto 0) := x"03";
6

7
process(clk)
8
begin
9
    if rising_edge(clk) then
10

11
        case to_integer(addr) is
12
            when 16#cAdd_x# to 16#cAdd_z# => ...            
13
            ...
14
        end case;
15

16
    end if;
17

18
end process;

Grüsse,
Stefan123
Gast #1518993
Lesenswert?

Ok, also Lothars Variante mit "unsigned' " lässt sich kompilieren, 
Modelsim beklagt sich "Case choice must be a locally static expression."
Aber das kann man ja in den Compile-Optionen ausschalten und stört auch 
nicht weiter für die Synthese.

Funktioniert:
1
case to_integer(unsigned(addr)) is
2
        when to_integer(unsigned'(x"01")) => ...


Ein weiterer Vorteil, die Adress-Bereichs-Abfrage nicht in den 
others-Zweig zu packen ist, dass Adress-Überlagerungen bemängelt werden.

Beispiel: wird von Modelsim bemängelt
1
case to_integer(unsigned(addr)) is
2
        when to_integer(unsigned'(x"01")) => ...
3
        when to_integer(unsigned'(x"01")) to to_integer(unsigned'(x"02") =>


Beispiel: wird nicht von Modelsim bemängelt
1
case to_integer(unsigned(addr)) is
2
        when to_integer(unsigned'(x"01")) => ...
3
        when others =>
4
             if addr >=x"01" and addr <= x"02" then
Moderator (Firma: Titel) Persönliche Seite #1519030
Lesenswert?

>> Was kann man da machen ?
1
signal addr : unsigned(7 downto 0);
2

3
constant cAdd_x : unsigned(7 downto 0) := x"01";
4
constant cAdd_y : unsigned(7 downto 0) := x"02";
5
constant cAdd_z : unsigned(7 downto 0) := x"03";
6

7
process(clk)
8
begin
9
    if rising_edge(clk) then
10
        case to_integer(addr) is
11
            when to_integer(cAdd_x) to to_integer(cAdd_z) => ...            
12
            ...
13
        end case;
14
    end if;
15
end process;


> Beispiel: wird von Modelsim bemängelt
Klar, denn es gibt zwei Pfade für addr=x"01".

> Beispiel: wird nicht von Modelsim bemängelt
Nur wird für addr=x"01" der others-Fall nicht ausgeführt...  :-o
Gast #1540686
Lesenswert?

Hallo Lothar,

>Aber case-when hat prinzipiell ein Problem mit der nicht statischen
>Funktion to_integer(), denn im case-when darf nur ein explizit
>statischer Wert stehen.

eine Frage hätte ich da noch:
1
process(clk)
2
begin
3
    if rising_edge(clk) then
4
        case to_integer(addr) is
5
            when to_integer(cAdd_x) to to_integer(cAdd_z) => ...            
6
            ...
7
        end case;
8
    end if;
9
end process;


Mit Modelsim erhalte ich folgende Warnung:

"Case choice must be a locally static expression"

Wenn ich jedoch versuche, einen integerierten Logic-Analyzer einzubauen 
(Altera Signaltap), so erhalte ich folgende Fehlermeldung:

ERROR: case choice must be a locally static expression (VHDL-1438)


Wie passt das zusammen? Wieso gibt Modelsim (mit aktiviertem "Check for 
Synthesis") eine Warnung aus, während es beim Einbau des Signaltap-Cores 
zu einem Abbruch kommt ?
Gibt es einen Ausweg aus dem Schlamassel, um dennoch die Bereichsabfrage 
hinzubekommen ?

Grüsse,
Stefan123

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