Forum: FPGA, VHDL & Co. Bits aus Vektor maskieren und verschieben


von MemY (Gast)


Lesenswert?

Hallo,

hat jemand einen Tipp, wie ich interaktiv maskierte Bits aus einem 
Vektor (INPUTDATA) neu angeordnet, durch Verschiebung, in ein Vektor 
(MASK0_N_0_TEMP_SRL) packen kann? Unten habe ich euch ein Beispiel:

Eingangsdaten:                 01010101110 -- INPUTDATA
Maske:                         00001111000 -- MASK0
Durch Maske gewählte Daten:    00000101000 -- MASK0_N_0_TEMP
Gewählte Daten verschieben:    00000000101 -- MASK0_N_0_TEMP_SRL

Das Problem ist, dass nicht nur die Input Daten, sodern auch die Maske 
variabel ist. So könnte ein Beispiel auch so aussehen:

Eingangsdaten:                01110111100 -- INPUTDATA
Maske:                        00011111110 -- MASK0
Durch Maske gewählte Daten:   00010111100 -- MASK0_N_0_TEMP
Gewählte Daten verschieben:   00001011110 -- MASK0_N_0_TEMP_SRL


Mein Ansatz:
1
-- Maskierung der Eingangsdaten
2
process(CLK, syn_n_reset)
3
begin
4
  if(syn_n_reset = '0') then
5
    MASK0_N_0_TEMP <= (others => '0');
6
  elsif rising_edge(CLK) then
7
    MASK0_N_0_TEMP <= INPUTDATA and MASK0;
8
  end if;
9
end process;
10
11
-- suche Anfang der Maske und verschiebe um Anzahl der Stellen bis zum ersten gesetzten Bit der Maske
12
process(CLK, syn_n_reset)
13
begin
14
  if rising_edge(CLK) then
15
    for i in 0 to MASK0'length loop
16
      if (MASK0(i) = '1') then
17
        MASK0_N_0_TEMP_SRL <= MASK0_N_0_TEMP SRL i;
18
      end if;
19
    end loop;
20
  end if;
21
end process;

Hat jemand eine bessere Idee oder einen besseren Ansatz dazu?

Grüße
MemY

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


Lesenswert?

MemY schrieb:
> Das Problem ist, dass nicht nur die Input Daten, sodern auch die Maske
> variabel ist.
Das gibt so erst mal einen Monstermultiplexer...

Must du diese Rechenoperation pro Wort in 1 Taktzyklus erledigen? Oder 
hast du da evtl. ein wenig Zeit?

von MemY (Gast)


Lesenswert?

Hallo Lothar,

danke für die Antwort.

Ich haette eig. schon ein paar Takte Zeit...

Ich habe es im Moment mit einer riesigen CASE-Anweisung (also einem MUX) 
realisiert. Mit einem kleinen Zähler schaue ich an welcher Bitposition 
die Maske beginnt, danach wird geeignet verschoben.
1
if (MASK0(Bit_CTR) = '1') then
2
CASE Bit_CTR IS
3
WHEN 0 => MASK0_N_0_TEMP_SRL(47 downto 0) <= MASK0_N_0_TEMP(47 downto 0);
4
WHEN 1 => MASK0_N_0_TEMP_SRL(46 downto 0) <= MASK0_N_0_TEMP(47 downto 1);
5
WHEN 2 => MASK0_N_0_TEMP_SRL(45 downto 0) <= MASK0_N_0_TEMP(47 downto 2);
6
WHEN 3 => MASK0_N_0_TEMP_SRL(44 downto 0) <= MASK0_N_0_TEMP(47 downto 3);
7
.
8
.
9
.
10
WHEN 46 => MASK0_N_0_TEMP_SRL(1 downto 0) <= MASK0_N_0_TEMP(47 downto 46);
11
WHEN 47 => MASK0_N_0_TEMP_SRL(0) <= MASK0_N_0_TEMP(47);
12
WHEN OTHERS => Bit_CTR := Bit_CTR - Bit_CTR;
13
END CASE;
14
else
15
Bit_CTR := Bit_CTR + 1;
16
end if;
Viele Grueße MemY

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


Lesenswert?

MemY schrieb:
> Ich haette eig. schon ein paar Takte Zeit...
Dann würde ich das mit einer FSM und einem Schieberegister lösen:
1. Ausmaskieren und das Schieberegister laden
2. mit jedem Takt einmal schieben, bis eine 1 am LSB ankommt

