Forum: FPGA, VHDL & Co. Sinus Phasen Verschiebung


von otti (Gast)


Lesenswert?

hallo,

ich arbeite zu zeit mit einem FPGA von der familie Spartan 3E.ich muss 
ein Sinussignal erzeugen 40Khz.der Fpga wird extern gesteuert mit 10Mhz.
die sinus Tabelle hat 250 Werte.bis jetzt war alles schön das könnte ich 
machen.
das problem ist Phasen verschiebung.ich soll mit 2 taster das Signal 
nach recht oder nach links verschieben.
hat sowas schon jemand gemacht?

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


Lesenswert?

otti schrieb:
> bis jetzt war alles schön das könnte ich machen.
Zeig doch mal deinen Code...

> das problem ist Phasen verschiebung.
> ich soll mit 2 taster das Signal
> nach recht oder nach links verschieben.
Und was ist daran komplizierter? Du mußt doch lediglich einen Offset auf 
deinen Index (in der Sinustabelle) draufaddieren....
Oder habe ich da was nicht verstanden?

> ich soll mit 2 taster das Signal
> nach recht oder nach links verschieben.
Was heißt hier "links" und "rechts"?

von hdd (Gast)


Lesenswert?

Die Frage ich auch, worauf sich denn deine Phase bezieht?
Ansonsten, bei jedem Tastendruck eine bestimmte Schrittweite vor oder 
zurück in der Tabelle springen und dort weitermachen.

von otti (Gast)


Lesenswert?

------------------------------------------------------------------------ 
----------
-- Company:
-- Engineer:
--
-- Create Date:    12:01:54 12/12/2010
-- Design Name:
-- Module Name:    Blinky_test - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
------------------------------------------------------------------------ 
----------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;



-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;

entity Blinky_test is
    Port ( SYSCLK : in  STD_LOGIC; -- board clock 48MHz
--        COMP_IN : in STD_LOGIC; -- 10MHz comparator input
        NPG : in STD_LOGIC; -- low active power good -- COMP_IN new 
comparator
           LED0 : out  STD_LOGIC := '0'; -- J3-3 is EXT-IO1 at F12
           LED1 : out  STD_LOGIC := '0'; -- J3-5 is EXT-IO3 at A12
           KEY0 : in  STD_LOGIC; -- J3-2 is EXT-IO0 at C12
           KEY1 : in  STD_LOGIC;-- J3-9 is EXT-IO5 at G13

        DAC_DATA  : out STD_LOGIC_VECTOR(11 downto 0) := (others => 
'0');
        DAC_nWR   : out STD_LOGIC := '0'; -- J4-14 is EXT2_IO10 at L2
        DAC_nCS   : out STD_LOGIC := '0'; -- J4-15 is EXT2_IO11 at F1
        DAC_nAB   : out STD_LOGIC := '0'  -- J4-34 is EXT2_IO25 at F14
      );
end Blinky_test;

architecture Behavioral of Blinky_test is

--signal counter : std_logic_vector(9 downto 0) := (others => '0');
signal clk : std_logic := '0';
signal clk_div2 : std_logic := '0';
signal position_sinus1 : integer range 0 to 249 := 0;
signal triangle : std_logic_vector(11 downto 0) := (others => '0');
signal position_sinus2 : integer range 0 to 249 := 0;

signal sinus_offset : integer range 0 to 1000 := 0;
signal sinus_out : std_logic_vector(11 downto 0) := (others => '0');

signal key0_debounce : std_logic := '0';

