当前位置:  开发笔记 > 编程语言 > 正文

使用BUFG来驱动时钟负载

如何解决《使用BUFG来驱动时钟负载》经验,为你挑选了1个好方法。

我正在尝试处理输出到DVI芯片的像素数据.使用各种时钟频率是因为DVI芯片寄存器是使用I2C编程的(因此需要时钟<500 KHz) - 来自时钟分频器.

DVI芯片需要一个40 MHz的差分像素时钟,然而,DVI每半个显示半个字节,因此每半个周期需要另外80 MHz的时钟将每一半像素推到数据线上,这些都是来自DCM.

这导致了各种各样的问题.我试图只使用双像素时钟速率交换像素的每一半,但是我得到了错误:

This design contains a global buffer instance, , driving the net, , that is driving the following (first 30) non-clock load pins.

所以我在DCM的输出和使用信号的组件之间添加了一个BUFG元素 - 但它没有改变任何东西,而是现在在BUFG的输入和输出上抛出两次错误.

我怎么能解决这个问题 - 因为我刚刚添加了一个BUFG并且它不喜欢它!

我的代码如下; 我试图删除与时钟无关的不相关的东西,但它仍然很长!

编辑1:我添加了块,当添加到系统时,导致错误(之前没有)它在第二个代码块中!我目前正在研究差分信号的其他建议,并在完成后再次编辑!

非常感谢,

大卫

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
library UNISIM;
use UNISIM.VComponents.all;

ENTITY I2CBus IS
    PORT(
        SYSCLK_N   : IN    STD_LOGIC;   --system 200MHz differential clock
        SYSCLK_P   : IN    STD_LOGIC;
        BTN        : IN    STD_LOGIC;   -- to manually change reset

        LED        : OUT   STD_LOGIC_VECTOR(3 downto 0); --to observe reset value
        SCL_DBG    : OUT   STD_LOGIC;   -- copy of SCL to output pin
        SDA_DBG    : OUT   STD_LOGIC;   --copy of SDA to output pin
        SCL        : OUT   STD_LOGIC;   --Serial Clock Line
        SDA        : INOUT STD_LOGIC;   --Serial Data Line

        DVIRESET_N : OUT   STD_LOGIC;   --reset_n to dvi device
        DVI_ENABLE : OUT   STD_LOGIC;   --enable DVI device inputs (active high)
        PXLCLK_P   : OUT   STD_LOGIC;   --pixel clock differential pair through buffers
        PXLCLK_N   : OUT   STD_LOGIC;
        DVI_DATA   : OUT   STD_LOGIC_VECTOR(11 downto 0); --12 bit multiplexed pixel to DVI
        HSYNC      : OUT   STD_LOGIC;   --Horizontal/Vertical sync timing pulses
        VSYNC      : OUT   STD_LOGIC
    );