von MemY (Gast)


Lesenswert?

Lothar Miller schrieb:
> 2. mit jedem Takt einmal schieben, bis eine 1 am LSB ankommt

Das wuerde bedeuten, dass die Maske und die maskierten Daten in jeweils 
ein Schieberegister hineingetaktet werden muesste?

von Falk B. (falk)


Lesenswert?

Ja.

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


Lesenswert?

MemY schrieb:
> Das wuerde bedeuten, dass die Maske und die maskierten Daten in jeweils
> ein Schieberegister hineingetaktet werden muesste?
Kann man so machen. Ich würde aber eher das Schieberegister mit dem 
maskierten Vektor laden. Und dieses "Zwischenergebnis" shiften. Dann ist 
nur 1 Schieberegister beteiligt. Du hast es selber schon so 
aufgezeichnet:
> Eingangsdaten: 01110111100 -- INPUTDATA
> Maske: 00011111110 -- MASK0
> Durch Maske gewählte Daten: 00010111100 -- MASK0_N_0_TEMP
---> dieses Zwischenergebnis kommt ins Schieberegister
Und dann werden die Daten geschoben:
> Gewählte Daten verschieben: 00001011110 -- MASK0_N_0_TEMP_SRL

von Falk B. (falk)


Lesenswert?

@ Lothar Miller (lkmiller) (Moderator) Benutzerseite

>Kann man so machen. Ich würde aber eher das Schieberegister mit dem
>maskierten Vektor laden. Und dieses "Zwischenergebnis" shiften.

Geht nicht, denn das maskierte LSB kann auch 0 sein.
Man braucht 2 Schieberegister.
Aber im Zeitalter der Multimilliongates-FPGAs sind 24 FlipFlops weiß 
Gott zu verschmerzen ;-)
Und vielleicht noch ne Handvoll Dollar, ähh FlipFlops für die state 
machine.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

So könnte es gehen, 39 FlipFlops, des Synthesizer packt noch 3 
obendrauf, damit es schneller wird.

von Schlumpf (Gast)


Lesenswert?

Eine andere Alternative, wenn es sehr schnell sein soll, wäre eine 
parallele Verarbeitung. Allerdings entsteht dabei eine Monsterlogik

Du bestimmst erst die Position der ersten "1" der Maske parallel:
1
pos <= 0 when mask(0)          = '1'          else
2
       1 when mask(1 downto 0) = "10"         else
3
       2 when mask(2 downto 0) = "100"        else
4
       3 when mask(3 downto 0) = "1000"       else
5
       .....
6
       n when mask(n downto 0) = "100...0";

Diesen wert von pos verwendest du dann, um einen Slice aus dem 
Ergebnisvektor nach der Maskierung herauszuschneiden und Richtung MSB 
hin mit Nullen aufzufüllen.
n sei dabei die größe der Vektoren (n downto 0)
1
ergebnis(n-pos downto 0) <= maskierter_vektor(n downto pos);
2
ergebnis(n downto n+1-pos) <= (others => '0');

also so:
Position:                      n         0
Eingangsdaten:                 01010101110
Maske:                         00001111000
Durch Maske gewählte Daten:    00000101000
Position:                   n         0
herausgeschnittene Daten:   00000000101

Ressourcenschonend ist das nicht gerade, aber vollkommen parallel und 
somit ganz ohne einen Takt möglich.

Hoff, ich hab keinen Denkfehler drin ;-)

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


Angehängte Dateien:

Lesenswert?

Falk Brunner schrieb:
>> dieses "Zwischenergebnis" shiften.
> Geht nicht, denn das maskierte LSB kann auch 0 sein.
Richtig, ich hatte das falsch verstanden:
MemY schrieb:
> bis zum ersten gesetzten Bit der Maske

Falk Brunner schrieb:
> So könnte es gehen
Man könnte den Sonderfall "Maske ist komplett null" aber auchvorneweg 
abfragen. Letztlich spart man sich aber nichts, weil dieser Vergleich 
mehr Logik braucht (siehe Anhang)...

> 39 FlipFlops
Lass die Registrierung vom result raus, dann sinds weniger... ;-)

von MemY (Gast)


Lesenswert?

Zuerst mal vielen Dank für die vielen nuetzlichen Hinweise von euch!

Habe nun den maskshift von Lothar für meine Beduerfnisse angepasst und 
simuliert und es scheint soweit alles gut zu gehen!


