Forum: FPGA, VHDL & Co. Zweierkomplement zu unsigned vector Problem


von janko (Gast)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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:
1
Signal SinePostitive : unsigned(14 downto 0);
2
3
...
4
SinePositive <= unsigned(resize(Sine, 15) + to_signed(8192, 15));
5
6
DAC2DB <= std_logic_vector(resize(SinePositive, 14));

Und nutz bitte die numeric_std lib.

von janko (Gast)


Lesenswert?

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
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_SIGNED.ALL;
5
use IEEE.STD_LOGIC_UNSIGNED.ALL;
6
use IEEE.NUMERIC_STD.ALL;
7
     
8
entity TOP_LEVEL is
9
   port (
10
        CLKIN                : in   STD_LOGIC;
11
        RESETn               : in   STD_LOGIC;
12
      DAC2DB            : out  STD_LOGIC_VECTOR(0 to 13);  -- This is the output vector to a DAC902e (12bit + 2 routed on PCB)
13
      DAC2REGCLK        : out  STD_LOGIC;
14
      DAC2CLK          : out  STD_LOGIC;
15
      DAC2PD            : out  STD_LOGIC;
16
      DAC2REFSEL        : out  STD_LOGIC
17
        );
18
end TOP_LEVEL;
19
20
architecture Behavioral of TOP_LEVEL is
21
---------------------------------------------------------------------
22
component BUFG 
23
  port (
24
        I   : in std_logic;
25
        O   : out std_logic
26
       ); 
27
end component;
28
---------------------------------------------------------------------
29
component DCM2
30
  port (
31
    CLKIN_IN : IN std_logic;
32
    RST_IN : IN std_logic;          
33
    CLKDV_OUT : OUT std_logic;
34
    CLKIN_IBUFG_OUT : OUT std_logic;
35
    CLK0_OUT : OUT std_logic
36
    );
37
end component;
38
---------------------------------------------------------------------
39
component DDS
40
  port (
41
    clk: in std_logic;
42
    sine: out std_logic_vector(13 downto 0));      -- DDS output from Xilinx DDS IP in 2's complement
43
end component;
44
---------------------------------------------------------------------
45
signal CLK0_W: std_logic;
46
signal CLK0: std_logic;
47
signal CLKDV_W: std_logic;
48
signal CLKDV: std_logic;
49
signal RESET: std_logic;
50
signal SINE: std_logic_vector(13 downto 0);
51
signal SinePos: unsigned(13 downto 0);
52
---------------------------------------------------------------------
53
begin
54
55
RESET <= NOT RESETn;
56
57
U_DDS: dds port map (
58
  clk => CLKDV,
59
  sine => SINE
60
);
61
62
SinePos <= to_unsigned(to_signed(SINE, 14) + to_signed(8192, 14)); --Line 62
63
            
64
U_DCM: DCM2 port map(
65
  CLKIN_IN => CLKIN,
66
  RST_IN => RESET,
67
  CLKDV_OUT => CLKDV_W,
68
  CLKIN_IBUFG_OUT => open,
69
  CLK0_OUT => CLK0_W
70
);
71
  
72
U_BUFG1: BUFG port map (
73
  I => CLKDV_W,
74
   O => CLKDV
75
);
76
77
U_BUFG2: BUFG port map (
78
   I => CLK0_W,
79
   O => CLK0
80
);
81
---------------------------------------------------------------------
82
process (CLKDV, RESETn) 
83
begin
84
   if   (RESETn = '0') then
85
         DAC2DB   <= (others => '0');
