Forum: FPGA, VHDL & Co. von LSB bis führendes bit auf 1 setzen.


von fpga-freund (Gast)


Lesenswert?

Hallo,

Ich habe einen 256 bit breiten Vector und ich möchte das ab der ersten 
vorkommenden 1 (aus MSB Richtung betrachtet) alle anchfolgenden Stellen 
auf 1 gesetzt werden.
Was währe denn unter berücksichtigung von geringen Taktzyklen und 
Durchlafszeiten eine gute Möglichkeit?

Bisher sieht mein Ansatz so aus, dass ich von MSB nach LSB N-Bit breit 
verodert prüfe ob ein oder mehrere bits auf 1 stehen.
Wenn nicht dann shift ansonsten werden bis zu N Takte benötigt um 
festzustellen welche stelle die erste eins hat.
Danach benötige ich wieder einige taktzyklen um die niederen bits  auf 1 
zu legen.

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


Lesenswert?

fpga-freund wrote:
> Was währe denn unter berücksichtigung von geringen Taktzyklen und
> Durchlafszeiten eine gute Möglichkeit?
Wie schnell muss das gehen? Der Ressourcenverbrauch ist egal?

> Ich habe einen 256 bit breiten Vector und ich möchte das ab der ersten
> vorkommenden 1 (aus MSB Richtung betrachtet) alle anchfolgenden Stellen
> auf 1 gesetzt werden.
Also eigentlich ein Monstermultiplexer.

> Wenn nicht dann shift
Schieberegister... hmmmm...ich weiß nicht so recht, ob das schneller 
ist. Auf jeden Fall musst du dann den Zugriff auf dieses Register 
arbitrieren und verwalten.

Ich würde darauf basierend mal was aufbauen:
http://www.lothar-miller.de/s9y/archives/55-Finde-das-MSB.html
Eine Strategie wäre z.B. sowas das 8 mal aufzubauen und dann nach Finden 
der "ersten" 1 alle "darunterliegenden" 32-Bit-Worte auf xffffffff zu 
legen...

: Bearbeitet durch Moderator
von ElKo (Gast)


Lesenswert?

You are in the english part of the forum. Would be nice to write english 
then, or post in mikrocontroller.net.

How about doing it in one clock cycle? Costs a lot of logic, but should 
be fast. Just check all 256 cases and use the result of the highest.

Untested Pseudocode:
1
input in[255:0];
2
output out[255:0];
3
integer i;
4
5
for (i=255; i>0; i=i-1) begin
6
    if ( (in >> i) == 1 ) begin
7
        out = (0!) >> i;
8
        break;
9
    end
10
end

If the break is not working properly you can also make a big or-gate for 
the result. This will keep only the highest result.
1
out = 0;
2
for (i=255; i>0; i=i-1) begin
3
    if ( (in >> i) >= 1 ) begin
4
        out = out | ((0!) >> i);
5
    end
6
end

Or you write it straight forward as a big switch-case.

I think this is the fastest regarding speed.

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


Lesenswert?

ElKo wrote:
> You are in the english part of the forum.
Ja, danke für den Tipp. Ich habe das korrigiert..

Wo ich die Antwort da so sehe befällt mich die Frage: welche 
Beschreibungssprache? Oder geht es lediglich um ein prinzipielles 
Verfahren?

von ElKo (Gast)


Lesenswert?

Lothar M. schrieb:
> Ja, danke für den Tipp. Ich habe das korrigiert..
Habs gesehen. Danke. Du warst ein klein wenig schneller. :)

Sprache: An Verilog angelehnt. Wie gesagt, als Anregung. Müsste so 
ähnlich aber umsetzbar sein. Meiner Erfahrung nach liegt der Teufel im 
Detail. Ich bin mir zum Beispiel nicht sicher, wie das break in den 
Tools wirklich umgesetzt werden würde.

von Gustl B. (-gb-)


Lesenswert?

Da gibt es doch den Prioritätsencoder. Der liefert die rein 
kombinatorisch den Index des höchstwertigen gesetzten Bits zurück.

: Bearbeitet durch User
von Sigi (Gast)


Lesenswert?

fpga-freund schrieb:
> Ich habe einen 256 bit breiten Vector und ich möchte das ab der ersten
> vorkommenden 1 (aus MSB Richtung betrachtet) alle anchfolgenden Stellen
> auf 1 gesetzt werden.
> Was währe denn unter berücksichtigung von geringen Taktzyklen und
> Durchlafszeiten eine gute Möglichkeit?

