mikrocontroller.net

Forum: FPGA, VHDL & Co. CVSD Encoder in Fixpoint


Autor: Hans-Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich versuche mich gerade an einem CVSD-Encoder in VHDL.
Ich komme noch nicht mit der Fixpoint-Darstellung zurecht.
Mittels Simulink Fixed Point habe ich mich für folgende Formate 
entschieden: Signed Fix(16,14) und Unsigned Fix(14,14) siehe unten.
Nun geht es um die Addition, Subtraktion und Multiplikation dieser 
Zahlenformate. Also andere ist erstmal unwichtig.
Kann mir jemand mal dabei weiterhelfen ?
Eingabe soll eine Datei (Nur die Abtastwerte) im Wave-Format sein.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity cvsd_encoder is
-- Anfangswerte für die Integratoren bzw. Summierer
-- demin = 0.001; demax = 0.1; ts = 1.0; td = 4.0
-- samprate = 16000
-- leakageFactor=exp(-1/(samprate*td/1000));  
-- predictorCoefficient=exp(-1/(samprate*ts/1000));
-- Mittels Simulink Fixpoint wurden folgende Zahlenformate ermittelt:
-- Für leakageFactor, predictorCoefficient, demin und demax Unsigned Fix(14,14) (14 Nachkommastellen) 
-- Für alle anderen Faktoren Signed Fix(16,14) (Vorzeichen, 1 Vorkommastelle, 14 Nachkommastellen)

-- leakageFactor für:
-- 2000;4000:8000:16000
-- 0,8825;0,9394;0,9692;0,9845
-- 2.000  = 0.11100001'11101011
-- 4.000  = 0.11110000'01111101
-- 8.000  = 0.11111000'00011111
-- 16.000 = 0.11111100'00000111
-- predictorCoefficient für:
-- 2000;4000;8000;16000
-- 0,6065;0,7788;0,8825;0,9394
-- 2.000  = 0.10011011'01000101
-- 4.000  = 0.11000111'01011111
-- 8.000  = 0.11100001'11101011
-- 16.000 = 0.11110000'01111101
-- leakageFactor = 0.9845
-- predictorCoefficient = 0.9394
  generic
  (
    SampleRate : natural := 16000;
    inputSize  : natural := 8
  );

  port
  (
    -----------------------------> Inputs
    FilteredWaveSample    : in  std_logic_vector(inputSize-1 downto 0);
    clock                 : in  std_logic;
    reset                : in   std_logic;
    load                  : in  std_logic;
    -----------------------------> Outputs
    output_valid         : out std_logic;
    cvsdOut          : out std_logic
  );
end cvsd_encoder;



architecture cvsd_rtl of cvsd_encoder is
   constant int  : natural := 1;
  constant frac : natural := 14;
   type states is (init_state, diff_state, overload_state, unipolar_state);
  signal state : states;
  subtype sfix1614 is signed (int+frac downto 0);
  subtype sfix3014 is signed (2*(int+frac)-1 downto 0);
  subtype ufix1414 is unsigned (frac-1 downto 0);
  signal diff, stepSize, estimatedSignal, encStep   : sfix1614;
  signal overload         : bit;
  signal cvsd          : bit_vector (2 downto 0);
  -- Nur Nachkommastellen
  constant leakageFactor       : ufix1414 := b"11111100_000001";
  constant predictorCoeffizient  : ufix1414 := b"11110000_011111";
  -- demin 0.001 = 0.00000000'01000001
  -- demax 0.1  = 0.00011001'10011001
  -- Nur Nachkommastellen
  constant demin : ufix1414 := b"00000000_010000";
  constant demax : ufix1414 := b"00011001_100110";
  -- (Vorzeichen, 1 Vorkommastelle, 14 Nachkommastellen)
  signal summe : sfix1614;
  -- signal product1, product2 : sfix3014;
begin  
  process (clock)
    variable product1, product2 : sfix3014;
  begin
    if rising_edge(clock)
    then
      case state is
        when init_state =>    if reset = '1'
                        then
                          estimatedSignal <= (others => '0');
                          encStep <= (others => '0');
                          cvsd(0) <= '0';
                          cvsd(1) <= '0';
                          if load = '1'
                          then
                            state <= diff_state;
                          end if;
                        end if;
                                        
        when diff_state =>    -- SFix(16,14) = UFix(16,0) - SFix(16,14)
                        diff <=   signed(FilteredWaveSample) - estimatedSignal;
                        if to_integer(diff) >= 0
                        then
                          cvsd(2) <= '1';
                        else
                          cvsd(2) <= '0';
                        end if;
                        state <= overload_state;
                    
        when overload_state =>  overload <= (cvsd(0) and cvsd(1) and cvsd(2)) or
                                (not cvsd(0) and not cvsd(1) and not cvsd(2));
                        if overload = '1'
                        then
                          -- Addition des Nachkommaanteils
                          -- SFix(16,14) = SFix(16,14) + UFix(14,14)
                           summe <= encStep + signed(demin);
                          -- encStep <= min(summe,demax);
                          if summe < to_integer(demax)
                          then
                            encStep <= summe;
                          else
                            -- Zuweisung des Nachkommaanteils
                            -- SFix(16,14) = UFix(14,14)
                            encStep(frac-1 downto 0) <= signed(demax);
                          end if;
                        else
                          -- SFix(30,14) = SFix(16,14) * UFix(14,14)
                           product1 := encStep * signed(leakageFactor);
                          -- encStep <= max(produkt,demin);
                          if product1 < to_integer(demin)
                          then
                            encStep <= product1(int+frac downto 0);
                          else
                            encStep(frac-1 downto 0) <= signed(demin);
                          end if;
                        end if;
                        state <= unipolar_state;
                    
        when unipolar_state =>  -- Unipolar to Bipolar
                        -- Aus [0,1] wird [-1,+1]
                        -- stepSize <= factor * encStep;
                        if cvsd(2) = '0'
                        then
                          stepSize <= -encStep;
                        else
                          stepSize <= encStep;
                        end if;
                        -- SFix(30,14) = SFix(16,14) * UFix(14,14)
                        product2 := estimatedSignal * signed(predictorCoeffizient);
                        -- SFix(16,14) = SFix(16,14) + ????
                        estimatedSignal <= stepSize + product2(int+frac downto 0);
                        cvsd(0) <= cvsd(1);
                        cvsd(1) <= cvsd(2);
                        cvsdout <= to_stdulogic(cvsd(2));
                        output_valid <= '1';
      end case;
    end if;
  end process;
  
end architecture cvsd_rtl;

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist denn die genaue Frage? Gibt es eine Testbench dazu? Und die 
Testvektoren? Und ist es richtig, das reset nur im init_state 
funktioniert?

Duke

P.S.: Der emacs hat einen vhdl-beautyfier eingebaut. Damit kann man den 
Code gleich viel lesbarer machen.

Autor: Hans-Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe oben:
Nun geht es um die Addition, Subtraktion und Multiplikation dieser
Zahlenformate. Also andere ist erstmal unwichtig.
Kann mir jemand mal dabei weiterhelfen ?

Ich habe mich bisher noch nicht an Fixpunkt-Arithmetik versucht.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.