--type sintab is array(0 to 249) of STD_LOGIC_VECTOR(11 downto 0);   -- 
speicher -250 Werte -
type sintab is array(0 to 249) of STD_LOGIC_VECTOR(11 downto 0);   -- 
speicher -250 Werte -
constant sinus : sintab :=(

x"800",x"833",x"867",x"89A",x"8CD",x"901",x"934",x"966",
x"999",x"9CB",x"9FD",x"A2F",x"A60",x"A91",x"AC1",x"AF2",
x"B21",x"B50",x"B7F",x"BAD",x"BDA",x"C07",x"C33",x"C5F",
x"C89",x"CB3",x"CDD",x"D05",x"D2D",x"D53",x"D79",x"D9E",
x"DC3",x"DE6",x"E08",x"E29",x"E4A",x"E69",x"E87",x"EA4",
x"EC1",x"EDC",x"EF6",x"F0E",x"F26",x"F3D",x"F52",x"F66",
x"F79",x"F8B",x"F9B",x"FAB",x"FB9",x"FC6",x"FD1",x"FDB",
x"FE4",x"FEC",x"FF3",x"FF8",x"FFC",x"FFE",x"FFF",x"FFF",
x"FFE",x"FFC",x"FF8",x"FF3",x"FED",x"FE5",x"FDC",x"FD2",
x"FC6",x"FBA",x"FAC",x"F9C",x"F8C",x"F7A",x"F67",x"F53",
x"F3E",x"F28",x"F10",x"EF7",x"EDD",x"EC2",x"EA6",x"E89",
x"E6B",x"E4C",x"E2C",x"E0A",x"DE8",x"DC5",x"DA1",x"D7C",
x"D56",x"D2F",x"D08",x"CDF"

,x"CB6",x"C8C",x"C61",x"C36",
x"C0A",x"BDD",x"BB0",x"B82",x"B53",x"B24",x"AF5",x"AC5",
x"A94",x"A63",x"A32",x"A00",x"9CE",x"99C",x"969",x"937",
x"904",x"8D1",x"89D",x"86A",x"837",x"803",x"7D0",x"79C",
x"769",x"736",x"703",x"6D0",x"69D",x"66A",x"638",x"606",
x"5D4",x"5A3",x"572",x"542",x"511",x"4E2",x"4B3",x"484",
x"456",x"429",x"3FC",x"3D0",x"3A4",x"379",x"34F",x"326",
x"2FE",x"2D6",x"2AF",x"289",x"264",x"240",x"21C",x"1FA",
x"1D9",x"1B8",x"199",x"17B",x"15D",x"141",x"126",x"10C",
x"0F3",x"0DB",x"0C5",x"0AF",x"09B",x"088",x"076",x"066",
x"056",x"048",x"03B",x"030",x"025",x"01C",x"014",x"00E",
x"008",x"004",x"002",x"000",x"000",x"001",x"004",x"007",
x"00D",x"013",x"01A",x"023",x"02D",x"039",x"046",x"053",
x"063",x"073",x"085",x"097",x"0AB",x"0C1",x"0D7",x"0EF",
x"107",x"121",x"13C",x"158",x"175",x"193",x"1B2",x"1D2",
x"1F4",x"216",x"239",x"25D",x"282",x"2A8",x"2CE",x"2F6",
x"31E",x"347",x"371",x"39C",x"3C7",x"3F3",x"420",x"44D",
x"47B",x"4AA",x"4D9",x"508",x"538",x"569",x"59A",x"5CB",
x"5FD",x"62F",x"661",x"693",x"6C6",x"6F9",x"72C",x"75F",
x"793",x"7C6"
);

signal CLKFB : std_logic := '0';

  COMPONENT key_debounce
  PORT(
    clk : IN std_logic;
    reset : IN std_logic;
    taster : IN std_logic;
    taster_out : OUT std_logic
    );
  END COMPONENT;

begin

--clk <= NPG; -- replaced by DCM

--  <-----Cut code below this line and paste into the architecture 
body---->

   -- DCM_SP: Digital Clock Manager Circuit
   --         Spartan-3E
   -- Xilinx HDL Language Template, version 12.1

   DCM_SP_inst : DCM_SP
   generic map (
      CLKDV_DIVIDE => 2.0, --  Divide by: 
1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
                           -- 
7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
      CLKFX_DIVIDE => 1,   --  Can be any interger from 1 to 32
      CLKFX_MULTIPLY => 4, --  Can be any integer from 1 to 32
      CLKIN_DIVIDE_BY_2 => FALSE, --  TRUE/FALSE to enable CLKIN divide 
by two feature
      CLKIN_PERIOD => 100.0, --  Specify period of input clock
      CLKOUT_PHASE_SHIFT => "NONE", --  Specify phase shift of "NONE", 
"FIXED" or "VARIABLE"
      CLK_FEEDBACK => "2X",         --  Specify clock feedback of 
"NONE", "1X" or "2X"
      DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", -- "SOURCE_SYNCHRONOUS", 
"SYSTEM_SYNCHRONOUS" or
                                             --     an integer from 0 to 
15
      DLL_FREQUENCY_MODE => "LOW",     -- "HIGH" or "LOW" frequency mode 
for DLL
      DUTY_CYCLE_CORRECTION => TRUE, --  Duty cycle correction, TRUE or 
FALSE
      PHASE_SHIFT => 0,        --  Amount of fixed phase shift from -255 
to 255
      STARTUP_WAIT => FALSE) --  Delay configuration DONE until DCM_SP 
