Forum: FPGA, VHDL & Co. Mux mit One-Hot Eingang


von Marius S. (lupin) Benutzerseite


Lesenswert?

slv_sel ist ein std_logic_vector welcher die Ergebnisse von vier 
Komparatoren zusammen fasst. Im Normalfall darf nur einer anschlagen 
(hoffentlich :)) und je nachdem welcher anschlägt soll aus dem 
record-Array rec_arr ein Record auf den Record rec_out gegeben werden.
1
WITH slv_sel SELECT
2
rec_out <= rec_arr(0) WHEN "0001",
3
           rec_arr(1) WHEN "0010",
4
           rec_arr(2) WHEN "0100",
5
           rec_arr(3) WHEN "1000",
6
           rec_arr(0) WHEN others;

Wie kann man das ganze schöner schreiben? Die Größe von rec_arr und die 
Länge von slv_sel soll über eine Generic anpassbar sein. Die Größe von 
rec_arr und die Länge von slv_sel stimmt immer überein.

Ich denke über eine FOR-Loop mit GENERATE-Anweisung könnte das klappen, 
oder? Nur wie genau?

: Bearbeitet durch User
von Christoph Z. (christophz)


Lesenswert?

Für solche Zwecke kannst du dir anstatt einen GENERATE auch eine 
FUNCTION schreiben. Hast dann mehr Freiheiten um an eine Lösung zu 
kommen.

von Leonard Lebewohl (Gast)


Lesenswert?

>Ich denke über eine FOR-Loop mit GENERATE-Anweisung könnte das klappen,
>oder? Nur wie genau?


Genau genohmen ist eine for -schleife was komplett anderes als eine 
generate schleife.

sowas wie
1
for i in 0 to 9 loop   
2
--.....
3
end loop;


passt nur in prozessen,
während
1
Generate_loop: for i in 0 to 9 generate 
2
--..
3
4
end generate Generate_loop;

 nur außerhalb von prozessen erlaubt ist. Eine foor loop mit generate 
ist nich.

IMHO möchtest du für deine Anwendung eine for - loop und kein generate.

MfG;

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


Lesenswert?

Das "when others" ist mir nicht ganz klar. Ist das nötig oder nur ein 
kleiner Hilfeschrei? Wäre es schlimm oder was würde passieren, wenn du 
sowas schreiben würdest:
1
WITH slv_sel SELECT
2
rec_out <= rec_arr(0) WHEN "0001",
3
           rec_arr(1) WHEN "0010",
4
           rec_arr(2) WHEN "0100",
5
           rec_arr(3) WHEN others;


Wenn du deine Beschreibung umschreibst, dann kommst du schnell auf 
sowas:
1
 rec_out <= rec_arr(0) WHEN slv_sel(0)='1' ELSE
2
            rec_arr(1) WHEN slv_sel(1)='1' ELSE
3
            rec_arr(2) WHEN slv_sel(2)='1' ELSE
4
            rec_arr(3) WHEN slv_sel(3)='1' ELSE
5
            rec_arr(0);
Und das erinnert mich irgendwie an die Sache mit dem or_reduce() von 
letzter Woche im Beitrag "Über Conditions loopen (VHDL)"...

von Marius S. (lupin) Benutzerseite


Lesenswert?

Leonard Lebewohl schrieb:
> Genau genohmen ist eine for -schleife was komplett anderes als eine
> generate schleife.

Also soweit ich weiss verwendet man For-Schleifen in Prozessen und 
Generate-Schleifen in der Architektur.

Meine Beschreibung steht in der Architektur und soll nebenläufig sein, 
daher die Idee mit der Generate-Schleife.

Lothar Miller schrieb:
> Wenn du deine Beschreibung umschreibst, dann kommst du schnell auf
> sowas: rec_out <= rec_arr(0) WHEN slv_sel(0)='1' ELSE
>             rec_arr(1) WHEN slv_sel(1)='1' ELSE
>             rec_arr(2) WHEN slv_sel(2)='1' ELSE
>             rec_arr(3) WHEN slv_sel(3)='1' ELSE
>             rec_arr(0);
> Und das erinnert mich irgendwie an die Sache mit dem or_reduce() von
> letzter Woche im Beitrag "Über Conditions loopen (VHDL)"...

Ja, kann man auch gerne so schreiben. Nur wie bringe ich das jetzt in 
eine Form, dass ich die Länge von slv_sel und die Göße von rec_arr 
parametrieren kann?

Mir ist im grunde egal ob das über Generate-Loop oder eine Funktion 
geht, ich will nur eine Lösung :-P

Was das mit dem erwähnten Beitrag zu tun hat sehe ich noch nicht, werde 
ihn mir mal etwas genauer durchlesen.

von Christoph Z. (christophz)


Lesenswert?

Mal ein Vorschlag als kombinatorischer Prozess:
1
onehotmux: process (slv_sel) is
2
begin  -- process onehotmux
3
    variable i : natural;
4
  begin
5
    assert rec_arr'length = slv_sel'length report "One-Hot Mux: Selection range" &
6
      " doesn't fit with range of input array" severity error;
7
    
8
    i := 0;
9
10
    -- convert one-hot encoding to integer
11
    for k in slv_sel'range loop
12
      if slv_sel(k) = '1' then
13
        i := k;
14
      end if;
15
    end loop;
16
    
17
    rec_out := rec_arr(i);
18
19
end process onehotmux;

