为什么我的用于生成VGA信号的VHDL代码不起作用

时间:2016-02-20 16:41:54

标签: vhdl clock xilinx vga spartan

我一直在努力让它发挥作用,但在过去的6个小时内没有任何内容,但仍然没有解决它:/

所以这是顶级模块

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity Test is
  Port ( CLKI : in  STD_LOGIC;
         HSO : out  STD_LOGIC;
         VSO : out  STD_LOGIC;
         RO,GO,BO : out  STD_LOGIC);
end Test;

architecture Behavioral of Test is
  component CLK_25Mhz_Divider
    Port ( CLK : in  STD_LOGIC;
           CLK_OUT : out  STD_LOGIC);
  end component;

  component VGA_Sync
    Port ( CLK : in  STD_LOGIC;
           HS : out  STD_LOGIC;
           VS : out  STD_LOGIC;
           R,G,B : out  STD_LOGIC);
  end component;

  signal CLKBE: STD_LOGIC;

begin

  CLK_Divider_1: CLK_25Mhz_Divider port map ( CLK => CLKI,
                                              CLK_OUT => CLKBE);

  VGA_S1: VGA_Sync port map ( CLK => CLKBE,
           HS => HSO,
           VS => VSO,
           R  => RO,
              G  => GO,
              B  => BO );

end Behavioral;

时钟分频器

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity CLK_25MHz_Divider is
    Port ( CLK : in  STD_LOGIC;
           CLK_OUT : out  STD_LOGIC);
end CLK_25MHz_Divider;

architecture Behavioral of CLK_25MHz_Divider is

 BEGIN
     PROCESS(CLK)
          VARIABLE COUNT : INTEGER:=0;
          VARIABLE TEMP : STD_LOGIC:='0';
          BEGIN
                IF RISING_EDGE(CLK)THEN
                     COUNT:=COUNT+1;
                     IF COUNT=2 THEN
                          TEMP:=NOT TEMP;
                          COUNT:=0;
                     END IF;
                END IF;
                CLK_OUT<=TEMP;
                END PROCESS;
end Behavioral;

VGA信号生成模块

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity VGA_Sync is
    Port ( CLK : in  STD_LOGIC;
           HS : out  STD_LOGIC;
           VS : out  STD_LOGIC;
           R,G,B : out STD_LOGIC);
end VGA_Sync;

architecture Behavioral of VGA_Sync is

begin 

  process(CLK)

  Variable countH : Integer := 0;
  Variable countV : Integer := 0;

    begin
     if (CLK'EVENT and CLK = '1') then

        if countH < 800 then 
            countH := countH + 1;
        else 
            countH := 0;
           if countV < 500 then
                countV := countV + 1;
        else 
               countV := 0;
           end if;
        end if;

        if countH >= 16 and countH < 112 then
           HS <= '0';
       else 
           HS <= '1';
        end if;

        if countV >= 10 and countV < 12 then
           VS <= '0';
       else 
           VS <= '1';
        end if;

        if (countH < 160) or (countV < 45) then 
           R <= '0';
            G <= '0';
            B <= '0';
        else 
           R <= '1';
            G <= '0';
            B <= '1';
      end if;
   end if;
 end process;       
end Behavioral;

请告诉我您对代码错误的看法

2 个答案:

答案 0 :(得分:1)

来自以下评论问题:

  

在那个分辨率下我应该使用25Mhz所以我使用板载时钟   这是50 Mhz并使用时钟分频器模块进行分频。 -   Mostafa的

您的时钟分频器将输入频率除以4而不是2.您可以在TEMP的每两个周期切换CLK,这是{top}模块的CLKI。因此,CLK_OUT的完整周期需要4个输入时钟周期。

要除以2,必须在输入时钟的每个时钟周期切换TEMP

architecture Behavioral of CLK_25MHz_Divider is
BEGIN
     PROCESS(CLK)
          VARIABLE TEMP : STD_LOGIC:='0';
     BEGIN
         IF RISING_EDGE(CLK)THEN
             TEMP:=NOT TEMP;
         END IF;
         CLK_OUT<=TEMP;
     END PROCESS;

end Behavioral;

TEMP = '0'开始,它会在CLK的第一个上升沿切换为“1”。在第二个上升沿,TEMP切换为'0',并在第三个上升沿切换回'1'。 50 MHz输入时钟的第一个和第三个上升沿之间的持续时间为40 ns,输出时钟的频率为25 MHz。

答案 1 :(得分:1)

因为您实际上没有描述这个问题,并且因为我有一个25 MHz时钟vga生成器的测试平台,只需要更改r,g和b的类型,我就在测试平台上运行了sync_vga:

library ieee;
use ieee.std_logic_1164.all;

entity vga_sync_tb is
end entity;

architecture foo of vga_sync_tb is
    signal clk:    std_logic := '0';
    signal hs:     std_logic;
    signal vs:     std_logic;
    signal r,g,b:  std_logic;
begin
DUT:
    entity work.vga_sync 
        port map (
            clk => clk,
            hs => hs,
            vs => vs,
            r => r,
            g => g,
            b => b
        );
CLOCK:
    process
    begin
        wait for 20 ns;  -- clock period 25 MHz = 40 ns;
        clk <= not clk;
        if now > 20 ms then  -- one frame time plus a bit
            wait;
        end if;
    end process;
end architecture;

它提供了大约60 Hz的垂直同步速率:

sync_vga_tb_full.png

放大并测量两个HS边缘之间的水平速率约为31.17 KHz。

你有水平和垂直消隐间隔,你的R,G和B做你的代码所说的。

那种离开时钟分频器或与平台有关的东西。

因为时钟的测试台很简单:

library ieee;
use ieee.std_logic_1164.all;

entity clock_tb is
end entity;

architecture foo of clock_tb is
    signal clk:     std_logic := '0';
    signal clk25:   std_logic;
begin
DUT:
    entity work.clk_25mhz_divider
        port map (
            clk => clk,
            clk_out => clk25
        );
CLOCK:
    process
    begin
        wait for 10 ns; -- half the period of 50 MHz
        clk <= not clk;
        if now > 130 ns then
            wait;
        end if;
    end process;
end architecture;

它展示了Martin Zabel的回答:

clock_tb.png

你的除以2实际上除以4。给出80 ns(12.5 MHz)的周期。

这证明了模拟的有用性,并且在模拟中使用信号而不是没有历史的变量也是有帮助的。变量没有投影输出波形,模拟器必须附加额外的代码才能以波形显示它们。

使用变量代替信号的模拟性能增加是为了显示它们的能力,并且在综合中没有任何有趣的区别。