Hallo zusammen!
Entschuldigt, bin Anfaenger und suche nach einer wahrscheinlich
trivialen Loesung (die Google so nicht hergibt): Ich habe einen DDS-Core
von Xilinx mit einem DAC auf meinem Board verknuepft, das Problem ist
jetzt, dass der DDS-Core Zweierkomplement ausgibt, der DAC aber einen
'unsigned vector' (heisst das so?) haben will, der Sinus der rauskommt
ist daher an den Nullstellen invertiert (springt). Der DAC ist ein alter
DAC902e von TI, 12bit breit aber 14bit sind zum DAC board geroutet (P160
Analog Module von MEMEC). Hier mein bescheidener VHDL-Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
entity TOP_LEVEL is
port (
CLKIN : in STD_LOGIC;
RESETn : in STD_LOGIC;
DAC2DB : out STD_LOGIC_VECTOR(1 to 14); -- This is
the output vector to a DAC902e (12bit + 2 routed on PCB)
DAC2REGCLK : out STD_LOGIC;
DAC2CLK : out STD_LOGIC;
DAC2PD : out STD_LOGIC;
DAC2REFSEL : out STD_LOGIC
);
end TOP_LEVEL;
architecture Behavioral of TOP_LEVEL is
---------------------------------------------------------------------
component BUFG
port (
I : in std_logic;
O : out std_logic
);
end component;
---------------------------------------------------------------------
component DCM2
port (
CLKIN_IN : IN std_logic;
RST_IN : IN std_logic;
CLKDV_OUT : OUT std_logic;
CLKIN_IBUFG_OUT : OUT std_logic;
CLK0_OUT : OUT std_logic
);
end component;
---------------------------------------------------------------------
component DDS
port (
clk: in std_logic;
sine: out std_logic_vector(13 downto 0)); -- DDS output from
Xilinx DDS IP in 2's complement
end component;
---------------------------------------------------------------------
signal CLK0_W: std_logic;
signal CLK0: std_logic;
signal CLKDV_W: std_logic;
signal CLKDV: std_logic;
signal RESET: std_logic;
signal SINE: std_logic_vector(13 downto 0);
---------------------------------------------------------------------
begin
RESET <= NOT RESETn;
U_DDS: dds port map (
clk => CLKDV,
sine => SINE
);
U_DCM: DCM2 port map(
CLKIN_IN => CLKIN,
RST_IN => RESET,
CLKDV_OUT => CLKDV_W,
CLKIN_IBUFG_OUT => open,
CLK0_OUT => CLK0_W
);
U_BUFG1: BUFG port map (
I => CLKDV_W,
O => CLKDV
);
U_BUFG2: BUFG port map (
I => CLK0_W,
O => CLK0
);
---------------------------------------------------------------------
process (CLKDV, RESETn)
begin
if (RESETn = '0') then
DAC2DB <= (others => '0');
elsif (CLKDV'event and CLKDV = '1') then
DAC2DB <= sine XOR "11111111111110" ; --convert DDS 2's
complement to binary and output to DAC
end if;
end process;
---------------------------------------------------------------------
DAC2REGCLK <= CLKDV; -- Toggle DAC register CLK
DAC2CLK <= CLKDV; -- Toggle DAC conversion CLK
DAC2PD <= '0';
DAC2REFSEL <= '0';
---------------------------------------------------------------------
end Behavioral;
Kann mir jemand sagen wie ich am sinnvollsten die Zahlendarstellungen
ineinander umrechne oder vielleicht andere Tricks? Vielen Dank!
Jan
Du musst dann mit einem Offset in Höhe der Hälfte des DDS
Ausgangsbereiches das Signal erst mal in den postitiven Bereich
verschieben. Wenn dein DDS 14 Bit Signed ausgibt, musst du auf das
Signal 8192 drauf addieren. Dann erhältst du einen 15 Bit Vektor, weil
das Signal ja bei positivem Eingang größer wird. Das kannst du dann per
resize wieder auf deinen DAC Bereich bringen.
Also etwa so:
Hallo Christian!
Vielen Dank fuer den Ansatz, im Prinzip ja ganz einfach, allerdings tue
ich mich im Moment noch sehr schwer mit den signed und unsigned
Variablen, habe noch etwas rumprobiert und folgendes rausbekommen, was
aber auch nicht recht funktioniert:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.STD_LOGIC_ARITH.ALL;
4
useIEEE.STD_LOGIC_SIGNED.ALL;
5
useIEEE.STD_LOGIC_UNSIGNED.ALL;
6
useIEEE.NUMERIC_STD.ALL;
7
8
entityTOP_LEVELis
9
port(
10
CLKIN:inSTD_LOGIC;
11
RESETn:inSTD_LOGIC;
12
DAC2DB:outSTD_LOGIC_VECTOR(0to13);-- This is the output vector to a DAC902e (12bit + 2 routed on PCB)
Bekomme diese Fehlermeldungen:
Line 62. to_signed can not have such operands in this context.
Line 87. resize can not have such operands in this context.
Ist bestimmt einfach, aber bis jetzt habe ich die ganzen Datentypen und
Umwandlungen in VHDL noch nicht so recht verstanden...
Vielen Dank!
Jan
janko schrieb:> library IEEE;> use IEEE.STD_LOGIC_1164.ALL;> use IEEE.STD_LOGIC_ARITH.ALL;> use IEEE.STD_LOGIC_SIGNED.ALL;> use IEEE.STD_LOGIC_UNSIGNED.ALL;> use IEEE.NUMERIC_STD.ALL;
ouch, viel hilft viel?
Nimm mal nur folgendes:
'unsigned' scheint er bei mir gar nicht zu kennen, auch nachdem ich bei
den libraries aufgeraeumt habe... auf jeden Fall wird das nicht farbig
angezeigt wie alle anderen Deklarationen.
Die Zeile
1
SinePos<=unsigned(to_signed(SINE,14)+to_signed(8192,14));--Now line 59
liefert jetzt folgenden Fehler:
Line 59. to_signed can not have such operands in this context.
Bin immer noch ziemlich ratlos :-(
janko schrieb:> process (CLKDV, RESETn)> begin> if (RESETn = '0') then> DAC2DB <= (others => '0');> elsif (CLKDV'event and CLKDV = '1') then> DAC2DB <= std_logic_vector(resize(SinePos, 14));> end if;> end process;
schoen, dass es tut. Nur so am Rande:
* Du koenntest auch
1
elsifrising_edge(CLKDV)then
schreiben
* Die Zuweisung muesste auch mit
1
DAC2DB<=std_logic_vector(SinePos);
funktionieren (SinePos ist ja schon 14bit breit)
* Wozu brauchst du den Reset? (hoffentlich isser einsynchronisiert!).
Statt Reset koenntest du in der Entity ganz oben auch folgendes machen:
Hm, stimmt die Erweiterung auf 15 Bit braucht man ja nicht. Ich war
jetzt irgendwie bei Gleichrichtung. Bei Signed auf Unsigned kann ja
nicht mehr als 16383 rauskommen in dem Fall.
janko schrieb:> process (CLKDV, RESETn)> begin> if (RESETn = '0') then> :> elsif (CLKDV'event and CLKDV = '1') then> :> end if;> end process;
Wenn du mit Xilinx arbeitest, dann solltest du dir unbedingt das
Whitepaper WP272 durchlesen...
Siehe auch den Beitrag "Xilinx und die Resets" und die Links
darin.