mikrocontroller.net

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


Autor: Michael Milan (Firma: Uni Hannover) (babybk)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vorab:
Schreib statt:
  process(Bit_in)
  begin
    Bit_out <= (Bit_add & Bit_in);
  end process;
Besser gleich concurrent:
  Bit_out <= (Bit_add & Bit_in);
Oder am besten gleich so:
  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;

Autor: Michael Milan (Firma: Uni Hannover) (babybk)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
entity PWM is
    Port ( CLK         : in  STD_LOGIC;         
           SINUS1       : in  STD_LOGIC_VECTOR(10 downto 0);
           SINUS2       : in  STD_LOGIC_VECTOR(10 downto 0);
           SINUS3       : in  STD_LOGIC_VECTOR(10 downto 0);
           PWM_OUT1      : out STD_LOGIC;
           PWM_OUT2      : out STD_LOGIC;
           PWM_OUT3      : out STD_LOGIC);
end PWM;

architecture Behavioral of PWM is
signal SIG_KST : std_logic_vector(10 downto 0):= "10111011100";--1500;
begin
    process (CLK)
    begin  
      if rising_edge( CLK ) then
        --PWM1
        if SINUS1 >= SIG_KST then PWM_OUT1 <= '1';
        else                      PWM_OUT1 <= '0';
        end if;
        --PWM2
        if SINUS2 >= SIG_KST then PWM_OUT2 <= '1';
        else                      PWM_OUT2 <= '0';
        end if;
        --PWM3
        if SINUS3 >= SIG_KST then PWM_OUT3 <= '1';
        else                      PWM_OUT3 <= '0';  
        end if;  
      end if;
    end process;
end Behavioral;

Autor: Michael Milan (Firma: Uni Hannover) (babybk)
Datum:

Bewertung
0 lesenswert
nicht 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

library IEEE;
  use IEEE.numeric_std.all;
  use IEEE.std_logic_1164.all;
  
  --use IEEE.STD_LOGIC_ARITH.ALL;
Entity sinnus is
   Port ( CLK       : in  std_logic;
          --Freq_Data : in  std_logic_vector (7 downto 0);
          D_out1      : out std_logic_vector (7 downto 0);
       D_out2      : out std_logic_vector (7 downto 0);
       D_out3      : out std_logic_vector (7 downto 0)
        );
   end sinnus;
  
Architecture RTL of sinnus is
  signal   Result1  : std_logic_vector (7 downto 0);
  signal   Result2  : std_logic_vector (7 downto 0);
  signal   Result3  : std_logic_vector (7 downto 0);
  signal   Accum1   : unsigned (20 downto 0) := (others=>'0'); 
  signal   Accum2   : unsigned (20 downto 0) :="0" & X"AAAAA" ;--[(2^21)-1]/3 = 699.050
  signal   Accum3   : unsigned (20 downto 0) := b"101010101010101010100";--1.398.100
  signal   Freq_Data : std_logic_vector(7 downto 0) := b"00001010";--2
  alias    Address1 : unsigned (6 downto 0) is Accum1(Accum1'high-1 downto Accum1'high-7);
  alias    Address2 : unsigned (6 downto 0) is Accum2(Accum2'high-1 downto Accum2'high-7);
  alias    Address3 : unsigned (6 downto 0) is Accum3(Accum3'high-1 downto Accum3'high-7);
  alias    Sign1    : std_logic is Accum1(Accum1'high); -- MSB
  alias    Sign2    : std_logic is Accum2(Accum2'high);
  alias    Sign3    : std_logic is Accum3(Accum3'high);
  --signal   TG       : std_logic_vector(7 downto 0):=X"7F";
begin
   process begin
     wait until rising_edge(CLK);
     Accum1 <= Accum1 + unsigned(Freq_Data);
    Accum2 <= Accum2 + unsigned(Freq_Data);
    Accum3 <= Accum3 + unsigned(Freq_Data);
   end process;

   process (Address1,Address2,Address3)
     type Rom128x8 is array (0 to 127) of std_logic_vector (7 downto 0); 
    -- Takte = 2^21/Freq_Data
    -->fsinnus = fclk*Freq_Data/2^21
    -- fsinnus = 50 Hz-->Freq_Data = 2
    --Tabelleswerte von 0 nach pi
     constant Sinus_Rom : Rom128x8 := (
       x"00",  x"03",  x"06",  x"09",  x"0c",  x"0f",  x"12",  x"15",
       x"18",  x"1b",  x"1e",  x"21",  x"24",  x"27",  x"2a",  x"2d",
       x"30",  x"33",  x"36",  x"39",  x"3b",  x"3e",  x"41",  x"43",
       x"46",  x"49",  x"4b",  x"4e",  x"50",  x"52",  x"55",  x"57",
       x"59",  x"5b",  x"5e",  x"60",  x"62",  x"64",  x"66",  x"67",
       x"69",  x"6b",  x"6c",  x"6e",  x"70",  x"71",  x"72",  x"74",
       x"75",  x"76",  x"77",  x"78",  x"79",  x"7a",  x"7b",  x"7b",
       x"7c",  x"7d",  x"7d",  x"7e",  x"7e",  x"7e",  x"7e",  x"7e",
       x"7f",  x"7e",  x"7e",  x"7e",  x"7e",  x"7e",  x"7d",  x"7d",
       x"7c",  x"7b",  x"7b",  x"7a",  x"79",  x"78",  x"77",  x"76",
       x"75",  x"74",  x"72",  x"71",  x"70",  x"6e",  x"6c",  x"6b",
       x"69",  x"67",  x"66",  x"64",  x"62",  x"60",  x"5e",  x"5b",
       x"59",  x"57",  x"55",  x"52",  x"50",  x"4e",  x"4b",  x"49",
       x"46",  x"43",  x"41",  x"3e",  x"3b",  x"39",  x"36",  x"33",
       x"30",  x"2d",  x"2a",  x"27",  x"24",  x"21",  x"1e",  x"1b",
       x"18",  x"15",  x"12",  x"0f",  x"0c",  x"09",  x"06",  x"03" );
   begin
     Result1 <= Sinus_Rom (to_integer(Address1));
    Result2 <= Sinus_Rom (to_integer(Address2));
    Result3 <= Sinus_Rom (to_integer(Address3));
   end process;
   
   -- Output registers
   -- ----------------
   process begin
     wait until rising_edge(CLK);
    if (Sign1='1') 
    then   D_out1 <= Result1;        
    else   D_out1 <= std_logic_vector (- signed(Result1));
    end if;
    
    if (Sign2='1') 
    then   D_out2 <= Result2;      
    else   D_out2 <= std_logic_vector (- signed(Result2));
    end if;
    
    if (Sign3='1') 
    then   D_out3 <= Result3;        
    else   D_out3 <= std_logic_vector (- signed(Result3));
    end if;
    
   end process;

end RTL;

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.
    :
    if (Sign1='1') 
    then   D_out1 <= std_logic_vector(to_unsigned(127,8) + unsigned(Result1));        
    else   D_out1 <= std_logic_vector(to_unsigned(127,8) - unsigned(Result1));
    end if;
    :
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'.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.