Das ganze kann man auch komplett generisch beschreiben mit Hilfe einer 
Funktion und eigenen Datentypdefinitionen (die man praktischerweise in 
einem Package zusammen hat).

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


Lesenswert?

> Mal ein Vorschlag als kombinatorischer Prozess
Die Sensitivliste ist nicht vollständig. Es fehlt das wichtigste 
Signal...

von Christoph Z. (christophz)


Lesenswert?

Danke. War gestern ein bisschen voreilig. Dachte ich könnte das schnell 
beschreiben und dann zu meiner Sammlung von Funktionen hinzufügen. 
Realisierte dann aber, dass für den Fragesteller mein Code nicht so 
hilfreich wäre (Müsste dann das ganze Package veröffentlichen mit 
Beispiel). Also habe ich dann den Schnellschuss produziert.
1
onehotmux: process (slv_sel, rec_arr) is
2
begin  -- process onehotmux
3
    variable i : natural;
4
  begin
5
    assert rec_arr'length = slv_sel'length report "One-Hot Mux: Selection range" &
6
      " doesn't fit with range of input array" severity error;
7
    
8
    i := 0;
9
10
    -- convert one-hot encoding to integer
11
    for k in slv_sel'range loop
12
      if slv_sel(k) = '1' then
13
        i := k;
14
      end if;
15
    end loop;
16
    
17
    rec_out := rec_arr(i);
18
19
end process onehotmux;

von Leonard Lebewohl (Gast)


Lesenswert?

Das others wird nicht identisch umgesetzt. Sind unerwarteterweise zwei 
bits
'1' wird nicht (0) selektiert sondern der Kanal der der höherwertigen 
'1' zugeordnet ist.

MfG,

von Leonard Lebewohl (Gast)


Lesenswert?

Lothar Miller schlug vor:
1
WITH slv_sel SELECT
2
rec_out <= rec_arr(0) WHEN "0001",
3
           rec_arr(1) WHEN "0010",
4
           rec_arr(2) WHEN "0100",
5
           rec_arr(3) WHEN others;

1
Wenn du deine Beschreibung umschreibst, dann kommst du schnell auf 
2
sowas: rec_out <= rec_arr(0) WHEN slv_sel(0)='1' ELSE
3
            rec_arr(1) WHEN slv_sel(1)='1' ELSE
4
            rec_arr(2) WHEN slv_sel(2)='1' ELSE
5
            rec_arr(3) WHEN slv_sel(3)='1' ELSE
6
            rec_arr(0);


--

Nein das ist nicht identisch bspw. für slv_sel "0110". Oberes selektiert
(3), der zweite code dagegen  (1).

MfG,

von Christoph Z. (christophz)


Lesenswert?

Leonard Lebewohl schrieb:
> Das others wird nicht identisch umgesetzt.

Korrekt. Da ist auch noch die Frage offen, ob das others genau so sein 
muss oder nicht.

Dieses Verhalten kann nach Wunsch mit dem Initalwert von "i" angepasst 
werden.

Leonard Lebewohl schrieb:
> Sind unerwarteterweise zwei bits '1' wird nicht (0) selektiert sondern der Kanal 
der der höherwertigen '1' zugeordnet ist.

Kommt darauf an ob slv_sel auf- oder absteigend ist. Man kann auch 
dieses Verhalten explizit beeinflussen.
1
for k in slv_sel'range loop

ersetzen durch:
1
for k in slv_sel'high downto slv_sel'low loop

Dann wird bei mehreren gesetzten '1' immer der niedrigste bevorzugt. 
(Letzte zuweisung gewinnt).

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


Lesenswert?

Leonard Lebewohl schrieb:
> Nein das ist nicht identisch ...
Der others-Fall ist offenbar nicht so wichtig, denn ich hatte da schon 
nachgefragt, und
Marius S. schrieb:
> Lothar Miller schrieb:
>> Wenn du deine Beschreibung umschreibst, dann ...
> Ja, kann man auch gerne so schreiben.
Also muss im Konfliktfall nicht unbedingt das erste Element selektiert 
werden.

von Marius S. (lupin) Benutzerseite


Lesenswert?

Stimmt, mir ist egal wie er im konfliktfall reagiert, der Fall darf 
nicht auftreten und wenn doch ist sowieso woanders was falsch.

Macht es denn vom resourcenverbrauch her einen Unterschied ob ich nur 
ein Bit oder alle auswerte? Ich glaube nicht, da er beides als eine LUT 
kodiert, oder?

von Marius S. (lupin) Benutzerseite


Lesenswert?

Die Lösung von Christoph funktioniert übrigens wie gewünscht, danke 
dafür :-)

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


Lesenswert?

Marius S. schrieb:
> Macht es denn vom resourcenverbrauch her einen Unterschied ob ich nur
> ein Bit oder alle auswerte? Ich glaube nicht, da er beides als eine LUT
> kodiert, oder?
Ob das alles in eine LUT passt, hängt davon ab, wie groß dein Record 
ist. Aber in 1 einzige LUT passt ein Decoder mit 4 Eingängen bestenfalls 
dann, wenn es eine 6er LUT ist...

> Macht es denn vom resourcenverbrauch her einen Unterschied ob ich nur
> ein Bit oder alle auswerte?
Ich würde das ausprobieren, wenn es mich interessieren würde und ichdas 
Ergbniss nicht wüsste. Dabei lernt man am meisten... ;-)

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.