Forum: FPGA, VHDL & Co. Funktionsabbildung mit Altera Integer Arithmethic Megafunctions


von yunokwork (Gast)


Lesenswert?

Ich möchte in VHDL folgende Funktionsabbildung mit den Altera Integer 
Arithmethic Megafunctions realisieren:

f(x)= floor( 255*(x-50)/150 )
x ist eine unsigned 8bit Zahl mit 50 < x < 200
also bspw.
f(51) = floor(1.7) =1
f(199) = floor(253.3) = 253

f(x) soll auch wieder eine unsigned 8bit Zahl sein

Ich habe in der PDF( 
http://www.altera.com/literature/ug/ug_lpm_alt_mfug.pdf ) zu den Altera 
Integer Arithmethic Megafunctions keine größere Erklärung gesehen, also 
sehe zumindest nicht, wie ich die anders verwenden sollte... kriege aber 
immer 0 für f raus (wenn done flag gesetzt ist).

Hier der Code:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
LIBRARY lpm;
5
USE lpm.lpm_components.all;
6
 
7
ENTITY Func IS
8
PORT(
9
    x      : in std_logic_vector(7 downto 0);
10
    reset  : in std_logic;
11
    clk : in std_logic;
12
    f      : out std_logic_vector(7 downto 0);
13
    done   : out std_logic;
14
    );
15
END Func;
16
    
17
ARCHITECTURE rtl OF Func IS
18
19
--dividierer mit 16 bit zähler und 8bit nenner
20
component LPM_DIVIDE
21
    generic (LPM_WIDTHN : natural := 16;
22
         LPM_WIDTHD : natural := 8;
23
LPM_NREPRESENTATION : string := "UNSIGNED";
24
LPM_DREPRESENTATION : string := "UNSIGNED";
25
LPM_PIPELINE : natural := 0;
26
LPM_TYPE : string := L_DIVIDE;
27
LPM_HINT : string := "UNUSED");
28
port (NUMER : in std_logic_vector(LPM_WIDTHN-1 downto 0);
29
DENOM : in std_logic_vector(LPM_WIDTHD-1 downto 0);
30
ACLR : in std_logic := '0';
31
CLOCK : in std_logic := '0';
32
CLKEN : in std_logic := '1';
33
QUOTIENT : out std_logic_vector(LPM_WIDTHN-1 downto 0);
34
REMAIN : out std_logic_vector(LPM_WIDTHD-1 downto 0));
35
end component;
36
 
37
component LPM_MULT
38
    generic ( LPM_WIDTHA : natural := 8;
39
         LPM_WIDTHB : natural := 8;
40
         LPM_WIDTHS : natural := 16;
41
         LPM_WIDTHP : natural := 16;
42
LPM_REPRESENTATION : string := "UNSIGNED";
43
LPM_PIPELINE : natural := 0;
44
LPM_TYPE: string := L_MULT;
45
LPM_HINT : string := "UNUSED");
46
port ( DATAA : in std_logic_vector(LPM_WIDTHA-1 downto 0);
47
DATAB : in std_logic_vector(LPM_WIDTHB-1 downto 0);
48
ACLR : in std_logic := '0';
49
CLOCK : in std_logic := '0';
50
CLKEN : in std_logic := '1';
51
SUM : in std_logic_vector(LPM_WIDTHS-1 downto 0) := (OTHERS
52
=> '0');
53
RESULT : out std_logic_vector(LPM_WIDTHP-1 downto 0));
54
end component;
55
 
56
type state_t is (S_start, S_calc, S_done);
57
signal state, state_nxt : state_t;
58
59
signal cs_div_res  : std_logic_vector(15 downto 0);
60
signal cs_mult_res : std_logic_vector(15 downto 0);
61
signal cs_diff_res : std_logic_vector(7 downto 0);
62
signal counter : std_logic_vector(7 downto 0);
63
signal calc : std_logic;
64
 
65
 begin
66
 
67
  cs_mult: LPM_MULT
68
  port map (
69
     DATAA  => "11111111",
70
     DATAB  => cs_diff_res,
71
     RESULT => cs_mult_res);
72
 
73
  cs_div: LPM_DIVIDE
74
  port map (
75
     NUMER    => cs_mult_res,
76
     DENOM    => "10010110", --150 binär
77
     QUOTIENT => cs_div_res);
78
 
79
  process(x)
80
    begin
81
     cs_diff_res <= std_logic_vector(unsigned(x)-unsigned("110010")); --binär 50
82
     f <= cd_div_res (7 downto 0); --die ersten 8 least significant bit
83
  end process;
84
85
  process(clk)
86
  begin
87
    if clk_in'event and clk_in='1' then
88
      if reset = '1' then
89
        counter <= (others => '0');
90
        state <= S_start;
91
      end if;         
92
        state <= state_nxt;
93
      if calc = '1' then
94
        counter <= std_logic_vector(unsigned(counter) + 1);
95
      else
96
        counter <= (others => '0');
97
      end if;
98
    end if;
99
  end process;
100
 
101
  process(state, counter)
102
  begin
103
      --defaultwerte
104
  
105
      state_nxt <= state;
106
      calc <= '0';
107
      done <= '0';
108
 
109
      case state is
110
         when S_start =>
111
          state_nxt <= S_calc;
112
           
113
         when S_calc =>
114
          calc='1';
115
          if counter > 50 then --nach spätestens 50 takten sollte die berechnung fertig sein
116
            state_nxt <= S_done;
117
          end if;
118
119
         when S_done =>
120
          done <= '1';
121
          --idle
122
      end case;
123
  end process;
124
END rtl;

von FPGA-Expert (Gast)


Lesenswert?

wenn die 150 fest stehen, nimm doch einfach mit k/150 mal

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


Lesenswert?

yunokwork schrieb:
> kriege aber immer 0 für f raus
Teil die Rechnung mal in kleiner Schritte auf.
Und: in welchem Rechenschritt klemmt es?

Dir ist schon klar, dass der Synthesizer bei deiner Schreibweise gerne 
auch so rechnen darf: f(x)= floor( 255*((x-50)/150) )
Und  (x-50)/150   ist fast immer kleiner als 1...  :-o


Überaus bedenklich ist übrigens die Division mit 150. Ich würde diesen 
Rechenschritt eher eine Multiplikation und anschliessendes Abschneiden 
von LSBs umwandeln.

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.