Forum: FPGA, VHDL & Co. Subtraktionsglied mit "Borrow Out"


von Burkhard K. (buks)


Angehängte Dateien:

Lesenswert?

Hallo,

lässt sich ein Subtraktionsglied mit "Borrow Out" per VHDL-Coding 
inferieren? Oder muss ich ein entsprechendes Modul eigenhändig 
implementieren? Verwendete Platform ist ein Artix-7 / Nexys4 Board. Im 
XST User Guide 
(ftp://ftp.xilinx.com/pub/documentation/misc/xstug_examples.zip) finde 
ich als Beispiel lediglich einen "8-bit Adder with Carry Out".

Hintergrund der Frage: Mein naiver Versuch ein DC Offset Removal à la 
Xilinx WP279 ("Digitally Removing a DC Offset: DSP Without Mathematics") 
umzusetzen (siehe unten angehängten Code), funktioniert zwar 
grundsätzlich, gelegentlich zeigen extern (an den vorgeschalteten ADC) 
angelegte periodische Signale jedoch Vorzeichenumkehr - aus einem 
(Ko-)Sinus wird dann ein Rechteck mit sinusförmig eingedellten Dach bzw. 
Boden.

Ursache ist ein möglicher Überlauf im Substraktionsglied 
"Msub_to_adder_1". Sofern beim Anlegen des externen Signals die 
initialen Werte dicht an der oberen oder unteren Grenze des 
ADC-Wertebereiches liegen wird der Wert im Akku für den Ergebnisvektor 
zu groß. Per Überlaufbit könnte das Ergenis auf den Maximal- bzw. 
Mininalwert begrenzt werden, um so eine mögiche Vorzeichenumkehr zu 
verhindern.

Gruß,
Burkhard
1
entity DCremover is
2
  Generic ( 
3
    C_DATA_WIDTH: integer := 12;
4
    C_K_WIDTH    : integer := 18;   -- width K Factor"
5
    DIN_USGND  : std_logic := '1'
6
  );
7
  Port ( 
8
      clk :  in  STD_LOGIC;
9
      clr :  in  STD_LOGIC;
10
      en   :  in  STD_LOGIC;
11
      din :  in  STD_LOGIC_VECTOR (C_DATA_WIDTH-1 downto 0);
12
      dout: out  STD_LOGIC_VECTOR (C_DATA_WIDTH-1 downto 0)
13
  );
14
end DCremover;
15
16
architecture RTL of DCremover is
17
18
  constant C_MULT_WIDTH: integer := C_DATA_WIDTH+C_K_WIDTH;
19
20
  signal to_subst : signed(C_DATA_WIDTH-1 downto 0);
21
  signal to_adder : signed(C_DATA_WIDTH-1 downto 0);
22
  signal accu_next: signed(C_MULT_WIDTH-1 downto 0);
23
  signal accu_reg : signed(C_MULT_WIDTH-1 downto 0) := (others=>'0');
24
  alias  accu_msb : signed(C_DATA_WIDTH-1 downto 0) is accu_reg(C_MULT_WIDTH-1 downto C_K_WIDTH);
25
26
begin
27
28
  process(clk, clr) 
29
  begin
30
    if rising_edge(clk) then
31
      if (clr = '1') then
32
        accu_reg <= to_signed(0, accu_reg'length);
33
      elsif(en='1') then
34
        accu_reg <= accu_next;
35
      end if;
36
    end if;
37
  end process;
38
  
39
  to_subst <= signed(not(din(din'high)) & din(din'high-1 downto 0)) when DIN_USGND='1' else
40
          signed(din);
41
  to_adder  <= to_subst - accu_msb;
42
  accu_next<= to_adder + accu_reg;
43
  dout    <= std_logic_vector(to_adder);
44
  
45
end RTL;

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


Lesenswert?

Burkhard K. schrieb:
> lässt sich ein Subtraktionsglied mit "Borrow Out" per VHDL-Coding
> inferieren?
Du meinst das "Unterlauf" Bit?

> Hintergrund der Frage:
Erlär doch mal dein Problem mit natürlichsprachlichen Worten und WERTEN. 
Dann kann man sich evtl. ganz leicht vorstellen, was du da willst. 
Derzeit ist es irgendwie holprig.

Ich vermute, das Grundproblem hier ist, dass das Ergebnis der Addition 
zweier Vektoren ein Bit breiter ist (bzw. sein kann) als der breitere 
der beiden Vektoren. Und dass eine Subtraktion eigentlich auch nur eine 
Addition ist...

Die von dir gesuchte Information steckt mit hoher Wahrscheinlichkeit in 
diesem zusätzlichen und von dir einfach abgeschnittenen Bit.

BTW: ich finde es extrem verwirrend, wenn da so viele accu_*** 
kursieren. Ich würde da den Überblick verlieren.

BTW2: was heißt denn DIN_USGND? Deutsche Industriennorm mit US Ground?
Oder warum machst du dir nicht die Geschwätzigkeit von VHDL zu Nutzen 
und schreibst "InputValueIsUnsigned"

von Gustl B. (-gb-)


Lesenswert?

Der 74193 kann das. Also runterzählen mit borrow out.

von Rick Dangerus (Gast)


Angehängte Dateien:

Lesenswert?

Burkhard K. schrieb:
> lässt sich ein Subtraktionsglied mit "Borrow Out" per VHDL-Coding
> inferieren?
Ich denke ja.

Um zu sehen, ob der Code richtig rechnet, verfüttere ich ihn (inklusive 
Testbench) an einen Simulator. Ich hab Dir mal eine Variante angefügt.


Rick

von Fpgakuechle K. (Gast)


Lesenswert?

Gustl B. schrieb:
> Der 74193 kann das. Also runterzählen mit borrow out.

Dort der Schaltplan dazu:
http://www.ee.scu.edu/classes/1998fall/elen021/hwk/ckt193b.GIF

Ob es sich interferen lässt kann dir der library guide verraten:

http://www.xilinx.com/support/documentation/sw_manuals/xilinx2012_2/ug953-vivado-7series-libraries.pdf

Im Abschnitt ADD/SUB Makro Auf Seite 42 steht ganz oben unter Design 
entry method "Interference - NO" Wobei sich das auf den DSP48 
adder/subtracter bezieht. bei carry chain Makros kann das schoon anders 
aussehen und eigentlich kann das synthesetool immer was aus LUT's 
zusammensynthetisieren ohne das man diese per Hand instanziiert. Ob's 
optimal ist sei dahingestellt.

MfG,

von Gustl B. (-gb-)


Lesenswert?

Was ist eigentlich dieses interferen? Den 74193 hab ich schon in VHDL 
gemacht, und zwar exakt den Schaltplan nachgebaut den ich zu TTL Stein 
gefunden hatte.

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


Lesenswert?

Gustl B. schrieb:
> Was ist eigentlich dieses interferen?
Es heißt eigentlich "inferieren" und bedeutet normalerweise, dass eine 
Komponente, die bereits als fertige Hardware vorliegt in ein Design 
eingebunden werden soll.
Es könnte also z.B. eine LUT inferiert werden. Oder ein Schieberegister 
oder ein RAM-Block. Oder ein Flipflop...

Das Wort "inferieren" deutet üblicherweise auf eine sehr hardwarenahe 
Beschreibung hin. So etwas ist beim hiesigen Problem aber eigentlich 
nicht nötig.

von Markus F. (mfro)


Lesenswert?

Das Wort "inferieren" gibt's eigentlich gar nicht. Jedenfalls hab' ichs 
im Duden nicht gefunden.

"to infer" heißt (im Englischen) soviel wie "etwas (von etwas anderem) 
ableiten" oder "schlußfolgern". Paßt irgendwie nicht so recht.

Fündig wird man aber im Lateinischen. "inferre" heißt "etwas hinzufügen" 
oder "etwas hineintun". Das paßt schon eher.

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


Lesenswert?

Markus F. schrieb:
> Das Wort "inferieren" gibt's eigentlich gar nicht. Jedenfalls hab' ichs
> im Duden nicht gefunden.
Besser als das dem Duden noch nicht bekannte "inferieren" sollte man 
deshalb das geläufigere "instanziieren" nehmen... ;-)

: Bearbeitet durch Moderator
von Burkhard K. (buks)


Angehängte Dateien:

Lesenswert?

Danke Euch soweit für die Antworten, Links und die Testbench.

Vielleicht noch ein Wort zur Erläuterung: Ich will die Breite des 
Eingangsvektors beibehalten, um das zu verarbeitende Signal nicht (um 6 
dB) zu dämpfen - ich rechne hier mit Audiosignalen. Würde ich den 
Wertebereich hier erweitern, müsste ich das an anderer Stelle wieder 
herausrechnen.

Den für mich entscheidenden Hinweis hat Lothar geliefert:
 >Und dass eine Subtraktion eigentlich auch nur eine Addition ist...

D.h. dass das "Borrow out" der Subtraktion dem "Carry Out" der Addition 
entspricht - bzw. dem "Überlaufbit" nach dem ich gesucht habe. Da 
vorzeichenbehaftete Werte verarbeitet werden, steckt diese Information 
im MSB-1. Anhand der Kombination MSB & MSB-1 läßt sich entscheiden, ob 
ein Überlauf im positiven- oder negativen Wertebereich erfolgt:
1
signal to_subst : signed(C_DATA_WIDTH-1 downto 0);
2
signal subst_wc : signed(C_DATA_WIDTH   downto 0);
3
signal to_adder : signed(C_DATA_WIDTH-1 downto 0);
4
5
...
6
7
subst_wc <= to_signed(to_integer(to_subst) - to_integer(accu_msb), subst_wc'length);
8
to_adder <= C_MAXINT when subst_wc(subst_wc'high downto subst_wc'high-1) = "01" else
9
            C_MININT when subst_wc(subst_wc'high downto subst_wc'high-1) = "10" else
10
            subst_wc(subst_wc'high) & subst_wc(subst_wc'high-2 downto 0);

wobei der Vektor subst_wc um ein Bit breiter sein muss als to_adder. Das 
Synthesetool macht daraus:

   Synthesizing Unit <DCremover>.
    Related source file is "...\DCremover.vhd".
        C_DATA_WIDTH = 14
        C_K_WIDTH = 18
        DIN_USGND = '1'
    Found 32-bit register for signal <accu_reg>.
    Found 15-bit subtractor for signal <subst_wc> created at line 75.
    Found 32-bit adder for signal <accu_next> created at line 79.
    Summary:
        inferred   2 Adder/Subtractor(s).
        inferred  32 D-type flip-flop(s).
   Unit <DCremover> synthesized.

Lediglich das RTL-Schaltbild wird durch die nachgeschaltete 
Begrenzerlogik umfangreicher.

Die noch nicht im Duden stehende Sprachschlamperei "Inferieren" möge man 
mir bitte nachsehen - sie ist aber im Gegensatz zu "Instanziieren" 
eindeutig, wie z.B. der Eintrag im "7 Series FPGA Libraries Guide" 
zeigt: Das ADDSUB_MACRO kann zwar instanziiert - aber nicht per Inferenz 
angesprochen werden.

von Fpgakuechle K. (Gast)


Lesenswert?

Markus F. schrieb:
> Das Wort "inferieren" gibt's eigentlich gar nicht. Jedenfalls hab' ichs
> im Duden nicht gefunden.
>
> "to infer" heißt (im Englischen) soviel wie "etwas (von etwas anderem)
> ableiten" oder "schlußfolgern". Paßt irgendwie nicht so recht.

Doch das passt 100%. Inferieren heisst hier das das Synthesetool aus der 
(Verhaltens-)beschreibung erkannt hat, das da bspw ein 8 bit binär 
counter gemeint ist und den dort einfügt. Oder das array of integer als 
BRAM-Block interpretiert und einfügt.

Im deutschen gibt es halt keine passende Übersetzung dafür.

Ich überprüfe beispielsweise im Syntheselog ob das tool "infer counter" 
etc.
an der erwartetet Stellen meldet. Andernfalls ist der Code fürs tool 
unverständlich. "Infered latch" sollte man auch beachten, dann ist die 
Beschreibung meist unvollständig.

Da eine Gegenüberstellung Istanziierung/Inferierung:
http://www.fpga.agh.edu.pl/puc/?download=W_PUC_Tips.pdf

MfG,

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.