VHDL:如何在进程中使用CLK和RESET

时间:2012-04-03 08:45:43

标签: vhdl

我为斯巴达3E板的VGA控制器编写了VHDL代码。代码模拟并且在没有下面代码中的重置和clk过程的情况下运行良好。但是在插入进程(reset,clk)之后,h_count和v_count计数器停止计数并在模拟中被驱动为未定义的XXXXX。我哪里错了。代码运行完美,没有clk,重置过程(用粗体注释),我也测试了harware上的代码。

VGA控制器的代码

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity vga_controller is
    port(clk          : inout std_logic;
         clk_50       : in    std_logic;
         hsync, vsync : out   std_logic;
         video_on     : out   std_logic;
         x_pos, y_pos : out   std_logic_vector(9 downto 0);
         sw           : in    std_logic_vector(2 downto 0) := "100";
         rgb          : out   std_logic_vector(2 downto 0)
    );

end vga_controller;

architecture Behavioral of vga_controller is
    signal h_count, v_count : unsigned(9 downto 0) := (others => '0');

begin
    -- Frequency divider to get 25 MHz clk from 50 MHz clock of Spartan 3E **
    freq_dividr : entity work.t_ff port map(clk_50, clk);
    -- If i remove this process everyting works fine. Why ????**
    process(clk, reset)
    begin
        if reset = '1' then
            h_count  <= (others => '0');
            v_count  <= (others => '0');
            video_on <= '0';
        elsif clk'event and clk = '1' then
            h_count <= h_count;
            v_count <= v_count;
        end if;
    end process;

    process(clk)                        -- Process for horizontal counter
    begin
        if clk'event and clk = '1' then
            if h_count = 799 then
                h_count <= (others => '0');
            else
                h_count <= h_count + 1;
            end if;
        end if;
    end process;

    process(clk)                        -- Process for vertical counter
    begin
        if clk'event and clk = '1' and h_count = 799 then
            if v_count = 524 and h_count = 799 then
                v_count <= (others => '0');
            else
                v_count <= v_count + 1;
            end if;
        end if;
    end process;

    hsync <= '0' when (h_count >= 656 and h_count <= 751) else '1';
    vsync <= '0' when (v_count >= 490 and v_count <= 491) else '1';
    video_on <= '1' when (h_count <= 649 and v_count <= 479) else '0';
    rgb <= sw when (h_count <= 649 and v_count <= 479) else "000";

    x_pos <= std_logic_vector(h_count);
    y_pos <= std_logic_vector(v_count);

end Behavioral;

2 个答案:

答案 0 :(得分:10)

您应该只从一个进程驱动信号。只需将您的重置功能放入计数器进程,它就可以正常工作。例如:

process(clk) -- Process for horizontal counter
begin
  if(rising_edge(clk)) then
    if(rst = '1') then
      h_count <= 0;
    else
      if h_count = 799 then
        h_count <= (others => '0');
      else
        h_count <= h_count + 1;
      end if;
    end if;
  end if;
end process;

其他几点说明:

如您所见,我在上面的代码段中使用了同步重置。除非您绝对需要异步重置,否则请使用同步重置。它有助于合成器,因为有一些使用异步复位不可用的特殊结构,它有助于在设计变大时防止出现问题(并且触发器由于信号偏斜而突然开始在不同时间重置)。

此外,除了时钟进程的初始if语句中的边缘(或重置)之外,不要检查任何内容。对于您的垂直计数器,您需要检查h_count = 799.请执行以下操作:

process(clk)
begin
  if(rising_edge(clk)) then
    if(h_count = 799) then
    (...)

它更清晰,并且不容易出错。

作为最后一件事,我已将clk'event and clk=1更改为更现代的方式,rising_edge(clk)。它应该没什么区别(除非在模拟中的某些情况下),但是rising_edge内置了一些额外的检查以确保你实际上有一个优势。

答案 1 :(得分:0)

一个信号不能有多个驱动程序。如果您没有(clk, reset)进程,则hcountvcount信号均由一个进程驱动。但是当你添加(clk, reset)进程时它会有并发驱动程序。