Forum: FPGA, VHDL & Co. Case konstrukt


von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Hallo liebe Leute,

ich hab momentan folgendes Problem ich will 3 sachen unterscheiden, 
größer als, kleiner als und ist gleich wie. Jeder würde sachen, alles 
klar machen wir ein Case-Konstrukt, allerdings meckert mein Compiler, 
das würde nicht gehen. Vll hab jemand von Euch ja noch eine Lösung

case DATA_IN_SIG is

when (MAX_SIG < DATA_IN_SIG) =>
MAX_SIG <= DATA_IN_SIG;
MAX_VAL <= DATA_IN;

when (MIN_SIG > DATA_IN_SIG) =>
MIN_SIG <= DATA_IN_SIG;
MIN_VAL <= DATA_IN;

when others    =>
UR_VAL <= DATA_IN;

end case;

Danke im Voraus

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jan Egal schrieb:
> allerdings meckert mein Compiler
Und was meckert er?
Dass es nicht in einem Prozess steht (case geht nur in einem Prozess)?
Zeig doch mal die ganze Datei...

BTW: Wenn du das kombinatorisch machst, dann wird er auf jeden Fall ein 
paar Latches anmeckern.

von mac4ever (Gast)


Lesenswert?

Sowas würde keiner in einem CASE machen, da CASE kein "größer" oder 
"kleiner" kennt. Der CASE vergleicht auf Gleichkeit.

Mach es mittels IF THEN ELSE
1
if MAX_SIG < DATA_IN_SIG then
2
 MAX_SIG <= DATA_IN_SIG;
3
 MAX_VAL <= DATA_IN;
4
elsif MAX_SIG > DATA_IN_SIG then
5
 MIN_SIG <= DATA_IN_SIG;
6
 MIN_VAL <= DATA_IN;
7
else
8
 UR_VAL <= DATA_IN;
9
end if;

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

if MAX_SIG < DATA_IN_SIG then
 MAX_SIG <= DATA_IN_SIG;
 MAX_VAL <= DATA_IN;
elsif MAX_SIG > DATA_IN_SIG then
 MIN_SIG <= DATA_IN_SIG;
 MIN_VAL <= DATA_IN;
else
 UR_VAL <= DATA_IN;
end if;


das klappt erstaunlicher weise nicht. Das gibt nur Grütze bei der 
Simulation, leider.

Komplett sieht das so aus:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity MIN_MAX_CUR is
    Port ( CLK : in STD_LOGIC;
        DATA_IN : in  STD_LOGIC_VECTOR (7 downto 0);
           CALC_EN : in STD_LOGIC;
        RAM_ADR : in STD_LOGIC_VECTOR (7 downto 0);
        MAX_VAL : out  STD_LOGIC_VECTOR (7 downto 0);
           MIN_VAL : out  STD_LOGIC_VECTOR (7 downto 0);
           CUR_VAL : out  STD_LOGIC_VECTOR (7 downto 0));
end MIN_MAX_CUR;

architecture Behavioral of MIN_MAX_CUR is

signal DATA_IN_SIG : STD_LOGIC_VECTOR (7 downto 0);
signal MAX_SIG : STD_LOGIC_VECTOR (7 downto 0):="00000000";
signal MIN_SIG : STD_LOGIC_VECTOR (7 downto 0):="00000000";
signal CUR_SIG : STD_LOGIC_VECTOR (7 downto 0):="00000000";
signal DATA_LOADED : std_logic;




begin


process (CLK)
begin


    if rising_edge (CLK)  then
      if CALC_EN = '1' then
        DATA_IN_SIG <= DATA_IN;
        CUR_VAL <= DATA_IN_SIG;
      end if;
    end if;

end process;
DATA_LOADED <= '1';

