xilinx IBUFDS 使用和仿真

xilinx IBUFDS 使用和仿真

接收代码:

以下代码的功能为:接收16位的LVDS差分信号接收:

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

library ieee;

use ieee.std_logic_1164.all;

Library UNISIM;

use UNISIM.vcomponents.all;

 

entity LVDS_RX_TEST is

         port (

                   k7_rclkp                              :                in     std_logic;

                   k7_rclkn                              :                in     std_logic;

                   lvds_rx_dp                                    :                in     std_logic_vector(15 downto 0);

                   lvds_rx_dn                                    :                in     std_logic_vector(15 downto 0);

                   adc_clk                                          :                 out   std_logic;

                   adc_dat                                         :                 out   std_logic_vector(31 downto 0)

         );

end LVDS_RX_TEST;

 

architecture rtl of LVDS_RX_TEST is

 

signal        k7_rclk                        :                 std_logic;

signal        lvds_rx_dat               :                 std_logic_vector(15 downto 0);

signal        adc_dat_i                   :                 std_logic_vector(31 downto 0);

signal        adc_dat_r                  :                 std_logic_vector(31 downto 0);

signal        k7_rclk_bufds  :                 std_logic;

begin

adc_clk              <=              k7_rclk;

process (k7_rclk)

begin

         if (k7_rclk'event and k7_rclk = '1') then

                   adc_dat_r         <=              adc_dat_i;

                   adc_dat             <=              adc_dat_r;

         end if;

end process;

K7_RCLK_IBUFDS_INST : IBUFDS

   generic map (

      DIFF_TERM                            =>   TRUE,               -- Differential Termination

      IBUF_LOW_PWR                  =>   FALSE,               -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards

      IOSTANDARD                         =>   "LVDS_25")

   port map (

      O          =>   k7_rclk_bufds,       -- Buffer output

      I           =>   k7_rclkp,                  -- Diff_p buffer input (connect directly to top-level port)

      IB         =>   k7_rclkn                    -- Diff_n buffer input (connect directly to top-level port)

   );        

K7_RCLK_BUFG_INST : BUFG

   port map (

      O                                               =>   k7_rclk,            -- 1-bit output: Clock output

      I                                                 =>   k7_rclk_bufds         -- 1-bit input: Clock input

   );        

lvds_rx_gen:

for i in 0 to 15 generate

begin

         IBUFDS_inst : IBUFDS

                   generic map (

                            DIFF_TERM              =>   TRUE,      -- Differential Termination

                            IBUF_LOW_PWR    =>   FALSE,     -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards

                            IOSTANDARD           =>   "LVDS_25")

                   port map (

                            O =>lvds_rx_dat(i),        -- Buffer output

                            I =>          lvds_rx_dp(i),         -- Diff_p buffer input (connect directly to top-level port)

                            IB => lvds_rx_dn(i)           -- Diff_n buffer input (connect directly to top-level port)

                   );

         IDDR_inst : IDDR

                   generic map (

                   DDR_CLK_EDGE=>          "SAME_EDGE_PIPELINED",   --"OPPOSITE_EDGE", "SAME_EDGE"

                                                                                                                -- or "SAME_EDGE_PIPELINED"

                   INIT_Q1 =>   '0',                                                          -- Initial value of Q1: '0' or '1'

                   INIT_Q2 =>   '0',                                                          -- Initial value of Q2: '0' or '1'

                   SRTYPE   =>   "SYNC")                                                 -- Set/Reset type: "SYNC" or "ASYNC"

                   port map (

                            Q1   =>   adc_dat_i(i),                               -- 1-bit output for positive edge of clock

                            Q2   =>   adc_dat_i(16+i),                        -- 1-bit output for negative edge of clock

                            C     =>   k7_rclk,                                     -- 1-bit clock input

                            CE   =>   '1',                                                 -- 1-bit clock enable input

                            D     =>   lvds_rx_dat(i),                         -- 1-bit DDR data input

                            R     =>   '0',                                                        -- 1-bit reset

                            S      =>   '0'                                                        -- 1-bit set

                            );                        

end generate;

end rtl;

原始仿真代码:

一开始的仿真代码如下:

module TB;

         // Inputs

         reg k7_rclkp;

         reg k7_rclkn;

         reg [15:0] lvds_rx_dp;

         reg [15:0] lvds_rx_dn;

         // Outputs

         wire adc_clk;

         wire [31:0] adc_dat;

         LVDS_RX_TEST uut (

                   .k7_rclkp(k7_rclkp),

                   .k7_rclkn(k7_rclkn),

                   .lvds_rx_dp(lvds_rx_dp),

                   .lvds_rx_dn(lvds_rx_dn),

                   .adc_clk(adc_clk),

                   .adc_dat(adc_dat)

         );

         initial begin

                   k7_rclkp = 1;

                   k7_rclkn = 0;

                   lvds_rx_dp = 0;

                   lvds_rx_dn = 0;

                   // Wait 100 ns for global reset to finish

                   #100;

         end

always #100   k7_rclkp=~k7_rclkp;

always #100   k7_rclkn=~k7_rclkn;

always #100  lvds_rx_dp =lvds_rx_dp +2'b11;

always #100  lvds_rx_dn = lvds_rx_dn +2'b10;

endmodule

仿真结果有误:

 

从图中可以看出lvds_rx_dat一直为高阻态,接收到的信号均为错误信号!!

原因分析:

         分析发现是IBUFDS原语的输出有问题!具体原因是自己对LVDS和IBUFDS的理解不到位,导致写出always #10000  lvds_rx_dp =lvds_rx_dp +2'b11;

always #10000  lvds_rx_dn = lvds_rx_dn +2'b10;这样错误的测试语句。

         事实上LVDS是差分信号,即lvds_rx_dp与lvds_rx_dn的每bit均是相反信号;IBUFDS原语的真值表如下:(其中“-*”表示输出维持上一次的输出值,保持不变)

         IBUFDS原语用于将差分输入信号转化成标准单端信号,且可加入可选延迟。在IBUFDS原语中,输入信号为I、IB,一个为主,一个为从,二者相位相反。

修改后的仿真代码:

module TB;

         // Inputs

         reg k7_rclkp;

         reg k7_rclkn;

         reg [15:0] lvds_rx_dp;

         reg [15:0] lvds_rx_dn;

         // Outputs

         wire adc_clk;

         wire [31:0] adc_dat;

         // Instantiate the Unit Under Test (UUT)

         LVDS_RX_TEST uut (

                   .k7_rclkp(k7_rclkp),

                   .k7_rclkn(k7_rclkn),

                   .lvds_rx_dp(lvds_rx_dp),

                   .lvds_rx_dn(lvds_rx_dn),

                   .adc_clk(adc_clk),

                   .adc_dat(adc_dat)

         );

         initial begin

                   // Initialize Inputs

                   k7_rclkp = 1;

                   k7_rclkn = 0;

                   lvds_rx_dp = 0;

                   lvds_rx_dn = 0;

                   #100;

         end

always #100   k7_rclkp=~k7_rclkp;

always #100   k7_rclkn=~k7_rclkn;

always #100  lvds_rx_dp =lvds_rx_dp +2'b11;

always #100  lvds_rx_dn = ~lvds_rx_dp; 

endmodule

修改后的仿真波形:

 

总结:

xilinx IBUFDS接收时先接时钟高电平的数据,但将其置于输出信号的低位!(高低位由语句:                        

 Q1 => adc_dat_i(i), -- 1-bit output for positive edge of clock

 Q2 => adc_dat_i(16+i), -- 1-bit output for negative edge of clock)决定

posted @ 2016-09-21 16:34  chuanchuan304  阅读(7882)  评论(0编辑  收藏  举报