Gruß MemY

von Falk B. (falk)


Lesenswert?

@ MemY (Gast)

>Habe nun den maskshift von Lothar für meine Beduerfnisse angepasst und

Der hat gegutenbergt!!! ;-)

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


Lesenswert?

Falk Brunner schrieb:
> Der hat gegutenbergt!!!
Das war doch nur gegutenborgt oder eher gutgeborgt... ;-)

von Schlumpf (Gast)


Lesenswert?

Ich habe gerade mal zum Spass den von mir gemachten Vorschlag durch die 
Synthese geschickt:
1
ARCHITECTURE arch OF mask_and_shift IS
2
   signal position : integer range 0 to 10;
3
   signal mask_vektor : std_logic_vector(10 downto 0);
4
BEGIN
5
   mask_vektor <= in_val AND mask;
6
   position <= 0 when mask(0)          = '1'            else
7
               1 when mask(1 downto 0) = "10"           else
8
               2 when mask(2 downto 0) = "100"          else
9
               3 when mask(3 downto 0) = "1000"         else
10
               4 when mask(4 downto 0) = "10000"        else
11
               5 when mask(5 downto 0) = "100000"       else
12
               6 when mask(6 downto 0) = "1000000"      else
13
               7 when mask(7 downto 0) = "10000000"     else
14
               8 when mask(8 downto 0) = "100000000"    else
15
               9 when mask(9 downto 0) = "1000000000"   else
16
              10 when mask(10 downto 0)= "10000000000";
17
   process(mask_vektor, position)
18
   begin
19
     ergebnis((10-position) downto 0) <= mask_vektor(10 downto position);
20
     ergebnis(10 downto (11-position)) <= (others => '0');
21
   end process;
22
END arch;

Benötigt 148 LUT4 und ist abzüglich der PAD-Delays in 12ns durch..
Hätte schlimmer kommen können gg

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


Lesenswert?

Schlumpf schrieb:
> Benötigt 148 LUT4
Auf einem S3 sinds nur 120... ;-)

> Hätte schlimmer kommen können
Und es kam schlimmer:
1
Macro Statistics
2
# Latches           :  11

Aber der Ansatz scheint vielversprechend, und ich habe ihn mal 
verschlankt:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity mask_shift_par is
6
    Port ( data : in  STD_LOGIC_VECTOR (10 downto 0);
7
           mask : in  STD_LOGIC_VECTOR (10 downto 0);
8
           result : out  STD_LOGIC_VECTOR (10 downto 0));
9
end mask_shift_seq;
10
11
architecture Behavioral of mask_shift_par is
12
   signal mv : std_logic_vector(10 downto 0);
13
BEGIN
14
   mv <= data AND mask;
15
   result <=                  mv(10 downto 0)  when mask(0) = '1' else
16
             "0"           &  mv(10 downto 1)  when mask(1) = '1' else
17
             "00"          &  mv(10 downto 2)  when mask(2) = '1' else
18
             "000"         &  mv(10 downto 3)  when mask(3) = '1' else
19
             "0000"        &  mv(10 downto 4)  when mask(4) = '1' else
20
             "00000"       &  mv(10 downto 5)  when mask(5) = '1' else
21
             "000000"      &  mv(10 downto 6)  when mask(6) = '1' else
22
             "0000000"     &  mv(10 downto 7)  when mask(7) = '1' else
23
             "00000000"    &  mv(10 downto 8)  when mask(8) = '1' else
24
             "000000000"   &  mv(10 downto 9)  when mask(9) = '1' else
25
             "0000000000"  &  mv(10 downto 10) when mask(10)= '1' else
26
             "00000000000";
27
END Behavioral;
Fazit:
Number of 4 input LUTs     62
Number of occupied Slices  33

von Schlumpf (Gast)


Lesenswert?

Lothar Miller schrieb:
> Auf einem S3 sinds nur 120... ;-)

Angeber ;-)

Lothar Miller schrieb:
> Und es kam schlimmer:Macro Statistics
> # Latches           :  11

Stimmt.. Bei mir waren es "combinatorial loops", aber das ist genauso 
bescheiden. Das Design von mir ist bei genauerem Hinsehen wirklich nicht 
ganz hasenrein...

Lothar Miller schrieb:
> und ich habe ihn mal
> verschlankt:

Sehr elegant.. und eigentlich so naheliegend :-)

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.