process (DATA_LOADED, DATA_IN_SIG)
begin


          if DATA_LOADED = '1' then
            if (MAX_SIG < DATA_IN_SIG) then
            MAX_SIG <= DATA_IN_SIG;
            MAX_VAL <= DATA_IN;

            else
            MIN_SIG <= DATA_IN_SIG;
            MIN_VAL <= DATA_IN;

            end if;
          end if;


--          case DATA_IN_SIG is
--
--          when (MAX_SIG < DATA_IN_SIG) =>
--          MAX_SIG <= DATA_IN_SIG;
--          MAX_VAL <= DATA_IN;
--
--          when (MIN_SIG > DATA_IN_SIG) =>
--          MIN_SIG <= DATA_IN_SIG;
--          MIN_VAL <= DATA_IN;
--
--          when others    =>
--          CUR_VAL <= DATA_IN;
--
--          end case;


end process;

end Behavioral;

den case hab ich ma auskommentiert. Die IF abfrage funzt so wie sie ist 
gut, nur wenn irgendwann mal einer gleicher wert auftritt gehts in die 
Hose

von mac4ever (Gast)


Lesenswert?

Aus diesem Grund macht man
1
if ...>... then
2
 ...
3
elsif ...<... then
4
 ...
5
else
6
 ...
7
end if;

von Christian R. (supachris)


Lesenswert?

Jan Egal schrieb:
> use IEEE.NUMERIC_STD.ALL;
> use IEEE.STD_LOGIC_UNSIGNED.ALL;

Und das macht man schon gar nicht. Vor allem nicht bei Rechnerei und 
Vergleichen.
Nimm mal lieber nur die numeric_std und ersetze die Vektoren in den 
Vergleichen durch singned bzw. unsigned.

von Steffen H. (avrsteffen)


Lesenswert?

Ich sehe gerade, dass hier in zwei Prozessen "CUR_VAL" ein Wert 
zugewiesen wird.

Geht das denn überhaupt?

Gruß
Steffen

von mac4ever (Gast)


Lesenswert?

Nein, das geht nicht ... da wird auch der Fehler liegen.

Lothar Miller schrieb:
>> allerdings meckert mein Compiler
> Und was meckert er?

Die Informationen hätte wirklich geholfen :)
Wahrscheinlich: Multiple Driver Error

von Georg A. (Gast)


Lesenswert?

Hm, was ist "der" Compiler? Für die Simulation würde er (ghdl, modelsim, 
...) das mit den multiplen Treibern nicht bemeckern, das geht 
einwandfrei,s olange man nicht ulogic nimmt. Wird halt vermutlich 
dauernd eine Kollision (X) rauskommen ;) xst wirds nicht schlucken.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Georg A. schrieb:
> xst wirds nicht schlucken.
Auch kein andrer Syhtesizer nicht.
Denn so ein Bauteil, das das könnte, gibt es nicht auf einem FPGA...

Und ich höre mich noch sagen:
Lothar Miller schrieb:
> BTW: Wenn du das kombinatorisch machst, dann wird er auf jeden Fall ein
> paar Latches anmeckern.

Zudem ist die Sensitivliste unvollständig:
1
process (DATA_LOADED, DATA_IN_SIG)
2
begin
3
          if DATA_LOADED = '1' then
4
            if (MAX_SIG < DATA_IN_SIG) then -- Ja, holla: MAX_SIG fehlt in der Senslist
5
              MAX_SIG <= DATA_IN_SIG;
6
              MAX_VAL <= DATA_IN;       -- Ja, holla: DATA_IN fehlt in der Senslist
7
            else
8
              MIN_SIG <= DATA_IN_SIG;
9
              MIN_VAL <= DATA_IN;
10
            end if;
11
          end if;
12
:
13
:



