Forum: FPGA, VHDL & Co. Problem mit Bit addieren!


von Michael M. (Firma: Uni Hannover) (babybk)


Lesenswert?

ich hab
*ein Sinnussignal(50 Hz,maximal Amplitude = 127) mit 8 bit 
std_logic_vector
*ein konstant Signal auch 8 bit mit dem Wert 127

Weil Sinnussignal inklusiv die negativen Werte hat,muss ich die 0 Punkt 
von Sinnus mit 128 in y Richtung addieren.
Dann vergleiche ich die Werte zwischen Sinnussignal und 
Konstantsignal,um PWM Signal zu bekommen.

-->hab ich ein schöne PWM(halbe Periode =1,halbe Periode = 0).Das ist 
okie.

Problem ist:

wenn Konstantksignal nicht 8 bit sondern 11 bit ist,muss die Bitzahl des 
Sinnussignal auch vergrößern.Der Wert des Konstantsignal ist jetzt 1627

Benutze ich folgende Code
-----------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Add_Bit is
    Port ( Bit_in : in  STD_LOGIC_VECTOR (7 downto 0);
           Bit_out : out  STD_LOGIC_VECTOR (10 downto 0));
end Add_Bit;
architecture Behavioral of Add_Bit is
constant Bit_add : std_logic_vector(2 downto 0) :="000";
begin
  process(Bit_in)
  begin
    Bit_out <= (Bit_add & Bit_in);
  end process;
end Behavioral;
---------------------
und Bit_in => Sinnussignal

Weil der Wert des Konstant Signal 1627,deshalb muss 0 Punkt von Sinnus 
noch 1500 addiere.

Ausgang 'Bit_out' =>'sig_in'
----------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity skala_verschiebung is
    Port ( sig_in : in  STD_LOGIC_VECTOR (10 downto 0);
           sig_out : out  STD_LOGIC_VECTOR (10 downto 0));
end skala_verschiebung;

architecture Behavioral of skala_verschiebung is

constant TG1 : std_logic_vector(8 downto 0):="1111111";--127
constant TG2 : std_logic_vector(10 downto 0):= "10111011100"--1500;
begin
process(sig_in)
begin
sig_out <= (sig_in + TG1+TG2);
end process;
end Behavioral;

-----------------------
Und mache ich das Vergleichen aber... PWM ist immer 1.Kann nicht 
verstehen

Jemand kann mir helfen.
Danke im Voraus.

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


Lesenswert?

Vorab:
Schreib statt:
1
  process(Bit_in)
2
  begin
3
    Bit_out <= (Bit_add & Bit_in);
4
  end process;
Besser gleich concurrent:
1
  Bit_out <= (Bit_add & Bit_in);
Oder am besten gleich so:
1
  Bit_out <= "000" & Bit_in;

> Und mache ich das Vergleichen
Wo denn?
Kopiere bitte deine Dateien incl. Vergliicher in eine vhdl-Datei und 
poste die. Du kannst auch mehrere Dateien an deinen Post anhängen...

Warum machst du für jede Zeile Code eine eigene Entity? Das ist doch 
absolut unübersichtlich...

Warum machst du das nicht mit numeric_std? Da kannst du sinnvoll und 
reproduzierbar rechnen, ganz ohne Abhängikeiten von
use IEEE.STD_LOGIC_UNSIGNED.ALL;
oder
use IEEE.STD_LOGIC_SIGNED.ALL;

von Michael M. (Firma: Uni Hannover) (babybk)


Angehängte Dateien:

Lesenswert?

@Lothar Miller

"Warum machst du für jede Zeile Code eine eigene Entity? Das ist doch
absolut unübersichtlich..."

-->weil ich Schematik benutze d.h jede Block muss ich defeniere.

Anhang schike ich Code dabei.

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


Lesenswert?

> Anhang schike ich Code dabei.
Ziemlich böse Herumjongliererei mit Variablen...

> PWM ist immer 1
Welche Werte kommen denn an den Signalen SINNUS1-3 herein?


BTW:
1)
Die Dreiecksfunktion, die hier verwendet wird, heisst SINUS  :-/