END I2CBus;
ARCHITECTURE behavior OF I2CBus IS
    COMPONENT IIC_MASTER                --sends data to write out onto SDA bus line in I2C protocol
        PORT(SCL     : IN    STD_LOGIC;
             SCL2X   : IN    STD_LOGIC;
             RESET_N : IN    STD_LOGIC;
             ENA     : IN    STD_LOGIC;
             ADR     : IN    STD_LOGIC_VECTOR(6 DOWNTO 0);
             REG     : IN    STD_LOGIC_VECTOR(7 DOWNTO 0);
             RW      : IN    STD_LOGIC;
             DAT_WR  : IN    STD_LOGIC_VECTOR(7 DOWNTO 0);
             BUSY    : OUT   STD_LOGIC;
             SDA     : INOUT STD_LOGIC;
             ACK_ERR : BUFFER STD_LOGIC);
    END COMPONENT IIC_MASTER;
    COMPONENT DCM                       --takes input system differential clocks, generates further clocks
        PORT(
            SYSCLK_P : IN  STD_LOGIC;   -- CLOCK IN PORTS 200MHZ DIFFERENTIAL
            SYSCLK_N : IN  STD_LOGIC;
            -- CLOCK OUT PORTS
            SYSCLK   : OUT STD_LOGIC;
            PXLCLK   : OUT STD_LOGIC;
            PXLCLK2X : OUT STD_LOGIC
        );
    END COMPONENT;

    COMPONENT CLK_DIVIDER               --divides system clock down for i2c bus clock line
        GENERIC(INPUT_FREQ : INTEGER;
                OUT1_FREQ  : INTEGER;
                OUT2_FREQ  : INTEGER);
        PORT(SYSCLK      : IN  STD_LOGIC;
             RESET_N     : IN  STD_LOGIC;
             RESET_N_OUT : OUT STD_LOGIC;
             OUT1        : OUT STD_LOGIC;
             OUT2        : OUT STD_LOGIC);
    END COMPONENT CLK_DIVIDER;

    COMPONENT DVI_INITIALISE            --initialises CH7301c registers to necessary operation values
        PORT(SYSCLK      : IN  STD_LOGIC;
             ACK_ERR     : IN  STD_LOGIC;
             BUSY        : IN  STD_LOGIC;
             RESET_N     : IN  STD_LOGIC;
             COUNT       : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
             DVI_WR      : OUT STD_LOGIC := '0';
             DVI_REGDATA : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
             DVI_WDATA   : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
    END COMPONENT DVI_INITIALISE;

    COMPONENT DVI_INTERFACE             --outputs sync pulses, controls enable and manages pixel addresses
        PORT(PIXEL_CLK    : IN  STD_LOGIC;
             RESET_N      : IN  STD_LOGIC;
             PXL_ADDR     : OUT STD_LOGIC_VECTOR(19 DOWNTO 0) := (OTHERS => '0');
             HSYNC, VSYNC : OUT STD_LOGIC                     := '1';
             ENABLE       : OUT STD_LOGIC                     := '0');
    END COMPONENT DVI_INTERFACE;

    COMPONENT DVI_MUX
        PORT(PXLCLK   : IN  STD_LOGIC;
             PXLCLK2X : IN  STD_LOGIC;
             PXL_DAT  : IN  STD_LOGIC_VECTOR(23 DOWNTO 0); --pixel as RGB
             DATA     : OUT STD_LOGIC_VECTOR(11 DOWNTO 0); --multiplexed output
             RESET_N  : IN  STD_LOGIC); --reset low signal
    END COMPONENT DVI_MUX;

    --Inputs
    signal reset_n_input : std_logic;   -- input reset from button

    ----Outputs ------
    signal sda_internal : STD_LOGIC;    -- Internal SDA

    ----Clocks-----
    signal SCL_internal   : std_logic;  -- i2c clock
    signal SCL2X_internal : std_logic;  -- i2c x2 to load SDA data
    signal sysclk         : std_logic;  --system clock
    signal pxlclk_p_int   : std_logic;  --differential pixel clock pair
    signal pxlclk_n_int   : std_logic;
    signal pxlclk         : std_logic;  --pxlclk after BUFG
    signal pxlclk2x_int   : STD_LOGIC;  --2x pixel clock for loading pixel data

    -----Internal Control Signals ---
    signal reset_n : std_logic;         --active high
    signal busy    : std_logic;         --low when not i2c not busy
    signal ack_err : std_logic;         --high when i2c ackknowledge error occurs

    ----Internal Data-----
    signal i2c_reg  : STD_LOGIC_VECTOR(7 DOWNTO 0); --register data for I2C
    signal i2c_rw   : STD_LOGIC;        --R/W* for I2C
    signal i2c_data : STD_LOGIC_VECTOR(7 DOWNTO 0); --Data for I2C

BEGIN
    master : IIC_Master
        port map(
            SCL     => SCL_internal,
            SCL2X   => SCL2X_internal,
            RESET_N => RESET_N,
            ENA     => '1',
            ADR     => "1110110",
            REG     => i2c_reg,
            RW      => i2c_rw,
            DAT_WR  => i2c_data,
            BUSY    => busy,
            SDA     => sda_internal,
            ACK_ERR => ack_err
        );
    DCM_SYS : DCM
        port map(
            SYSCLK_P => SYSCLK_P,       --take differential input clock
            SYSCLK_N => SYSCLK_N,
            SYSCLK   => sysclk,         --200 MHz system clock 
            PXLCLK   => pxlclk,         --and pixel clock
            PXLCLK2X => pxlclk2x_int    --pixel clock at double rate
        );

    Clk_Div : Clk_Divider
        generic map(
            INPUT_FREQ => 200000000,    --200 MHz system input
            OUT1_FREQ  => 100000,       --to work correctly, 200 must go into all frequencies (x2).
            OUT2_FREQ  => 200000        --i.e. from 200, cannot generate 40 as 200/40/2 = 2.5, which will be 2
        )
        port map(
            SYSCLK      => sysclk,
            RESET_N     => reset_n_input,
            RESET_N_OUT => reset_n,
            OUT1        => scl_internal,
            OUT2        => scl2x_internal
        );

    data_load : component DVI_INITIALISE
        port map(
            SYSCLK      => sysclk,
            ACK_ERR     => ack_err,
            BUSY        => busy,
            RESET_N     => reset_n,
            COUNT       => LED,
            DVI_WR      => i2c_rw,
            DVI_REGDATA => i2c_reg,
            DVI_WDATA   => i2c_data
        );

    interface : DVI_INTERFACE
        port map(
            PIXEL_CLK => pxlclk_p_int,
            RESET_N   => reset_n,
            PXL_ADDR  => open,
            HSYNC     => HSYNC,
            VSYNC     => VSYNC,
            ENABLE    => DVI_ENABLE
        );

    pxl_mux : DVI_MUX
        port map(
            PXLCLK   => pxlclk_p_int,
            PXLCLK2X => pxlclk2x_int,
            PXL_DAT  => x"FF0000",
            DATA     => DVI_DATA,
            RESET_N  => reset_n
        );
    ------------OUTPUT BUFFERS (CLOCK FORWARDING)------------
    ODDR_pxlclk_p : ODDR2
        generic map(
            DDR_ALIGNMENT => "NONE",
            INIT          => '0',
            SRTYPE        => "SYNC")
        port map(
            Q  => PXLCLK_P,             --output to positive output
            C0 => pxlclk_p_int,         --differential input
            C1 => pxlclk_n_int,
            CE => '1',                  --chip enable tied high
            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,             --output to negative output
            C0 => pxlclk_n_int,
            C1 => pxlclk_p_int,
            CE => '1',
            D0 => '1',
            D1 => '0',
            R  => '0',
            S  => '0'
        );

    out2_bufg : BUFG port map(I => pxlclk, O => pxlclk_p_int); --ERROR THROWN ON I/O HERE 
    ----------------Mappings---------------------------
    reset_n_input <= not BTN;           --when button pressed, reset
    SCL           <= 'Z' when scl_internal = '1' else scl_internal;
    SCL_DBG       <= 'Z' when scl_internal = '1' else scl_internal;
    SDA           <= sda_internal;
    SDA_DBG       <= SDA;               --copy SDA to debug line

    DVIRESET_N   <= reset_n;            --reset DVI device 
    pxlclk_n_int <= not pxlclk_p_int;   --create differential pair

end behavior;

DVI_MUX当我将这个块添加到系统时,错误被扔到以前没有的地方

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

ENTITY DVI_MUX IS
    PORT(
        PXLCLK   : IN  STD_LOGIC;       --pixel clock
        PXLCLK2X : IN  STD_LOGIC;       --double freq. pixel clock
        PXL_DAT  : IN  STD_LOGIC_VECTOR(23 downto 0); --pixel in RGB format
        DATA     : OUT STD_LOGIC_VECTOR(11 downto 0); --
        RESET_N  : IN  STD_LOGIC
    );
END ENTITY DVI_MUX;

architecture RTL of DVI_Mux is
begin
    mux_proc : process(PXLCLK2X)
    begin
        if falling_edge(PXLCLK2X) then
            if PXLCLK = '0' then        -- if pxlclk low, load first half of pixel
                DATA <= PXL_DAT(23 downto 16) & PXL_DAT(11 downto 8);
            else    --else load second half
                DATA <= PXL_DAT(15 downto 12) & PXL_DAT(7 downto 0);
            end if;
            if RESET_N = '0' then --if reset active7
                DATA <= (others => '1');
            end if;
        end if;
    end process;

end architecture RTL;

scary_jeff.. 5

这并不直接回答您的问题,但看起来您正在尝试使用DDR输出原语来驱动外部差分时钟引脚.这是一件好事,但你做的方式似乎是非常规的.执行此操作的标准方法看起来更像是:

编辑:我意识到我误解了这个问题,并且已经整合了@StuartVivian的差分输出实例化

pxclk_inverted <= not pxlclk;

ODDR_pxlclk_p : ODDR2
    generic map(
        DDR_ALIGNMENT => "NONE",
        INIT          => '0',
        SRTYPE        => "SYNC")
    port map(
        Q  => PXLCLK_OUT,
        C0 => pxlclk,
        C1 => pxclk_inverted,
        CE => '1',
        D0 => '1',
        D1 => '0',
        R  => '0',
        S  => '0'
    );

inst_obufds : OBUFDS 
generic map (
  IOSTANDARD=>"LVDS_25"
) 
port map 
(
  O => PXLCLK_OUT_P, 
  OB  => PXLCLK_OUT_N, 
  I   => PXLCLK_OUT
);

在IO分配中,PXLCLK_OUT_N/P将设置为使用差分IO标准.在图形引脚分配窗口中,此端口将使用两个引脚,并且只允许您将它们分配给有效的正/负对.你要做的是在DDR输出原语之前手动创建正负信号,这不是它应该工作的方式.

我想如果你使用这种技术,并摆脱你的BUFG,你的问题应该消失.如果没有,可以用这个更新问题,无论新问题是什么.


现在您已经更新了问题,我可以看到您的像素输出数据似乎也是DDR总线.您正试图通过使用时钟信号作为选择线来实现多路复用器来推断DDR输出行为.

执行此操作的更标准方法是实例化n个 DDR输出原语,对于并行DDR输出的每个位一个.根据最新的VHDL标准(VHDL2008),可以推断DDR输出,但问题在于该技术还没有广泛的工具链支持.



1> scary_jeff..:

这并不直接回答您的问题,但看起来您正在尝试使用DDR输出原语来驱动外部差分时钟引脚.这是一件好事,但你做的方式似乎是非常规的.执行此操作的标准方法看起来更像是:

编辑:我意识到我误解了这个问题,并且已经整合了@StuartVivian的差分输出实例化

pxclk_inverted <= not pxlclk;

ODDR_pxlclk_p : ODDR2
    generic map(
        DDR_ALIGNMENT => "NONE",
        INIT          => '0',
        SRTYPE        => "SYNC")
    port map(
        Q  => PXLCLK_OUT,
        C0 => pxlclk,
        C1 => pxclk_inverted,
        CE => '1',
        D0 => '1',
        D1 => '0',
        R  => '0',
        S  => '0'
    );

inst_obufds : OBUFDS 
generic map (
  IOSTANDARD=>"LVDS_25"
) 
port map 
(
  O => PXLCLK_OUT_P, 
  OB  => PXLCLK_OUT_N, 
  I   => PXLCLK_OUT
);

在IO分配中,PXLCLK_OUT_N/P将设置为使用差分IO标准.在图形引脚分配窗口中,此端口将使用两个引脚,并且只允许您将它们分配给有效的正/负对.你要做的是在DDR输出原语之前手动创建正负信号,这不是它应该工作的方式.

我想如果你使用这种技术,并摆脱你的BUFG,你的问题应该消失.如果没有,可以用这个更新问题,无论新问题是什么.


现在您已经更新了问题,我可以看到您的像素输出数据似乎也是DDR总线.您正试图通过使用时钟信号作为选择线来实现多路复用器来推断DDR输出行为.

执行此操作的更标准方法是实例化n个 DDR输出原语,对于并行DDR输出的每个位一个.根据最新的VHDL标准(VHDL2008),可以推断DDR输出,但问题在于该技术还没有广泛的工具链支持.

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有