我正在尝试处理输出到DVI芯片的像素数据.使用各种时钟频率是因为DVI芯片寄存器是使用I2C编程的(因此需要时钟<500 KHz) - 来自时钟分频器.
DVI芯片需要一个40 MHz的差分像素时钟,然而,DVI每半个显示半个字节,因此每半个周期需要另外80 MHz的时钟将每一半像素推到数据线上,这些都是来自DCM.
这导致了各种各样的问题.我试图只使用双像素时钟速率交换像素的每一半,但是我得到了错误:
This design contains a global buffer instance,
所以我在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输出,但问题在于该技术还没有广泛的工具链支持.
这并不直接回答您的问题,但看起来您正在尝试使用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输出,但问题在于该技术还没有广泛的工具链支持.