division von signed

Gast #3094548
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
Moderator (Firma: Titel) Persönliche Seite #3094626
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren