Forum: FPGA, VHDL & Co. division von signed


von Hans (Gast)


Lesenswert?

Hallo,
ich versuch gerade einen exp. gleitenden Mittelwert zu beschreiben.
1
 
2
entity exp_average is
3
    Port ( clk   : in  STD_LOGIC;
4
           value   : in  signed (1 downto 0);  -- -1, 0 , +1
5
           mean   : out signed (31 downto 0));
6
end exp_average;
7
8
architecture Behavioral of exp_average is
9
10
  signal state    : std_logic := '0';
11
  signal exp_mean_a : signed (31 downto 0) := to_signed(0, 32);
12
  signal exp_mean_b : signed (31  downto 0) := to_signed(0, 32); 
13
14
begin
15
16
process (clk)
17
begin
18
  if rising_edge(clk) then
19
    
20
    if state = '0' then
21
      state <= '1';
22
      mean <= exp_mean_b srl 12;
23
      exp_mean_a   <= (exp_mean_b - (exp_mean_b srl 12)) + (resize(signed(value),32) sll 12);
24
    else
25
      state <= '0';
26
      mean <= exp_mean_b srl 12;
27
      exp_mean_b   <= (exp_mean_a - (exp_mean_a srl 12)) +  (resize(signed(value),32) sll 12);
28
    end if;
29
  end if;
30
end process;
31
32
end Behavioral;
Value soll nur die Werte -1, 0, 1 annehmen. Wenn es 1 hat, dann 
konvergiert mean auch schön gegen 4096. Jedoch bei -1 funktioniert, dass 
ganze nicht. Wahrscheinlich liegt es an dem Shiften. Man könnte das 
Shiften durch Multiplikation/Divison ersetzen, aber da müsste man doch 
die Bitzahl des Ergebnisses erweitern? Gibt es eine Möglichkeit das 
Shiften vorzeichen unabhänging durchzuführen?

Mfg
Hans

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


Lesenswert?

Hans schrieb:
> Wahrscheinlich liegt es an dem Shiften.
Was sagt denn die Simulation?

Das ist die srl in der numeric_std:
1
  function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is
2
  begin
3
    if (COUNT >= 0) then
4
      return SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT));  -- hoppala, da wird unsigned geshiftet!!
5
    else
6
      return SHIFT_LEFT(ARG, -COUNT);
7
    end if;
8
  end "srl";

Nimm besser gleich die SHIFT_RIGHT:
1
  function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is
2
  begin
3
    if (ARG'LENGTH < 1) then return NAS;
4
    end if;
5
    return SIGNED(XSRA(STD_LOGIC_VECTOR(ARG), COUNT));
6
  end SHIFT_RIGHT;
7
8
  function XSRA (ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR
9
      is
10
    constant ARG_L: INTEGER := ARG'LENGTH-1;
11
    alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG;
12
    variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0);
13
    variable XCOUNT: NATURAL := COUNT;
14
  begin
15
    if ((ARG'LENGTH <= 1) or (XCOUNT = 0)) then return ARG;
16
    else
17
      if (XCOUNT > ARG_L) then XCOUNT := ARG_L;
18
      end if;
19
      RESULT(ARG_L-XCOUNT downto 0) := XARG(ARG_L downto XCOUNT);
20
      RESULT(ARG_L downto (ARG_L - XCOUNT + 1)) := (others => XARG(ARG_L)); -- hier ist die Vorzeichenerweiterung
21
    end if;
22
    return RESULT;
23
  end XSRA;

Allerdings solltest du aufassen: die Division einer negativen Zahl durch 
2 ist nicht das selbe wie ein Rechtsshift einer negativen Zahl um 1.

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.