Christian R. schrieb:
> Jan Egal schrieb:
>> use IEEE.NUMERIC_STD.ALL;
>> use IEEE.STD_LOGIC_UNSIGNED.ALL;
> Und das macht man schon gar nicht.
Jan Egal ist das egal:
Beitrag "Re: Mittelwertberechnung aus vier 8-Bit Zahlen"
Man könnte das auch beratungsresitent bezeichnen...  :-(

von Christian R. (supachris)


Lesenswert?

Lothar Miller schrieb:
> Jan Egal ist das egal:
> Beitrag "Re: Mittelwertberechnung aus vier 8-Bit Zahlen"
> Man könnte das auch beratungsresitent bezeichnen...  :-(

Hm, schlimm. Das blöde ist, dass es meistens klappt. Aber manchmal eben 
nicht :)

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Das hat nichts mit beratungsresistenz zu tun, ich nur kann der simple 
additionen nicht ausführn wenn die unsigned fehlt. Habs bisher nur auf 
diese Weise gemacht/gelernt. Und in diesem Funktionsblock hat das m.E. 
keinen EInfluss kann diese auch gern rausnehmen.

CUR_VAL ist wenn man hinsieht nur in einem process enthalten, da 
"case..." auskommentiert ist. Das es mit case nicht funzt ist mir auch 
klar, allerdings habe ich das Problem das der mit einem IF THEN ELSE 
konstrukt probleme bei dem Werte vergleich macht, CUR und MAX 
funktionieren einwandfrei leider nur nicht MIN und da is der Hund in der 
IF geschichte begraben

von mac4ever (Gast)


Lesenswert?

Also ich weiß nicht wo das Problem liegen soll ...

Pseudocode:
1
WENN MAX_SIG < DATA DANN
2
  ...
3
ANSONSTEN WENN MAX_SIG > DATA DANN
4
  ...
5
ANSONSTEN (hier ist MAX_SIG=DATA)
6
  ...

Die Ursache liegt mit Sicherheit nicht bei der IF-Anweisung. Prüfe 
nochmal die Eingangsdaten ...
Außerdem: Wenn Du es schon kombinatisch (also ohne Takt) versuchst, dann 
kodiere bitte auch alle IF-Zweige aus. Auch wenn dort nicht zu tun ist. 
Weise einfach das Signal sich selbst du.

Aber das wurde ja bereits zweimal erwähnt ...

Lothar Miller schrieb:
> Und ich höre mich noch sagen:
> Lothar Miller schrieb:
>> BTW: Wenn du das kombinatorisch machst, dann wird er auf jeden Fall ein
>> paar Latches anmeckern.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jan Egal schrieb:
> Das hat nichts mit beratungsresistenz zu tun, ich nur kann der simple
> additionen nicht ausführn wenn die unsigned fehlt.
Klar: du kannst Additionen mit std_logic-Vektoren nicht ausführen!
Und das ist gut so, denn: *Mit Vektoren rechnet man nicht.*
Dfür gibt es die Datentypen signed und unsigned...

Jan Egal schrieb:
> Die IF abfrage funzt so wie sie ist gut, nur wenn irgendwann mal
> einer gleicher wert auftritt gehts in die Hose
Nein. Dann wird der else-Pfad ausgeführt.
Oder sag mal, was in die Hose geht...

Jan Egal schrieb:
> Komplett sieht das so aus:
Wenn das der gesamte Code ist, dann kann das nicht stimmen:
Jan Egal schrieb:
> CUR und MAX funktionieren einwandfrei
> leider nur nicht MIN und da is der Hund in der IF geschichte begraben
Es gibt im gesamten Code kein CUR, MAX und MIN. Und wenn damit jeweils 
CUR_VAL, MAX_VAL und MIN_VAL gemeint waren, dann kann die Aussage 
trotzdem nicht stimmen.

BTW: das was du hier machst, ist als Salamitaktik bekannt.
Informationen nur spärlich und nur auf wiederholtes Bitten.
So macht Helfen keinen Spass... :-(

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Ok, dann drück ich ma ein BSP aus wo es nicht gehen wird.

Wenn z.B die DATA_IN folge: 0, 1, 2, 4, 3 erscheint wird das ein Problem 
geben, und zwar deswegen bei dem MIN WERT. MIt dem Quelltext den ihr 
angebt wird dann 3 ausgegeben, und zwar deswegen, weil auf der 4 eine 3 
folgt und diese kleiner ist. Die kleinste Zahl in der Folge ist aber die 
0. Und vorher durchlaufen des processes steht ja nix in den Signale, 
oder kann man durch einen trick diese vordefenieren wie z.B bei einer 
variable?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Dann machs so:
1
          if DATA_LOADED = '1' then
2
            if (MAX_SIG < DATA_IN_SIG) then
3
              MAX_SIG <= DATA_IN_SIG;
4
              MAX_VAL <= DATA_IN;
5
            elsif (MIN_SIG > DATA_IN_SIG) then  ---!
6
              MIN_SIG <= DATA_IN_SIG;
7
              MIN_VAL <= DATA_IN;
8
            end if;
9
          end if;

von Jan O. (Firma: keine) (quamstar)


Angehängte Dateien:

Lesenswert?

So ich hab nochmal zur besseren übersicht ein Simulationsbild 
rangehängt. Wie man dort sieht wird der Wert MIN_VAL nie bearbeitet, was 
mich schon die ganze Zeit stört. Hier nochmal der Quelltext:

process (CLK)
begin
    if rising_edge(CLK) then
      if CALC_EN = '1' then
      DATA_IN_S <= DATA_IN;
      end if;
    end if;
end process;


process (CLK, DATA_IN_S)
begin


    if rising_edge (CLK) then

        CUR_S <= DATA_IN_S;
        CUR_VAL <= DATA_IN_S;

        if (MAX_S < DATA_IN_S)  then
          MAX_S <= DATA_IN_S;
          MAX_VAL <= DATA_IN_S;



    elsif (MIN_S /= DATA_IN_S) and (MIN_S > DATA_IN_S) then
       MIN_S <= DATA_IN_S;
       MIN_VAL <= DATA_IN_S;


      end if;
    end if;

end process;


Meine Vermutung liegt noch mit darin das MIN_S ja keinen Wert zuvor noch 
keinen Wert besitzt (default = 0?) und somit MIN_S niemals größer sein 
kann als der aktuelle wert DATA_IN, ich schaffe es auch nicht dem MIN_S 
z.B zu begin bevor CALC_EN auf 1 geht, z.B "11111111" zuzuweisen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jan Egal schrieb:
> Meine Vermutung liegt noch mit darin das MIN_S ja keinen Wert zuvor noch
> keinen Wert besitzt (default = 0?)
Ja. So ist das.
Und du selber tust das ja auch noch:
signal MIN_SIG : STD_LOGIC_VECTOR (7 downto 0):="00000000";

Probier mal das:
signal MIN_SIG : STD_LOGIC_VECTOR (7 downto 0):="11111111";


Aber insgesamt ist das Design sowieso vermurkst, so mit den Latches...

von Jan O. (Firma: keine) (quamstar)


Angehängte Dateien:

Lesenswert?

Lassen sich die latches durch kombinatorik vermeiden? Als ich habs mal 
so sumuliert und es gibt zumindest (logischer weise) keine 
taktverzögerung mehr.

Das mit der zuweisung ...:="11111111"; klappt ebenfalls nicht

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jan Egal schrieb:
> Lassen sich die latches durch kombinatorik vermeiden?
Nein.
Latches enstehen durch Kombinatorik.

Vermeiden kannst du die nur, wenn der Takt mit ins Spiel kommt. Denn 
dann werden ganz normale D-FFs zum Speichern hergenommen.

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Das is doch Taktabhänig, zumindest habe ich in beiden ÜProzessen CLK 
drin. Fällt dir noch eine möglichkeit ein warum der nicht mit dem MIN_S 
klarkommt?

von Clemens M. (panko)


Lesenswert?

Nur mit meinem bescheidenden Wissen:
as ist doch nicht Taktabhängig, du hast einen if(edge)und dann ELSE....

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jan Egal schrieb:
> Das is doch Taktabhänig, zumindest habe ich in beiden ÜProzessen CLK
> drin.
Richtig.
Clemens M. schrieb:
> Nur mit meinem bescheidenden Wissen:
> as ist doch nicht Taktabhängig, du hast einen if(edge)und dann ELSE....
Das sieht nur so aus bei dieser Formatierung... :-/

Ich würde behaupten, dass das gehen muß:
1
signal MAX_S : STD_LOGIC_VECTOR (7 downto 0):="00000000";
2
signal MIN_S : STD_LOGIC_VECTOR (7 downto 0):="11111111";
3
signal CUR_S : STD_LOGIC_VECTOR (7 downto 0);
4
:
5
:
6
process (CLK) -- DATA_IN_S unnötig, der Prozess ist nur auf clk sensitiv
7
begin
8
    if rising_edge (CLK) then
9
      CUR_S <= DATA_IN_S;
10
      CUR_VAL <= DATA_IN_S;
11
12
      if (MAX_S < DATA_IN_S)  then
13
        MAX_S <= DATA_IN_S;
14
        MAX_VAL <= DATA_IN_S;
15
      elsif (MIN_S > DATA_IN_S) then
16
        MIN_S <= DATA_IN_S;
17
        MIN_VAL <= DATA_IN_S;
18
      end if;
19
20
    end if;
21
end process;

BTW:
Mit den Tags [ vhdl ]  und [ /vhdl ]   (ohne die Leerzeichen) kannst du 
das schöne Syntaxhighlighting nutzen...

Jan Egal schrieb:
> Das mit der zuweisung ...:="11111111"; klappt ebenfalls nicht
Bei mir klappt das bestens. Was machst du falsch?

Wrum machst du das alles doppelt:
        MAX_S   <= DATA_IN_S;
        MAX_VAL <= DATA_IN_S;
MAX_S und MAX_VAL sollen offenbar den selben Wert haben.
Warum nicht so:
1
signal MAX_S : STD_LOGIC_VECTOR (7 downto 0):="00000000";
2
signal MIN_S : STD_LOGIC_VECTOR (7 downto 0):="11111111";
3
signal CUR_S : STD_LOGIC_VECTOR (7 downto 0);
4
:
5
:
6
process (CLK) -- DATA_IN_S unnötig, der Prozess ist nur auf clk sensitiv
7
begin
8
    if rising_edge (CLK) then
9
      CUR_S <= DATA_IN_S;
10
      if (MAX_S < DATA_IN_S)  then
11
        MAX_S <= DATA_IN_S;
12
      elsif (MIN_S > DATA_IN_S) then
13
        MIN_S <= DATA_IN_S;
14
      end if;
15
    end if;
16
end process;
17
18
MIN_VAL <= MIN_S;
19
MAX_VAL <= MAX_S;
20
CUR_VAL <= CUR_S;

von Jan O. (Firma: keine) (quamstar)


Lesenswert?

Ich glaube ich hab viel zu kompliziert gedacht. Hatte im Kopf das ich 
ständig die Signale sichern muss damit der das unterscheiden kann, daher 
diese doppelzuweisung. Wenn man so versteift auf einen Fehler ist, dann 
sieht den Wald vor lauter Bäumen nicht, Danke Lothar.

von Christian R. (supachris)


Lesenswert?

Bei 2 der Signale hast du am Anfang X, da schreiben irgendwie 2 Prozesse 
offenbar auf das gleiche Signal. Bei nicht initialisiert ist U, das ist 
was anderes. Und wieso wehrst du dich eigentlich immer noch gegen 
unsigned/signed? gerade bei den Vergleichen krieg ich da echt 
Bauchschmerzen mit Vektoren...das Argument, dann geht keine Addition, 
ist doch auch irgendwie völlig daneben. Alles ziemlich verwirrend.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Christian R. schrieb:
> Alles ziemlich verwirrend.
ACK ;-)

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.