2)
Der Code wäre so (ohne signifikante Funktionsänderung) wesentlich 
aufgeräumter:
1
entity PWM is
2
    Port ( CLK         : in  STD_LOGIC;         
3
           SINUS1       : in  STD_LOGIC_VECTOR(10 downto 0);
4
           SINUS2       : in  STD_LOGIC_VECTOR(10 downto 0);
5
           SINUS3       : in  STD_LOGIC_VECTOR(10 downto 0);
6
           PWM_OUT1      : out STD_LOGIC;
7
           PWM_OUT2      : out STD_LOGIC;
8
           PWM_OUT3      : out STD_LOGIC);
9
end PWM;
10
11
architecture Behavioral of PWM is
12
signal SIG_KST : std_logic_vector(10 downto 0):= "10111011100";--1500;
13
begin
14
    process (CLK)
15
    begin  
16
      if rising_edge( CLK ) then
17
        --PWM1
18
        if SINUS1 >= SIG_KST then PWM_OUT1 <= '1';
19
        else                      PWM_OUT1 <= '0';
20
        end if;
21
        --PWM2
22
        if SINUS2 >= SIG_KST then PWM_OUT2 <= '1';
23
        else                      PWM_OUT2 <= '0';
24
        end if;
25
        --PWM3
26
        if SINUS3 >= SIG_KST then PWM_OUT3 <= '1';
27
        else                      PWM_OUT3 <= '0';  
28
        end if;  
29
      end if;
30
    end process;
31
end Behavioral;

von Michael M. (Firma: Uni Hannover) (babybk)


Lesenswert?

>Welche Werte kommen denn an den Signalen SINNUS1-3 herein?

Wert von Block sinnus

> Die Dreiecksfunktion, die hier verwendet wird, heisst SINUS  :-/

Ja,benutze ich deinen Sinnuscode(3 sinnussignal mit 120 versetzt).
Problem ist:bekomme ich falsches Ergebnis,wenn ich die 0-von Sinnus 
verschiebe.Ich verstehe nicht warum
>
> 2)
> ohne signifikante Funktionsänderung
 was bedeutet das?

Gebe ich wieder deinen Sinnus Code
1
library IEEE;
2
  use IEEE.numeric_std.all;
3
  use IEEE.std_logic_1164.all;
4
  
5
  --use IEEE.STD_LOGIC_ARITH.ALL;
6
Entity sinnus is
7
   Port ( CLK       : in  std_logic;
8
          --Freq_Data : in  std_logic_vector (7 downto 0);
9
          D_out1      : out std_logic_vector (7 downto 0);
10
       D_out2      : out std_logic_vector (7 downto 0);
11
       D_out3      : out std_logic_vector (7 downto 0)
12
        );
13
   end sinnus;
14
  
15
Architecture RTL of sinnus is
16
  signal   Result1  : std_logic_vector (7 downto 0);
17
  signal   Result2  : std_logic_vector (7 downto 0);
18
  signal   Result3  : std_logic_vector (7 downto 0);
19
  signal   Accum1   : unsigned (20 downto 0) := (others=>'0'); 
20
  signal   Accum2   : unsigned (20 downto 0) :="0" & X"AAAAA" ;--[(2^21)-1]/3 = 699.050
21
  signal   Accum3   : unsigned (20 downto 0) := b"101010101010101010100";--1.398.100
22
  signal   Freq_Data : std_logic_vector(7 downto 0) := b"00001010";--2
23
  alias    Address1 : unsigned (6 downto 0) is Accum1(Accum1'high-1 downto Accum1'high-7);
24
  alias    Address2 : unsigned (6 downto 0) is Accum2(Accum2'high-1 downto Accum2'high-7);
25
  alias    Address3 : unsigned (6 downto 0) is Accum3(Accum3'high-1 downto Accum3'high-7);