86
  elsif (CLKDV'event and CLKDV = '1') then
87
      DAC2DB <= std_logic_vector(resize(SinePos, 14)); --Line 87
88
   end if;
89
end process;
90
---------------------------------------------------------------------
91
DAC2REGCLK   <= CLKDV;                     -- Toggle DAC register CLK
92
DAC2CLK   <= CLKDV;                      -- Toggle DAc conversion CLK
93
DAC2PD  <= '0';          
94
DAC2REFSEL  <= '0';      
95
---------------------------------------------------------------------
96
end Behavioral;

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

von janko (Gast)


Lesenswert?

Ah, sehe gerade in meinem ISE ist das unsigned bei
1
signal SinePos: unsigned(13 downto 0);
nicht farbig wie zB alle anderen std_logic_vector etc., hat das was zu 
bedeuten?

von berndl (Gast)


Lesenswert?

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:
1
> library IEEE;
2
> use IEEE.STD_LOGIC_1164.ALL;
3
> use IEEE.NUMERIC_STD.ALL;
und in Zeile 62 versuch mal:
1
SinePos <= unsigned(to_signed(SINE, 14) + to_signed(8192, 14)); --Line 62
Zeile 87 duerfte Probleme haben mit (... to ...) vs. (... downto ...)

von berndl (Gast)


Lesenswert?

berndl schrieb:
> SinePos <= unsigned(to_signed(SINE, 14) + to_signed(8192, 14)); --Line 62

bzw. so:
1
SinePos <= unsigned(signed(SINE, 14) + to_signed(8192, 14));
(Konvertierungen mit numeric_std sind bei Lother und bei Doulos zu 
finden)

von janko (Gast)


Lesenswert?

'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 :-(

von berndl (Gast)


Lesenswert?

der kennt das schon, der Editor ist halt etwas beschraenkt...

Wg. der Konvertierung:
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std

von janko (Gast)


Lesenswert?

Vielen Dank an alle! Funktioniert jetzt, siehe neuen code:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
     
5
entity TOP_LEVEL is
6
   port (
7
        CLKIN                : in   STD_LOGIC;
8
        RESETn               : in   STD_LOGIC;
9
      DAC2DB            : out  STD_LOGIC_VECTOR(0 to 13);  -- This is the output vector to a DAC902e (12bit + 2 routed on PCB)
10
      DAC2REGCLK        : out  STD_LOGIC;
11
      DAC2CLK          : out  STD_LOGIC;
12
      DAC2PD            : out  STD_LOGIC;
13
      DAC2REFSEL        : out  STD_LOGIC
14
        );
15
end TOP_LEVEL;
16
17
architecture Behavioral of TOP_LEVEL is
18
---------------------------------------------------------------------
19
component BUFG 
20
  port (
21
        I   : in std_logic;
22
        O   : out std_logic
23
       ); 
24
end component;
25
---------------------------------------------------------------------
26
component DCM2
27
  port (
28
    CLKIN_IN : IN std_logic;
29
    RST_IN : IN std_logic;          
30
    CLKDV_OUT : OUT std_logic;
31
    CLKIN_IBUFG_OUT : OUT std_logic;
32
    CLK0_OUT : OUT std_logic
33
    );
34
end component;
35
---------------------------------------------------------------------
36
component DDS
37
  port (
38
    clk: in std_logic;
39
    sine: out std_logic_vector(13 downto 0));      -- DDS output from Xilinx DDS IP in 2's complement
40
end component;
41
---------------------------------------------------------------------
42
signal CLK0_W: std_logic;
43
signal CLK0: std_logic;
44
signal CLKDV_W: std_logic;
45
signal CLKDV: std_logic;
46
signal RESET: std_logic;
47
signal SINE: std_logic_vector(13 downto 0);
48
signal SinePos: unsigned(13 downto 0);
49
---------------------------------------------------------------------
50
begin
51
52
RESET <= NOT RESETn;
53
54
U_DDS: dds port map (
55
  clk => CLKDV,
56
  sine => SINE
57
);
58
59
--SinePos <= unsigned(signed(SINE, 14) + to_signed(8192, 14));
60
SinePos <= unsigned(signed(SINE) + 8192);            
61
62
U_DCM: DCM2 port map(
63
  CLKIN_IN => CLKIN,
64
  RST_IN => RESET,
65
  CLKDV_OUT => CLKDV_W,
66
  CLKIN_IBUFG_OUT => open,
67
  CLK0_OUT => CLK0_W
68
);
69
  
70
U_BUFG1: BUFG port map (
71
  I => CLKDV_W,
72
   O => CLKDV
73
);
74
75
U_BUFG2: BUFG port map (
76
   I => CLK0_W,
77
   O => CLK0
78
);
79
---------------------------------------------------------------------
80
process (CLKDV, RESETn) 
81
begin
82
   if   (RESETn = '0') then
83
         DAC2DB   <= (others => '0');
84
  elsif (CLKDV'event and CLKDV = '1') then
85
      DAC2DB <= std_logic_vector(resize(SinePos, 14));
86
   end if;
87
end process;
88
---------------------------------------------------------------------
89
DAC2REGCLK   <= CLKDV;                     -- Toggle DAC register CLK
90
DAC2CLK   <= CLKDV;                      -- Toggle DAc conversion CLK
91
DAC2PD  <= '0';          
92
DAC2REFSEL  <= '0';      
93
---------------------------------------------------------------------
94
end Behavioral;

Geht bestimmt auch schoener, aber so kommt am DAC ein schoener Sinus 
raus und der Sonntag ist gerettet!

Schoenes Restwochenende noch!

Jan

von berndl (Gast)


Lesenswert?

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
elsif rising_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:
1
DAC2DB : out STD_LOGIC_VECTOR(0 to 13) := (others => '0');
 (initialisiert mit Nullen)

von Christian R. (supachris)


Lesenswert?

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.

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


Lesenswert?

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.

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.