FPGA在VGA屏幕上输出模拟时钟的逻辑

时间:2015-12-10 19:18:11

标签: vhdl fpga vga

我正在实现一个模拟时钟,它将在640x480的vga屏幕上显示小时和分针,时钟以480x480为中心。时钟每分钟更新一次。下面的时序图显示了HSYNC和VSYNC的时序及其相对于26.25MHz时钟的位置。

这是我在VHDL的第一门课程,我想知道我在clock.vhd中缺少什么,以及如何有效地编写测试平台以便我可以获得输出

Timing Diagram

我有一个名为counter.vhd的独立组件,它在clock.vhd中被实例化两次,一个作为水平计数器,一个作为垂直计数器。

这是我的counter.vhd,clock.vhd和我的testbench的代码,它不完整。

counter.vhd

entity counter is
Port ( clk : STD_LOGIC;
       reset : STD_LOGIC;
                      ena : STD_LOGIC;
                      rollover_out : STD_LOGIC;
                      address : STD_LOGIC_VECTOR(7 downto 0);
                      sync : STD_LOGIC
                     );

-- Generics
generic (count_value :=800;
                    sync_start :=10;
                    sync_end :=20
                    );
end counter;

architecture Behavioral of counter is

signal temp : STD_LOGIC_VECTOR(9 downto 0); -- counts to 800