26
  alias    Sign1    : std_logic is Accum1(Accum1'high); -- MSB
27
  alias    Sign2    : std_logic is Accum2(Accum2'high);
28
  alias    Sign3    : std_logic is Accum3(Accum3'high);
29
  --signal   TG       : std_logic_vector(7 downto 0):=X"7F";
30
begin
31
   process begin
32
     wait until rising_edge(CLK);
33
     Accum1 <= Accum1 + unsigned(Freq_Data);
34
    Accum2 <= Accum2 + unsigned(Freq_Data);
35
    Accum3 <= Accum3 + unsigned(Freq_Data);
36
   end process;
37
38
   process (Address1,Address2,Address3)
39
     type Rom128x8 is array (0 to 127) of std_logic_vector (7 downto 0); 
40
    -- Takte = 2^21/Freq_Data
41
    -->fsinnus = fclk*Freq_Data/2^21
42
    -- fsinnus = 50 Hz-->Freq_Data = 2
43
    --Tabelleswerte von 0 nach pi
44
     constant Sinus_Rom : Rom128x8 := (
45
       x"00",  x"03",  x"06",  x"09",  x"0c",  x"0f",  x"12",  x"15",
46
       x"18",  x"1b",  x"1e",  x"21",  x"24",  x"27",  x"2a",  x"2d",
47
       x"30",  x"33",  x"36",  x"39",  x"3b",  x"3e",  x"41",  x"43",
48
       x"46",  x"49",  x"4b",  x"4e",  x"50",  x"52",  x"55",  x"57",
49
       x"59",  x"5b",  x"5e",  x"60",  x"62",  x"64",  x"66",  x"67",
50
       x"69",  x"6b",  x"6c",  x"6e",  x"70",  x"71",  x"72",  x"74",
51
       x"75",  x"76",  x"77",  x"78",  x"79",  x"7a",  x"7b",  x"7b",
52
       x"7c",  x"7d",  x"7d",  x"7e",  x"7e",  x"7e",  x"7e",  x"7e",
53
       x"7f",  x"7e",  x"7e",  x"7e",  x"7e",  x"7e",  x"7d",  x"7d",
54
       x"7c",  x"7b",  x"7b",  x"7a",  x"79",  x"78",  x"77",  x"76",
55
       x"75",  x"74",  x"72",  x"71",  x"70",  x"6e",  x"6c",  x"6b",
56
       x"69",  x"67",  x"66",  x"64",  x"62",  x"60",  x"5e",  x"5b",
57
       x"59",  x"57",  x"55",  x"52",  x"50",  x"4e",  x"4b",  x"49",
58
       x"46",  x"43",  x"41",  x"3e",  x"3b",  x"39",  x"36",  x"33",
59
       x"30",  x"2d",  x"2a",  x"27",  x"24",  x"21",  x"1e",  x"1b",
60
       x"18",  x"15",  x"12",  x"0f",  x"0c",  x"09",  x"06",  x"03" );
61
   begin
62
     Result1 <= Sinus_Rom (to_integer(Address1));
63
    Result2 <= Sinus_Rom (to_integer(Address2));
64
    Result3 <= Sinus_Rom (to_integer(Address3));
65
   end process;
66
   
67
   -- Output registers
68
   -- ----------------
69
   process begin
70
     wait until rising_edge(CLK);
71
    if (Sign1='1') 
72
    then   D_out1 <= Result1;        
73
    else   D_out1 <= std_logic_vector (- signed(Result1));
74
    end if;
75
    
76
    if (Sign2='1') 
77
    then   D_out2 <= Result2;      
78
    else   D_out2 <= std_logic_vector (- signed(Result2));
79
    end if;
80
    
81
    if (Sign3='1') 
82
    then   D_out3 <= Result3;        
83
    else   D_out3 <= std_logic_vector (- signed(Result3));
84
    end if;
85
    
86
   end process;
87
88
end RTL;

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


Lesenswert?

> Weil Sinnussignal inklusiv die negativen Werte hat
Wenn dich das stört, dann pass doch einfach die Sinus-Erzeugung an.
Und zwar genau so:
> muss ich die 0 Punkt von Sinnus mit 128 in y Richtung addieren.
Dazu solltest du dir die arithmetischen Funktionen der VHDL-Libs genauer 
anschauen.
1
    :
2
    if (Sign1='1') 
3
    then   D_out1 <= std_logic_vector(to_unsigned(127,8) + unsigned(Result1));        
4
    else   D_out1 <= std_logic_vector(to_unsigned(127,8) - unsigned(Result1));
5
    end if;
6
    :
Alles weitere sind mathematische Grundlagen...

Nochmal:
Ersetze SINNUS durch SINUS  :-/
Sinus hat nur 1 'n', auch Cosinus hat nur 1 'n'. Nur Tangens hat 2 'n'.

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.