Schau dir mal als Beispiel die Carry-Chain einer
Spartan3/VirtexII/Virtex4-Logikzelle an. Du fütterst
diese ganz Unten mit 0, sobald eine 1 auftaucht, wird
eine 1 ausgegeben und eine 1 in die Chain eingespeisst.
Da du von MSB an abwärts arbeitest musst du nur noch
den Vektor "umgekehrt" an die Chain legen.

Bei 256 Bit schätze ich (+Datasheet-Specs) beim Virtex4
bist du bei 40MHz.

von ElKo (Gast)


Angehängte Dateien:

Lesenswert?

Ok, das Break wollte Modelsim nicht. Keine Ahnung wieso. SystemVerilog 
soll das eigentlich können.
> ** Error: (vsim-3043) compare.v(36): Unresolved
>      reference to 'break'.

Mit der richtigen Bedingung im if geht es aber auch ohne. Ergebnis siehe 
Anhang. Hier für 16 Bit. Für 256 einfach den Parameter hoch setzen. 
Synthesefähigkeit nicht geprüft.
1
module compare(
2
        din,
3
        dout
4
    );
5
    
6
    parameter len = 16;
7
    
8
    // Inputs, Outputs
9
        input   [len-1:0] din;
10
        output  [len-1:0] dout;
11
        
12
    // variables
13
        integer i;
14
        reg [len-1:0] temp;
15
    
16
    assign dout = temp;
17
    
18
    // multiplexer
19
    always @(din) begin
20
        temp = 16'h0;
21
        for (i=len-1; i>=0; i=i-1) begin
22
            if ( (din >> i) == 1 ) begin
23
                temp = (16'hFFFF) >> (len-i-1);
24
            end
25
        end
26
    end
27
28
endmodule

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


Angehängte Dateien:

Lesenswert?

ElKo schrieb:
> Synthesefähigkeit nicht geprüft.
Mit VHDL geht es komplett kombinatorisch. Auf dem alten S3 laut 
Synthesizer mit knapp 50ns, ein V5 macht 30ns daraus...

EDIT: mal genauer untersucht: der lügt sich da irgendwas in die 
Tasche... :-/

Ich würde mir auch mal die Sache mit der Carry-Chain genauer anschauen, 
ob sich da nicht was machen lässt.

: Bearbeitet durch Moderator
von bitwurschtler (Gast)


Lesenswert?

fpga-freund schrieb:
>Ich habe einen 256 bit breiten Vector und ich möchte das ab der ersten
>vorkommenden 1 (aus MSB Richtung betrachtet) alle anchfolgenden Stellen
>auf 1 gesetzt werden.
>Was währe denn unter berücksichtigung von geringen Taktzyklen und
>Durchlafszeiten eine gute Möglichkeit?

RS-FF, das high aktive S mit Q des FF davor verbinden.

von Sigi (Gast)


Angehängte Dateien:

Lesenswert?

Lothar M. schrieb:
> Ich würde mir auch mal die Sache mit der Carry-Chain genauer anschauen,
> ob sich da nicht was machen lässt.

Dein Code macht im Prinzip schon dass, was ich mit der
CarryChain erreichen möchte, ISE mapped es aber nicht
perfekt in die CLBs/Slices. Von daher ist es ein wenig
(wirklich nur wenig!) langsamer als die CarryChain.

Im Anhang/Bildern sieht man eine einzelne Zelle, einen
Teil der Kette und beide Testbenches.

Wenn man noch zusätzlich bedenkt, dass die verwendeten
LUT4 4 Eingänge besitzen und per Tabelle eine Art
Priority-Encoder implementiert werden kann, dann kann
man damit die Kettenlänge nochmal durch 4 teilen und
erreicht durch entsprechende Location-Constraints
Taktraten um die 400-500MHz (auf Virtex5 sogar bis
700MHz). Allerdings wird das Weitertransportieren bei
diesen Taktraten schnell sehr aufwendig.

von Sigi (Gast)


Lesenswert?

bitwurschtler schrieb:
> RS-FF, das high aktive S mit Q des FF davor verbinden.

Kann man machen, man muss aber bedenkten, dass
dadurch eine sehr langsame Kette generiert wird
(geschätzt ca. 5-10 mal langsamer als eine CarryChain).

Eine CarryChain hat z.B. per V4-Slice 0.09ns
(256/2*0.09ns = 11.52ns) und per V5-Slice 0.11ns
(256/4*0.11ns = 7.04ns) Durchlaufzeit. Durch geschicktes
Verwenden dieser Ketten können z.B. 16KBit-Vektoren
mit >=50MHz auf V5 mit einer Konstanten/Variablen
verglichen werden.

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.