process (clk, reset)
    if (reset = 0) then
    temp <="000000";
    sync <='1';
    rollover_out <='0';
    else (clk'event & clk = 1);
    rollover_out <='0';
    temp <= temp+"000000";
            if (temp = count_value - 1) then
            temp <="000000"
            rollover_out <= '1';
            end if;
            if (sync_start = temp) then
            sync <= '0';
            end if;
            if (sync_end = temp) then 
            sync <= '1';
            end if;
    end if;
end process;

address <= temp (8 downto 1);

begin
    -- 800 horizontal sync counter
    process(h_count_reg,h_end,pixel_tick)
            begin
                    if (pixel_tick = '1') then -- 25MHz tick
                            if (h_end='1') then 
                                    h_count_next <= (others => '0');
                            else
                                    h_count_next <= h_count_reg+1;
                            end if;
                    else
                            h_count_next <= h_count_reg;
                    end if;
    end process;

    -- 525 vertical sync counter 
    process(v_count_reg,h_end,v_end,pixel_tick)
            begin
                    if (pixel_tick = '1') and (h_end = '1') then
                            if (v_end = '1') then 
                                    v_count_next <= (others => '0');
                            else 
                                    v_count_next <= v_count_reg+1;
                            end if;
                    else
                            v_count_next <= v_count_reg;
                    end if;
    end process;

end Behavioral;

clock.vhd

entity clock is
Port ( clk : in  STD_LOGIC;
       reset : in  STD_LOGIC;
       hsync : out  STD_LOGIC;
       vsync : out  STD_LOGIC;
       video_on : out  STD_LOGIC;
                      p_tick : out STD_LOGIC;
       pixel_x : out  STD_LOGIC_VECTOR(9 downto 0);
       pixel_y : out  STD_LOGIC_VECTOR(9 downto 0)
                      );
 end clock;

 architecture Behavioral of clock is
 -- VGA 640x480 sync parameters
 constant HD: integer:=640; -- horizontal display area
 constant HF: integer:=16; -- horizontal front porch
 constant HB: integer:=48; -- horizontal back porch
 constant HR: integer:=96; -- horizontal retrace "sync pulse"
 constant VD: integer:=480; -- vertical display area
 constant VF: integer:=10; -- vertical front porch
 constant VB: integer:=33; -- vertical back porch
 constant VR: integer:=2; -- vertical retrace "sync pulse"

-- mod2 counter to generate a 25MHz enable tick
signal mod2_reg : std_logic; 
signal mod2_next : std_logic;

-- sync counters for the horizontal and vertical scans
signal v_count_reg : unsigned(9 downto 0);
signal v_count_next : unsigned(9 downto 0);
signal h_count_reg : unsigned(9 downto 0);
signal h_count_next : unsigned(9 downto 0);

-- output buffer
signal v_sync_reg : unsigned(9 downto 0);
signal h_sync_reg : unsigned(9 downto 0);
signal v_sync_next : unsigned(9 downto 0); 
signal h_sync_next : unsigned(9 downto 0);

-- status signal
signal h_end : std_logic;
signal v_end : std_logic;
signal pixel_tick : std_logic;

component counter
generic (count_value :=800;
                    sync_start :=10;
                    sync_end :=20
                    );
Port                 (clk : STD_LOGIC;
     reset : STD_LOGIC;
                    ena : STD_LOGIC;
                    rollover_out : std_logic;
     sync : STD_LOGIC;
                    address : std_logic_vector(9 downto 0)
                    );

signal carry : std_logic;                        
end component;

horizontal: counter 
generic map (count_value :=800;
                            sync_start :=10;
                            sync_end :=20
                            );                                        
PORT MAP (clk <= clk;
                    reset <= reset;
                    ena <= '1';
                    rollover_out <= carry;
                    sync <= hsync
                    address <= open
                    );

vertical: counter
generic map (count_value :=525;
                            sync_start := 2;
                            sync_end := 4
                            );
Port map (clk <= clk;
                    reset <= reset;
                    ena <= carry;
                    rollover_out <= open;
                    sync <= vsync;        
                    address <= open
                    );                        

begin 
    -- register
    process(clk,reset)
            begin
                    if (reset='1') then
                            mod2_reg <= '0';
                            v_count_reg <=(others=>'0');
                            h_count_reg <=(others=>'0');
                            v_sync_reg <=(others=>'0');
                            h_sync_reg <=(others=>'0');
                    elsif(clk' event and clk='1') then
                            mod2_reg <= mod2_next;
                            v_count_reg <= v_count_next;
                            h_count_reg <= h_count_next;
                            v_sync_reg <= v_sync_next;
                            h_sync_reg <= h_sync_next;
                    end if;
    end process;

    -- mod2 circuit to generate 25MHz enable tick
    mod2_next <= not mod2_reg;

    -- 25MHz pixel tick
    pixel_tick <= '1' when mod2_reg = '1' else '0';

    -- status
    h_end <= -- end of horizontal counter
            '1' when h_count_reg = (HD+HF+HB+HR-1) else --799
            '0';
    v_end <= -- end of vertical counter
            '1' when v_count_reg = (VD+VF+VB+VR-1) else --524
            '0';

    -- video on/off
    video_on <= '1' when (h_count_reg < HD) and (v_count_reg < VD) else '0';

    -- output signals
    hsync <= h_sync_reg;
    vsync <= v_sync_reg;        
    pixel_x <= std_logic_vector(h_count_reg);
    pixel_y <= std_logic_vector(v_count_reg);
    p_tick <= pixel_tick;

end Behavioral;

测试平台

ENTITY clock_tb IS
END clock_tb;

ARCHITECTURE behavior OF clock_tb IS 

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT clock
PORT(
     clk : IN  std_logic;
     reset : IN  std_logic;
     hsync : OUT  std_logic;
     vsync : OUT  std_logic;
     video_on : OUT  std_logic;
     p_tick : OUT  std_logic;
     pixel_x : OUT  std_logic_vector(9 downto 0);
     pixel_y : OUT  std_logic_vector(9 downto 0)
    );
END COMPONENT;


--Inputs
signal clk : std_logic := '0';
signal reset : std_logic := '0';

     --Outputs
signal hsync : std_logic;
signal vsync : std_logic;
signal video_on : std_logic;
signal p_tick : std_logic;
signal pixel_x : std_logic_vector(9 downto 0);
signal pixel_y : std_logic_vector(9 downto 0);

-- Clock period definitions
constant clk_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
uut: clock PORT MAP (
      clk => tb_clk,
      reset => tb_reset,
      hsync => tb_hsync,
      vsync => tb_vsync,
      video_on => tb_video_on,
      p_tick => tb_p_tick,
      pixel_x => tb_pixel_x,
      pixel_y => tb_pixel_y
    );

-- Clock process definitions
clk_process :process
begin
            clk <= '0';
            wait for clk_period/2;
            clk <= '1';
            wait for clk_period/2;
end process;


-- Stimulus process
stim_proc: process
begin                
  -- hold reset state for 100 ns.
            wait for 100 ns;        

  wait for clk_period*10;

  -- insert stimulus here 

  wait;
end process;

END;

1 个答案:

答案 0 :(得分:1)

如果我正确理解了这个问题,您需要将您的任务分为两个部分。

首先,您需要一种设计,当给定26.25MHz时钟时,将生成HSYNC,VSYNC和视频数据信号,并将其输出到FPGA的引脚上。

其次,您需要使用代表时钟指针图形的像素数据的RGB / YCbCr位图填充该视频数据。该块将接收视频定时信号和时钟,然后填充视频数据。

如何生成时钟指针是一个棘手的部分,我怀疑运行该课程的人正在寻找解决该特定问题的聪明才智。

从小处开始积累。尝试将设计结合在一起以生成定时信号,并在屏幕上放置一个平坦的彩色块或黑白色。可以创建一个测试平台,然后将该像素数据保存到一个可以处理成位图的文件中,这样您就可以在进入硬件之前看到模拟结果。