Papilio Plus/Hello World

From Hamsterworks Wiki!

Jump to: navigation, search

This Papilio Plus project tests the basic Papilio Plus/VGA functionality by displaying "Hello world" in the screen in blocky 16x16 blocks. The screen runs in 800x600 @ 60Hz, requiring an 40MHz pixel clock.

It also puts blocks in the corners, but as 16 doesn't divide evenly into 600 the bottom corners are not at the very bottom.

This isn't my best work, but it works very well and this style design is usable well into 160MHz Pixel clock range, if required.

As well as the code below, an IP core is required for "Clk40". Use the "Clocking Wizard" IP Core to take the 32MHz clock and generate a single Clk40 output running at 40MHz (multiply by five, divide by four)/

HelloWorld.ucf

NET CLK  LOC = "P94" | PERIOD = 31.25ns | IOSTANDARD = LVCMOS25;

NET Blue(0)     LOC="P99"  | IOSTANDARD=LVTTL;  # B0
NET Blue(1)     LOC="P97"  | IOSTANDARD=LVTTL;  # B1
NET Blue(2)     LOC="P92"  | IOSTANDARD=LVTTL;  # B2
NET Blue(3)     LOC="P87"  | IOSTANDARD=LVTTL;  # B3

NET Green(0)    LOC="P84"  | IOSTANDARD=LVTTL;  # B4
NET Green(1)    LOC="P82"  | IOSTANDARD=LVTTL;  # B5
NET Green(2)    LOC="P80"  | IOSTANDARD=LVTTL;  # B6
NET Green(3)    LOC="P78"  | IOSTANDARD=LVTTL;  # B7

NET Red(0)      LOC="P118" | IOSTANDARD=LVTTL;  # C4
NET Red(1)      LOC="P119" | IOSTANDARD=LVTTL;  # C5
NET Red(2)      LOC="P120" | IOSTANDARD=LVTTL;  # C6
NET Red(3)      LOC="P121" | IOSTANDARD=LVTTL;  # C7

NET vSync       LOC="P116" | IOSTANDARD=LVTTL;  # C2
NET hSync       LOC="P117" | IOSTANDARD=LVTTL;  # C3

HelloWorld.vhd

----------------------------------------------------------------------------------
-- Engineer:       Mike Field <hamster@snap.net.nz>
-- Module Name:    HelloWorld - Behavioral 
-- Description:    Generates an 800x600 VGA screen saying "Hello World"
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

entity HelloWorld is
    Port ( clk   : in  STD_LOGIC;
           Red   : out  STD_LOGIC_VECTOR (3 downto 0);
           Green : out  STD_LOGIC_VECTOR (3 downto 0);
           Blue  : out  STD_LOGIC_VECTOR (3 downto 0);
           hSync : out  STD_LOGIC;
           vSync : out  STD_LOGIC);
end HelloWorld;

architecture Behavioral of HelloWorld is
   type reg is record
      hCounter : unsigned(10 downto 0);
      vCounter : unsigned(9 downto 0);
      shiftReg : std_logic_vector(49 downto 0);
      hSync    : std_logic;
      vSync    : std_logic;
   end record;
      signal r : reg := ((others=>'0'), (others=>'0'), (others=>'0'), '0', '0');
   signal n : reg;
   
   component clk40
   port
   (
      CLK_IN1        : in     std_logic;
      Clk40          : out    std_logic
   );
   end component;

   signal pixelClock : std_logic;
   -- Timing constants
   constant hMaxCount  : natural  := 1056;
   constant hStartSync : natural := 840;
   constant hEndSync   : natural := 968;
   constant vMaxCount  : natural := 628;
   constant vStartSync : natural := 601;
   constant vEndSync   : natural := 605;
   
begin
   -- Assign the outputs
   hSync <= r.hSync;
   vSync <= r.vSync;
   Red   <= r.shiftReg(49) & "000";-- & r.shiftReg(49) & r.shiftReg(49) & r.shiftReg(49);
   Green <= r.shiftReg(49) & "000";-- & r.shiftReg(49) & r.shiftReg(49) & r.shiftReg(49);
   Blue  <= r.shiftReg(49) & "000";-- & r.shiftReg(49) & r.shiftReg(49) & r.shiftReg(49);
   
clockgen : clk40
  port map
   (
    CLK_IN1 => clk,
    Clk40 => pixelClock
   );
    
   process(r)
   begin
      n <= r;
      n.hSync <= '0';      
      n.vSync <= '0';      

      -- Count the lines and rows
      if r.hCounter = hMaxCount-1 then
         n.hCounter <= (others => '0');
         if r.vCounter = vMaxCount-1 then
            n.vCounter <= (others => '0');
         else
            case r.vCounter(9 downto 4) is
            when "000000" => n.shiftReg <= "10000000000000000000000000000000000000000000000001";
            when "000010" => n.shiftReg <= "00101011101000100011100000010001011101100100011000";
            when "000011" => n.shiftReg <= "00101010001000100010100000010001010101010100010100";
            when "000100" => n.shiftReg <= "00111011101000100010100000010101010101110100010100";
            when "000101" => n.shiftReg <= "00101010001000100010100000011011010101100100010100";
            when "000110" => n.shiftReg <= "00101011101110111011100000010001011101010111011000";
            when "100100" => n.shiftReg <= "10000000000000000000000000000000000000000000000001";
            when others   => n.shiftReg <= (others => '0');
            end case;
            n.vCounter <= r.vCounter+1;
         end if;
      else
         n.hCounter <= r.hCounter+1;
         -- If we are crossing onto the next 16th pixel, then move the shift register along one
         if r.hCounter(3 downto 0) = "1111" then
            n.shiftReg <= r.shiftReg(48 downto 0) & '0';
         end if;
      end if;
      
      -- Are we in the hSync pulse?
      if r.hCounter >= hStartSync and r.hCounter < hEndSync then
         n.hSync <= '1';   -- Positive hSync pulse
      end if;

      -- Are we in the vSync pulse?
      if r.vCounter >= vStartSync and r.vCounter < vEndSync then
         n.vSync <= '1'; -- Positive vSync pulse
      end if;
   end process;

   process(pixelClock,n)
   begin
      if rising_edge(pixelClock)
      then
         r <= n;
      end if;
   end process;
end Behavioral;

Personal tools