在 ISE 中访问 Spartan-6 ODDR 和其他 selectIO 库设计
Accessing Spartan-6 ODDR & other selectIO library designs in ISE
我正在编写一个程序,希望最终能与 SP605 板上的 DVI 编解码器通信。
但是,我在向所需的 DVI 编解码器输出差分时钟时遇到问题,看来我需要使用 ODDR2 才能做到这一点。
虽然提到过,但我不确定如何在代码中实际实例化它;在阅读 SelectIO 资源和 Spartan-6 库指南后,我似乎应该能够在代码中实例化这个方向,如下所示;但是,当我这样做时,我得到了错误(每个 ODDR2 有 1 个);
ERROR:HDLCompiler:432 - "C:\Users\EEEuser\Xilinix_Projects\i2c1\chron.vhd" Line 50: Formal <c1> has no actual or default value.
ERROR:HDLCompiler:432 - "C:\Users\EEEuser\Xilinix_Projects\i2c1\chron.vhd" Line 65: Formal <c1> has no actual or default value.
为什么会这样以及如何实例化 ODDR2(和其他库资源)?我一直在寻找 use
库声明,但没有找到。
作为参考,我的总体目标是将数据输出到 DVI 编解码器,然后它应该能够 运行 DVI 端口并将数据输出到屏幕。目前,数据全部是 '1'
因为一开始我只想得到一个白屏输出。
下面显示了我尝试实例化两个 ODDR2 模块的代码。
非常感谢!
大卫
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.VComponents.all;
entity chron is
Port ( SYSCLK_N : in STD_LOGIC;
SYSCLK_P : in STD_LOGIC;
USRCLK: in STD_LOGIC; --27 MHz user clock
PXLCLK_N : out STD_LOGIC; --differential pixel clock
PXLCLK_P : out STD_LOGIC;
D : out STD_LOGIC_VECTOR (11 downto 0); --data bus
H : out STD_LOGIC; --hysnc
V : out STD_LOGIC; --vsync
DE : out STD_LOGIC); -- data enable
end chron;
architecture Behavioral of chron is
component DCM
port
(-- Clock in ports
SYSCLK_N : in std_logic;
SYSCLK_P : in std_logic;
-- Clock out ports
PXLCLK_P : out std_logic;
PXLCLK_N : out std_logic
);
end component;
signal data_enable : std_logic := '1';--Data enable high when data video input
signal data : std_logic_vector (11 downto 0) := (others => '1'); --data bus
signal hsync, vsync : std_logic; --active low
signal hsync_counter : integer range 0 to 512; --counter 0 to 450 for hsync using 27 MHz input clock
signal vsync_counter : integer range 0 to 524288; --counter 0 to 359856 for vsync using 27 MHz
signal pxlclk_p_int, pxlclk_n_int: std_logic;
begin
DCM_clock : DCM
port map
(-- Clock in ports
SYSCLK_N => SYSCLK_N,
SYSCLK_P => SYSCLK_P,
-- Clock out ports
PXLCLK_P => pxlclk_p_int,
PXLCLK_N => pxlclk_n_int);
ODDR_pxlclk_p : ODDR2
generic map(
DDR_ALIGNMENT => "NONE",
INIT => '0',
SRTYPE => "SYNC")
port map (
Q => PXLCLK_P,
C0 => pxlclk_p_int,
CE => not(pxlclk_p_int),
D0 => '1',
D1 => '0',
R => '0',
S =>'0'
);
ODDR_pxlclk_n : ODDR2
generic map(
DDR_ALIGNMENT => "NONE",
INIT => '0',
SRTYPE => "SYNC")
port map (
Q => PXLCLK_N,
C0 => pxlclk_n_int,
CE => not(pxlclk_n_int),
D0 => '1',
D1 => '0',
R => '0',
S =>'0'
);
hsync_proc : process(usrclk)
begin
if rising_edge(usrclk) then --only on rising edge
if hsync_counter > 450 then
hsync_counter <= 0; --reset counter to 0
else
if hsync_counter < 33 then --else take low for 33 time periods
hsync <= '0';
else --and then set high
hsync <= '1';
end if;
hsync_counter <= hsync_counter + 1; --increment counter
end if;
end if;
end process;
vsync_proc : process(usrclk)
begin
if rising_edge(usrclk) then --only on rising edge
if vsync_counter > 359856 then
vsync_counter <= 0; --reset counter to 0
else
if vsync_counter < 1350 then --else take low for 1350 time periods
vsync <= '0';
else --and then set high
vsync <= '1';
end if;
vsync_counter <= vsync_counter + 1; --increment counter
end if;
end if;
end process;
D <= (others => '1');
H <= hsync;
V <= vsync;
DE <= '1';
end Behavioral;
ODDR2
组件有另一个必须分配的输入端口 C1
。
C0
处的上升沿分配 Q <= D0
,C1
处的上升沿分配 Q <= D1
。
因此,要镜像时钟,您必须将端口 C0
处的时钟信号的 180° 相移版本分配给端口 C1
。但是您已将其分配给端口 CE
,这是时钟启用。
以下应该适用于第一个实例:
ODDR_pxlclk_p : ODDR2
generic map(
DDR_ALIGNMENT => "NONE",
INIT => '0',
SRTYPE => "SYNC")
port map (
Q => PXLCLK_P,
C0 => pxlclk_p_int,
C1 => not(pxlclk_p_int),
CE => '1',
D0 => '1',
D1 => '0',
R => '0',
S =>'0'
);
进一步改进
只有在DCM锁定的情况下才应该输出时钟。您可以在 DCM 向导中启用输出 LOCKED
。将此输出连接到 CE
输入。因此,DVI 发送器只能看到稳定的时钟。
为了驱动输入 C1
Xilinx 建议使用来自 DCM 的 180° 相移时钟。您已经有了这个,名为 pxlclk_n_int
.
因此,示例可以改进为:
ODDR_pxlclk_p : ODDR2
generic map(
DDR_ALIGNMENT => "NONE",
INIT => '0',
SRTYPE => "SYNC")
port map (
Q => PXLCLK_P,
C0 => pxlclk_p_int,
C1 => pxlclk_n_int, -- second clock signal from DCM
CE => locked, -- locked signal from DCM
D0 => '1',
D1 => '0',
R => '0',
S =>'0'
);
ODDR_pxlclk_n : ODDR2
generic map(
DDR_ALIGNMENT => "NONE",
INIT => '0',
SRTYPE => "SYNC")
port map (
Q => PXLCLK_N,
C0 => pxlclk_p_int, -- same clock signals as above
C1 => pxlclk_n_int, -- ...
CE => locked, --
D0 => '0', -- but inverted data
D1 => '1', -- ...
R => '0',
S =>'0'
);
我正在编写一个程序,希望最终能与 SP605 板上的 DVI 编解码器通信。
但是,我在向所需的 DVI 编解码器输出差分时钟时遇到问题,看来我需要使用 ODDR2 才能做到这一点。
虽然提到过,但我不确定如何在代码中实际实例化它;在阅读 SelectIO 资源和 Spartan-6 库指南后,我似乎应该能够在代码中实例化这个方向,如下所示;但是,当我这样做时,我得到了错误(每个 ODDR2 有 1 个);
ERROR:HDLCompiler:432 - "C:\Users\EEEuser\Xilinix_Projects\i2c1\chron.vhd" Line 50: Formal <c1> has no actual or default value.
ERROR:HDLCompiler:432 - "C:\Users\EEEuser\Xilinix_Projects\i2c1\chron.vhd" Line 65: Formal <c1> has no actual or default value.
为什么会这样以及如何实例化 ODDR2(和其他库资源)?我一直在寻找 use
库声明,但没有找到。
作为参考,我的总体目标是将数据输出到 DVI 编解码器,然后它应该能够 运行 DVI 端口并将数据输出到屏幕。目前,数据全部是 '1'
因为一开始我只想得到一个白屏输出。
下面显示了我尝试实例化两个 ODDR2 模块的代码。
非常感谢!
大卫
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.VComponents.all;
entity chron is
Port ( SYSCLK_N : in STD_LOGIC;
SYSCLK_P : in STD_LOGIC;
USRCLK: in STD_LOGIC; --27 MHz user clock
PXLCLK_N : out STD_LOGIC; --differential pixel clock
PXLCLK_P : out STD_LOGIC;
D : out STD_LOGIC_VECTOR (11 downto 0); --data bus
H : out STD_LOGIC; --hysnc
V : out STD_LOGIC; --vsync
DE : out STD_LOGIC); -- data enable
end chron;
architecture Behavioral of chron is
component DCM
port
(-- Clock in ports
SYSCLK_N : in std_logic;
SYSCLK_P : in std_logic;
-- Clock out ports
PXLCLK_P : out std_logic;
PXLCLK_N : out std_logic
);
end component;
signal data_enable : std_logic := '1';--Data enable high when data video input
signal data : std_logic_vector (11 downto 0) := (others => '1'); --data bus
signal hsync, vsync : std_logic; --active low
signal hsync_counter : integer range 0 to 512; --counter 0 to 450 for hsync using 27 MHz input clock
signal vsync_counter : integer range 0 to 524288; --counter 0 to 359856 for vsync using 27 MHz
signal pxlclk_p_int, pxlclk_n_int: std_logic;
begin
DCM_clock : DCM
port map
(-- Clock in ports
SYSCLK_N => SYSCLK_N,
SYSCLK_P => SYSCLK_P,
-- Clock out ports
PXLCLK_P => pxlclk_p_int,
PXLCLK_N => pxlclk_n_int);
ODDR_pxlclk_p : ODDR2
generic map(
DDR_ALIGNMENT => "NONE",
INIT => '0',
SRTYPE => "SYNC")
port map (
Q => PXLCLK_P,
C0 => pxlclk_p_int,
CE => not(pxlclk_p_int),
D0 => '1',
D1 => '0',
R => '0',
S =>'0'
);
ODDR_pxlclk_n : ODDR2
generic map(
DDR_ALIGNMENT => "NONE",
INIT => '0',
SRTYPE => "SYNC")
port map (
Q => PXLCLK_N,
C0 => pxlclk_n_int,
CE => not(pxlclk_n_int),
D0 => '1',
D1 => '0',
R => '0',
S =>'0'
);
hsync_proc : process(usrclk)
begin
if rising_edge(usrclk) then --only on rising edge
if hsync_counter > 450 then
hsync_counter <= 0; --reset counter to 0
else
if hsync_counter < 33 then --else take low for 33 time periods
hsync <= '0';
else --and then set high
hsync <= '1';
end if;
hsync_counter <= hsync_counter + 1; --increment counter
end if;
end if;
end process;
vsync_proc : process(usrclk)
begin
if rising_edge(usrclk) then --only on rising edge
if vsync_counter > 359856 then
vsync_counter <= 0; --reset counter to 0
else
if vsync_counter < 1350 then --else take low for 1350 time periods
vsync <= '0';
else --and then set high
vsync <= '1';
end if;
vsync_counter <= vsync_counter + 1; --increment counter
end if;
end if;
end process;
D <= (others => '1');
H <= hsync;
V <= vsync;
DE <= '1';
end Behavioral;
ODDR2
组件有另一个必须分配的输入端口 C1
。
C0
处的上升沿分配 Q <= D0
,C1
处的上升沿分配 Q <= D1
。
因此,要镜像时钟,您必须将端口 C0
处的时钟信号的 180° 相移版本分配给端口 C1
。但是您已将其分配给端口 CE
,这是时钟启用。
以下应该适用于第一个实例:
ODDR_pxlclk_p : ODDR2
generic map(
DDR_ALIGNMENT => "NONE",
INIT => '0',
SRTYPE => "SYNC")
port map (
Q => PXLCLK_P,
C0 => pxlclk_p_int,
C1 => not(pxlclk_p_int),
CE => '1',
D0 => '1',
D1 => '0',
R => '0',
S =>'0'
);
进一步改进
只有在DCM锁定的情况下才应该输出时钟。您可以在 DCM 向导中启用输出 LOCKED
。将此输出连接到 CE
输入。因此,DVI 发送器只能看到稳定的时钟。
为了驱动输入 C1
Xilinx 建议使用来自 DCM 的 180° 相移时钟。您已经有了这个,名为 pxlclk_n_int
.
因此,示例可以改进为:
ODDR_pxlclk_p : ODDR2
generic map(
DDR_ALIGNMENT => "NONE",
INIT => '0',
SRTYPE => "SYNC")
port map (
Q => PXLCLK_P,
C0 => pxlclk_p_int,
C1 => pxlclk_n_int, -- second clock signal from DCM
CE => locked, -- locked signal from DCM
D0 => '1',
D1 => '0',
R => '0',
S =>'0'
);
ODDR_pxlclk_n : ODDR2
generic map(
DDR_ALIGNMENT => "NONE",
INIT => '0',
SRTYPE => "SYNC")
port map (
Q => PXLCLK_N,
C0 => pxlclk_p_int, -- same clock signals as above
C1 => pxlclk_n_int, -- ...
CE => locked, --
D0 => '0', -- but inverted data
D1 => '1', -- ...
R => '0',
S =>'0'
);