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


von Hans-Werner (Gast)


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.
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity cvsd_encoder is
6
-- Anfangswerte für die Integratoren bzw. Summierer
7
-- demin = 0.001; demax = 0.1; ts = 1.0; td = 4.0
8
-- samprate = 16000
9
-- leakageFactor=exp(-1/(samprate*td/1000));  
10
-- predictorCoefficient=exp(-1/(samprate*ts/1000));
11
-- Mittels Simulink Fixpoint wurden folgende Zahlenformate ermittelt:
12
-- Für leakageFactor, predictorCoefficient, demin und demax Unsigned Fix(14,14) (14 Nachkommastellen) 
13
-- Für alle anderen Faktoren Signed Fix(16,14) (Vorzeichen, 1 Vorkommastelle, 14 Nachkommastellen)
14
15
-- leakageFactor für:
16
-- 2000;4000:8000:16000
17
-- 0,8825;0,9394;0,9692;0,9845
18
-- 2.000  = 0.11100001'11101011
19
-- 4.000  = 0.11110000'01111101
20
-- 8.000  = 0.11111000'00011111
21
-- 16.000 = 0.11111100'00000111
22
-- predictorCoefficient für:
23
-- 2000;4000;8000;16000
24
-- 0,6065;0,7788;0,8825;0,9394
25
-- 2.000  = 0.10011011'01000101
26
-- 4.000  = 0.11000111'01011111
27
-- 8.000  = 0.11100001'11101011
28
-- 16.000 = 0.11110000'01111101
29
-- leakageFactor = 0.9845
30
-- predictorCoefficient = 0.9394
31
  generic
32
  (
33
    SampleRate : natural := 16000;
34
    inputSize  : natural := 8
35
  );
36
37
  port
38
  (
39
    -----------------------------> Inputs
40
    FilteredWaveSample    : in  std_logic_vector(inputSize-1 downto 0);
41
    clock                 : in  std_logic;
42
    reset                : in   std_logic;
43
    load                  : in  std_logic;
44
    -----------------------------> Outputs
45
    output_valid         : out std_logic;
46
    cvsdOut          : out std_logic
47
  );
48
end cvsd_encoder;
49
50
51
52
architecture cvsd_rtl of cvsd_encoder is
53
   constant int  : natural := 1;
54
  constant frac : natural := 14;
55
   type states is (init_state, diff_state, overload_state, unipolar_state);
56
  signal state : states;
57
  subtype sfix1614 is signed (int+frac downto 0);
58
  subtype sfix3014 is signed (2*(int+frac)-1 downto 0);
59
  subtype ufix1414 is unsigned (frac-1 downto 0);
60
  signal diff, stepSize, estimatedSignal, encStep   : sfix1614;
61
  signal overload         : bit;
62
  signal cvsd          : bit_vector (2 downto 0);
63
  -- Nur Nachkommastellen
64
  constant leakageFactor       : ufix1414 := b"11111100_000001";
65
  constant predictorCoeffizient  : ufix1414 := b"11110000_011111";
66
  -- demin 0.001 = 0.00000000'01000001
67
  -- demax 0.1  = 0.00011001'10011001
68
  -- Nur Nachkommastellen
69
  constant demin : ufix1414 := b"00000000_010000";
70
  constant demax : ufix1414 := b"00011001_100110";
71
  -- (Vorzeichen, 1 Vorkommastelle, 14 Nachkommastellen)
72
  signal summe : sfix1614;
73
  -- signal product1, product2 : sfix3014;
74
begin  
75
  process (clock)
76
    variable product1, product2 : sfix3014;
77
  begin
78
    if rising_edge(clock)
79
    then
80
      case state is
81
        when init_state =>    if reset = '1'
82
                        then
83
                          estimatedSignal <= (others => '0');
84
                          encStep <= (others => '0');
85
                          cvsd(0) <= '0';
86
                          cvsd(1) <= '0';
87
                          if load = '1'
88
                          then
89
                            state <= diff_state;
90
                          end if;
91
                        end if;
92
                                        
93
        when diff_state =>    -- SFix(16,14) = UFix(16,0) - SFix(16,14)
94
                        diff <=   signed(FilteredWaveSample) - estimatedSignal;
95
                        if to_integer(diff) >= 0
96
                        then
97
                          cvsd(2) <= '1';
98
                        else
99
                          cvsd(2) <= '0';
100
                        end if;
101
                        state <= overload_state;
102
                    
103
        when overload_state =>  overload <= (cvsd(0) and cvsd(1) and cvsd(2)) or
104
                                (not cvsd(0) and not cvsd(1) and not cvsd(2));
105
                        if overload = '1'
106
                        then
107
                          -- Addition des Nachkommaanteils
108
                          -- SFix(16,14) = SFix(16,14) + UFix(14,14)
109
                           summe <= encStep + signed(demin);
110
                          -- encStep <= min(summe,demax);
111
                          if summe < to_integer(demax)
112
                          then
113
                            encStep <= summe;
114
                          else
115
                            -- Zuweisung des Nachkommaanteils
116
                            -- SFix(16,14) = UFix(14,14)
117
                            encStep(frac-1 downto 0) <= signed(demax);
118
                          end if;
119
                        else
120
                          -- SFix(30,14) = SFix(16,14) * UFix(14,14)
121
                           product1 := encStep * signed(leakageFactor);
122
                          -- encStep <= max(produkt,demin);
123
                          if product1 < to_integer(demin)
124
                          then
125
                            encStep <= product1(int+frac downto 0);
126
                          else
127
                            encStep(frac-1 downto 0) <= signed(demin);
128
                          end if;
129
                        end if;
130
                        state <= unipolar_state;
131
                    
132
        when unipolar_state =>  -- Unipolar to Bipolar
133
                        -- Aus [0,1] wird [-1,+1]
134
                        -- stepSize <= factor * encStep;
135
                        if cvsd(2) = '0'
136
                        then
137
                          stepSize <= -encStep;
138
                        else
139
                          stepSize <= encStep;
140
                        end if;
141
                        -- SFix(30,14) = SFix(16,14) * UFix(14,14)
142
                        product2 := estimatedSignal * signed(predictorCoeffizient);
143
                        -- SFix(16,14) = SFix(16,14) + ????
144
                        estimatedSignal <= stepSize + product2(int+frac downto 0);
145
                        cvsd(0) <= cvsd(1);
146
                        cvsd(1) <= cvsd(2);
147
                        cvsdout <= to_stdulogic(cvsd(2));
148
                        output_valid <= '1';
149
      end case;
150
    end if;
151
  end process;
152
  
153
end architecture cvsd_rtl;

von Duke Scarring (Gast)


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.

von Hans-Werner (Gast)


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.

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.