LOCK, TRUE/FALSE
   port map (
      CLK0 => clk_div2,     -- 0 degree DCM CLK ouptput
      CLK180 => open, -- 180 degree DCM CLK output
      CLK270 => open, -- 270 degree DCM CLK output
      CLK2X => clk,   -- 2X DCM CLK output
      CLK2X180 => open, -- 2X, 180 degree DCM CLK out
      CLK90 => open,   -- 90 degree DCM CLK output
      CLKDV => open,   -- Divided DCM CLK out (CLKDV_DIVIDE)
      CLKFX => open,   -- DCM CLK synthesis out (M/D)
      CLKFX180 => open, -- 180 degree CLK synthesis out
      LOCKED => open, --LED1, -- DCM LOCK status output
      PSDONE => open, -- Dynamic phase adjust done output
      STATUS => open, -- 8-bit DCM status bits output
      CLKFB => clk,   -- DCM clock feedback
      CLKIN => NPG,   -- Clock input (from IBUFG, BUFG or DCM)
      PSCLK => open,   -- Dynamic phase adjust clock input
      PSEN => open,     -- Dynamic phase adjust enable input
      PSINCDEC => open, -- Dynamic phase adjust increment/decrement
      RST => '0'        -- DCM asynchronous reset input
   );
--   -- End of DCM_SP_inst instantiation

proc_clockdivider: process(clk) begin
  if rising_edge(clk) then
    if clk_div2 = '0' then
      if position_sinus1 < 249 then
        position_sinus1 <= position_sinus1 + 1;
      else
        position_sinus1 <= 0;
      end if;

      if triangle < 3000 then
        triangle <= triangle + 1;
      else
        triangle <= (others => '0');
      end if;
      sinus_out <= sinus(position_sinus2);
--      sinus_out <= triangle;--sinus(position_sinus2);
    else
      if ((position_sinus1 + sinus_offset) > 249) then
        position_sinus2 <= position_sinus1 + sinus_offset - 250;
      else
        position_sinus2 <= position_sinus1 + sinus_offset - 1;
      end if;
      sinus_out <= triangle + sinus_offset;--sinus(position_sinus1);
    end if;
  end if;
end process;

DAC_DATA <= sinus_out;

DAC_nAB <= clk_div2; -- channel multiplexer DAC_A and DAC_B
DAC_nWR <= '0'; -- write only
DAC_nCS <= clk; -- to be testet with 10MHz or 10kHz; one sample needs 
falling and (!) rising edge

--LED0 <= '1' when counter < "0111111111" else '0';
LED0 <= '1' when position_sinus1 < 125 else '0';
--LED1 <= clk_div2;--KEY1 and COMP_IN;

  Inst_key_debounce: key_debounce PORT MAP(
    clk => clk,
    reset => '1',
    taster => KEY0,
    taster_out => key0_debounce
  );

offset_proc : process( key0_debounce) begin
  if rising_edge( key0_debounce ) then
    if sinus_offset < 1000 then
      sinus_offset <= sinus_offset + 100;
    else
      sinus_offset <= 0;
    end if;
  end if;
end process;

--LED0 <= key0_debounce;
LED1 <= KEY0;

end Behavioral;

das ist mein code.
> Was heißt hier "links" und "rechts"?
wenn ich eine taste drücke, übernehme ich den nächsten werte von der 
Tabelle

von Purzel H. (hacky)


Lesenswert?

Sinnvollerweise hat die Tabelle 256 Werte. Das macht den Wrap-around 
einfacher.

von otti (Gast)


Lesenswert?

ja du hast auf jeden recht aber da ich von einem 10Mhz eingangsignal 
40khz erzeugen will muss ich mit 250 werte arbeiten.für die phasen 
verschiebung um die mit 1° machen kann muss eigentlich 360 werte nehmen

von otti (Gast)


Lesenswert?

hdd schrieb:
so will ich das machen
> Ansonsten, bei jedem Tastendruck eine bestimmte Schrittweite vor oder
> zurück in der Tabelle springen und dort weitermachen.

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


Lesenswert?

otti schrieb:
> ja du hast auf jeden recht aber da ich von einem 10Mhz eingangsignal
> 40khz erzeugen will muss ich mit 250 werte arbeiten.
Ich kann das mit einer DDFS auch anders:
http://www.lothar-miller.de/s9y/categories/31-DDFS

> für die phasen verschiebung um die mit 1° machen kann
Steht das im Pflichtenheft (bzw. in der Aufgabe)?
> muss eigentlich 360 werte nehmen
Du denkst zu sehr in deinen Koordinatensystemen.
Nur, weil irgendwann mal irgendjemand einen Kreis in 360 Teile zerhackt 
hat, bedeutet das nicht, dass das für Hardware ein sehr geeigneter Wert 
wäre...

Denn irgendwie sind doch deine 250 Stützpunkte extrem inkompatibel zu 
360 Schritten Phasenverschiebung. Will heißen: du wirst mit 10MHz und 
40kHz nie auf 1/360 Periodendauer auflösen können... :-/

von otti (Gast)


Lesenswert?

Lothar Miller schrieb:
> Steht das im Pflichtenheft (bzw. in der Aufgabe)?

Ja das steht in der Aufgabe (250)

in welcher Schrittweise kann man die Aufgabe realisieren? 1.44° oder

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.