diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2012 Gergo Erdi
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The names of the authors may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/kansas-lava-papilio.cabal b/kansas-lava-papilio.cabal
new file mode 100644
--- /dev/null
+++ b/kansas-lava-papilio.cabal
@@ -0,0 +1,54 @@
+Name:               kansas-lava-papilio
+Version:            0.1.0
+Synopsis:           Kansas Lava support files for the Papilio FPGA board
+Description:
+        IO definitions of the Papilio FPGA board and its Wings and MegaWings
+         
+Category:            Hardware
+License:             BSD3
+License-file:        LICENSE
+Copyright:           (C) 2012-2014 Gergo Erdi
+Author:              Gergo Erdi
+Maintainer:          Gergo Erdi <gergo@erdi.hu>
+Stability:	     alpha
+build-type: 	     Simple
+Cabal-Version:       >= 1.10
+Data-files: 
+   ucf/*.ucf
+
+Library
+  Build-Depends: 
+        base >= 4 && < 5,
+        netlist >= 0.3.1,
+        kansas-lava >= 0.2.4.1 && < 0.2.5,
+        kansas-lava-cores >= 0.1.2.1,
+        filepath >= 1.3,
+        sized-types >= 0.3.4,
+        ansi-terminal >= 0.5.5,
+        data-default,
+        directory,
+        bytestring,
+        network
+
+  Exposed-modules:
+        Language.KansasLava.Signal.Utils
+        Hardware.KansasLava.SevenSegment
+        Hardware.KansasLava.PS2
+        Hardware.KansasLava.VGA
+        Hardware.KansasLava.VGA.Driver
+        Hardware.KansasLava.Boards.Papilio
+        Hardware.KansasLava.Boards.Papilio.UCF
+        Hardware.KansasLava.Boards.Papilio.LogicStart
+        Hardware.KansasLava.Boards.Papilio.Arcade
+  Other-modules:
+        Paths_kansas_lava_papilio
+
+  Hs-Source-Dirs: src
+  Other-modules:
+  -- Ghc-Options: -fcontext-stack=100
+  Ghc-Options: -Werror -fwarn-unused-imports -fwarn-unused-matches -fwarn-unused-binds
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: git://github.com/gergoerdi/kansas-lava-papilio.git
diff --git a/src/Hardware/KansasLava/Boards/Papilio.hs b/src/Hardware/KansasLava/Boards/Papilio.hs
new file mode 100644
--- /dev/null
+++ b/src/Hardware/KansasLava/Boards/Papilio.hs
@@ -0,0 +1,44 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE DataKinds, KindSignatures #-}
+module Hardware.KansasLava.Boards.Papilio
+       ( Model(..)
+         -- * Class for the methods of the Papilio
+       , Papilio(..)
+         -- * Initialization, and global settings.
+       , clockRate
+       ) where
+
+import Language.KansasLava as KL
+import Hardware.KansasLava.Rate
+
+import Data.Sized.Ix hiding (all)
+import Control.Monad.Fix
+
+data Model = PapilioOne
+           | PapilioPro
+
+-- | The clock rate on the Papilio (32MHz), in hertz.
+clockRate :: Integer
+clockRate = 32 * 1000 * 1000
+
+class MonadFix fabric => Papilio fabric where
+    -- | 'board_init' sets up the use of default clock,
+    -- which is the native 32MHz on-board clock.
+    board_init :: fabric ()
+
+    -- | 'tickTock' generates 'n' pulses per second,
+    -- based on the expected simulation, or clockrate on the board.
+    -- The purpose is for controlling real-time sampling, or for animations.
+    --
+    tickTock :: (Size w) => Witness w -> Integer -> fabric (Seq Bool)
+
+instance Papilio Fabric where
+  board_init = do
+      -- we need to name and pull in the clock
+      theClk "CLK_32MHZ"
+
+  tickTock wit hz = return $ rate wit tickTime
+    where
+      clockHz = fromIntegral clockRate / fromIntegral hz
+      tickTime = 1 / clockHz
diff --git a/src/Hardware/KansasLava/Boards/Papilio/Arcade.hs b/src/Hardware/KansasLava/Boards/Papilio/Arcade.hs
new file mode 100644
--- /dev/null
+++ b/src/Hardware/KansasLava/Boards/Papilio/Arcade.hs
@@ -0,0 +1,74 @@
+{-# LANGUAGE RecordWildCards #-}
+module Hardware.KansasLava.Boards.Papilio.Arcade (
+    Model(..)
+    -- * Class for the methods of the Spartan3e
+    , Arcade(..)
+    -- * Initialization, and global settings.
+    , clockRate
+    , board_init
+    , toUCF
+      -- * Data structures
+    , Buttons(..)
+    , RawVGA(..)
+    , PS2(..)
+    ) where
+
+import Language.KansasLava as KL
+import Hardware.KansasLava.VGA
+import Hardware.KansasLava.PS2
+import Hardware.KansasLava.Boards.Papilio
+import qualified Hardware.KansasLava.Boards.Papilio.UCF as Papilio
+
+import Data.Sized.Ix
+import Data.Sized.Matrix
+import Control.Monad (ap, liftM)
+
+data Buttons clk = Buttons{ buttonUp, buttonDown
+                          , buttonLeft, buttonRight :: Signal clk Bool
+                          }
+
+class Papilio fabric => Arcade fabric where
+    -- | Setup global reset signal
+    wing_init :: fabric ()
+
+    -- | Don't use this if you also use 'wing_init' as that sets the
+    -- reset button as the global reset signal
+    resetButton :: fabric (Signal CLK Bool)
+
+    buttons :: fabric (Buttons CLK)
+    leds :: Matrix X4 (Signal CLK Bool) -> fabric ()
+    vga :: RawVGA CLK X4 X4 X4 -> fabric ()
+    ps2 :: fabric (PS2 CLK, PS2 CLK)
+
+toUCF :: Model -> KLEG -> IO String
+toUCF model = Papilio.toUCF fileName (Just "CLK_32MHZ")
+  where
+    fileName = "Arcade-" ++ designator ++ ".ucf"
+    designator = case model of
+        PapilioOne -> "One"
+        PapilioPro -> "Pro"
+
+instance Arcade Fabric where
+    wing_init = theRst "RESET"
+
+    resetButton = inStdLogic "RESET"
+
+    buttons = Buttons
+              `liftM` inStdLogic "BTN_UP"
+              `ap`    inStdLogic "BTN_DOWN"
+              `ap`    inStdLogic "BTN_LEFT"
+              `ap`    inStdLogic "BTN_RIGHT"
+
+    leds inp = outStdLogicVector "LED" (pack inp :: Seq (Matrix X4 Bool))
+
+    vga RawVGA{..} = do
+        outStdLogicVector "VGA_R" (pack vgaRawR :: Seq (Matrix X4 Bool))
+        outStdLogicVector "VGA_G" (pack vgaRawG :: Seq (Matrix X4 Bool))
+        outStdLogicVector "VGA_B" (pack vgaRawB :: Seq (Matrix X4 Bool))
+        outStdLogic "VGA_VSYNC" vgaRawVSync
+        outStdLogic "VGA_HSYNC" vgaRawHSync
+
+    ps2 = do
+        ps2a <- PS2 `liftM` inStdLogic "PS2A_CLK" `ap` inStdLogic "PS2A_DAT"
+        ps2b <- PS2 `liftM` inStdLogic "PS2B_CLK" `ap` inStdLogic "PS2B_DAT"
+        return (ps2a, ps2b)
diff --git a/src/Hardware/KansasLava/Boards/Papilio/LogicStart.hs b/src/Hardware/KansasLava/Boards/Papilio/LogicStart.hs
new file mode 100644
--- /dev/null
+++ b/src/Hardware/KansasLava/Boards/Papilio/LogicStart.hs
@@ -0,0 +1,130 @@
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE DataKinds #-}
+module Hardware.KansasLava.Boards.Papilio.LogicStart
+       ( Model(..)
+         -- * Class for the methods of the Spartan3e
+       , LogicStart(..)
+         -- * Initialization, and global settings.
+       , clockRate
+       , board_init
+       , toUCF
+         -- * Data structures
+       , Active(..)
+       , SevenSegment(..)
+       , Buttons(..)
+       , VGA(..)
+         -- -- * Utilities for Board and Simulation use
+       , switchesP
+         -- , buttonsP -- TODO
+       , ledsP
+       ) where
+
+import Language.KansasLava as KL
+import Hardware.KansasLava.Boards.Papilio
+import qualified Hardware.KansasLava.Boards.Papilio.UCF as Papilio
+import Hardware.KansasLava.SevenSegment
+import Hardware.KansasLava.VGA
+
+import Data.Sized.Ix hiding (all)
+import Data.Sized.Matrix hiding (all)
+import Control.Applicative
+import Control.Monad (ap, liftM)
+
+data Buttons clk = Buttons{ buttonUp, buttonDown
+                          , buttonLeft, buttonRight
+                          , buttonCenter :: Signal clk Bool
+                          }
+
+------------------------------------------------------------
+-- The LogicStart class
+------------------------------------------------------------
+
+class Papilio fabric => LogicStart fabric where
+   ----------------------------------------------------------------------------
+
+   ----------------------------------------------------------------------------
+
+   switches :: fabric (Matrix X8 (Signal CLK Bool))
+   buttons :: fabric (Buttons CLK)
+   leds :: Matrix X8 (Signal CLK Bool) -> fabric ()
+   sseg :: SevenSegment CLK ActiveLow X4 -> fabric ()
+   vga :: RawVGA CLK X3 X3 X2 -> fabric ()
+
+------------------------------------------------------------
+-- initialization
+------------------------------------------------------------
+
+toUCF :: Model -> KLEG -> IO String
+toUCF model = Papilio.toUCF fileName (Just "CLK_32MHZ")
+  where
+    fileName = "Arcade-" ++ designator ++ ".ucf"
+    designator = case model of
+        PapilioOne -> "One"
+        PapilioPro -> "Pro"
+
+------------------------------------------------------------
+-- instance
+------------------------------------------------------------
+
+instance LogicStart Fabric where
+  ------------------------------------------------------------
+  -- RAW APIs
+  ------------------------------------------------------------
+
+  switches = do
+        inp <- inStdLogicVector "SWITCH" :: Fabric (Seq (Matrix X8 Bool))
+        return (unpack inp)
+
+  buttons = Buttons
+            `liftM` inStdLogic "BTN_UP"
+            `ap`    inStdLogic "BTN_DOWN"
+            `ap`    inStdLogic "BTN_LEFT"
+            `ap`    inStdLogic "BTN_RIGHT"
+            `ap`    inStdLogic "BTN_CENTER"
+
+  leds inp = outStdLogicVector "LED" (pack inp :: Seq (Matrix X8 Bool))
+
+  sseg SevenSegment{..} = do
+      outStdLogicVector "SS_ANODES" (pack ssAnodes :: Seq (Matrix X4 Bool))
+      outStdLogicVector "SS_SEGS" (pack ssSegments :: Seq (Matrix X7 Bool))
+      outStdLogic "SS_DP" ssDecimalPoint
+
+  vga RawVGA{..} = do
+      outStdLogicVector "VGA_R" (pack vgaRawR :: Seq (Matrix X3 Bool))
+      outStdLogicVector "VGA_G" (pack vgaRawG :: Seq (Matrix X3 Bool))
+      outStdLogicVector "VGA_B" (pack vgaRawB :: Seq (Matrix X2 Bool))
+      outStdLogic "VGA_VSYNC" vgaRawVSync
+      outStdLogic "VGA_HSYNC" vgaRawHSync
+
+-------------------------------------------------------------
+-- Utilites that can be shared
+-------------------------------------------------------------
+
+-- | 'switchesP' gives a patch-level API for the toggle switches.
+switchesP :: (LogicStart fabric)
+          => fabric (Patch () (Matrix X8 (Seq Bool)) () (Matrix X8 ()))
+switchesP = do
+    sws <- switches
+    return $
+      outputP sws $$
+      backwardP (\ _mat -> ()) $$
+      matrixStackP (pure emptyP)
+
+{-
+-- | 'buttonsP' gives a patch-level API for the toggle switches.
+buttonsP :: (LogicStart fabric)
+         => fabric (Patch () Buttons () (Matrix X5 ()))
+buttonsP = do
+    btns <- buttons
+    return $
+      outputP btns $$
+      backwardP (\ _mat -> ()) $$
+      matrixStackP (pure emptyP)
+-}
+
+-- | 'ledP' gives a patch-level API for the leds.
+ledsP :: (LogicStart fabric)
+      => Patch (Matrix X8 (Seq Bool)) (fabric ()) (Matrix X8 ()) ()
+ledsP =
+    backwardP (\ () -> pure ()) $$
+    forwardP leds
diff --git a/src/Hardware/KansasLava/Boards/Papilio/UCF.hs b/src/Hardware/KansasLava/Boards/Papilio/UCF.hs
new file mode 100644
--- /dev/null
+++ b/src/Hardware/KansasLava/Boards/Papilio/UCF.hs
@@ -0,0 +1,15 @@
+module Hardware.KansasLava.Boards.Papilio.UCF (toUCF) where
+
+import Language.KansasLava
+import Hardware.KansasLava.Boards.UCF (filterUCF)
+import System.FilePath.Posix ((</>))
+
+import Paths_kansas_lava_papilio
+
+getUCF :: FilePath -> IO String
+getUCF fileName = getDataFileName ("ucf" </> fileName)
+
+toUCF :: FilePath -> Maybe String -> KLEG -> IO String
+toUCF fileName rawClock kleg = do
+    src <- readFile =<< getUCF fileName
+    return $ filterUCF rawClock kleg src
diff --git a/src/Hardware/KansasLava/PS2.hs b/src/Hardware/KansasLava/PS2.hs
new file mode 100644
--- /dev/null
+++ b/src/Hardware/KansasLava/PS2.hs
@@ -0,0 +1,97 @@
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TypeFamilies #-}
+module Hardware.KansasLava.PS2
+       ( PS2(..)
+       , samplePS2
+       , decodePS2
+       ) where
+
+import Language.KansasLava
+import Data.Bits
+import Language.KansasLava.Signal.Utils
+import Data.Sized.Matrix as Matrix
+import Data.Sized.Unsigned as Unsigned
+
+data PS2 clk = PS2{ ps2Clock, ps2Data :: Signal clk Bool }
+
+data PS2State = Idle
+              | Shift
+              | Parity
+              | Stop
+              deriving (Eq, Enum, Bounded)
+
+instance Rep PS2State where
+    type W PS2State = X2
+    newtype X PS2State = XPS2State{ unXPS2State :: Maybe PS2State }
+
+    unX = unXPS2State
+    optX = XPS2State
+
+    toRep s = toRep . optX $ s'
+      where
+        s' :: Maybe X4
+        s' = fmap (fromIntegral . fromEnum) $ unX s
+
+    fromRep rep = optX $ fmap (toEnum . fromIntegral) $ unX x
+      where
+        x :: X X4
+        x = sizedFromRepToIntegral rep
+
+    repType _ = repType (Witness :: Witness X4)
+
+samplePS2 :: (Clock clk) => PS2 clk -> Signal clk (Enabled Bool)
+samplePS2 PS2{..} = runRTL $ do
+    ps2Clock' <- newReg False
+    clockPattern <- newReg (0 :: U8)
+
+    ps2Data' <- newReg False
+    dataPattern <- newReg (0 :: U8)
+
+    let fallingClock = reg ps2Clock' .&&. bitNot (var ps2Clock')
+
+    clockPattern := (reg clockPattern `shiftL` 1) .|. unsigned ps2Clock
+    CASE [ IF (reg clockPattern .==. pureS maxBound) $ do
+                ps2Clock' := high
+         , IF (reg clockPattern .==. pureS minBound) $ do
+                ps2Clock' := low
+         ]
+
+    dataPattern := (reg dataPattern `shiftL` 1) .|. unsigned ps2Data
+    CASE [ IF (reg dataPattern .==. pureS maxBound) $ do
+                ps2Data' := high
+         , IF (reg dataPattern .==. pureS minBound) $ do
+                ps2Data' := low
+         ]
+
+    return $ packEnabled fallingClock (reg ps2Data')
+
+decodePS2 :: (Clock clk) => Signal clk (Enabled Bool) -> Signal clk (Enabled U8)
+decodePS2 line = runRTL $ do
+    state <- newReg Idle
+    shiftCounter <- newReg (0 :: X8)
+    shift <- newReg (0 :: U8)
+
+    parityChecked <- newReg False
+    haveCode <- newReg False
+    let enableOutput = var haveCode .&&. isEnabled line
+
+    whenEnabled line $ \ps2Data -> do
+        CASE
+          [ IF (reg state .==. pureS Idle) $ do
+                 state := mux ps2Data (pureS Shift, pureS Idle)
+                 haveCode := low
+                 shift := 0
+          , IF (reg state .==. pureS Shift) $ do
+                 let last = reg shiftCounter .==. pureS maxBound
+                 state := mux last (pureS Shift, pureS Parity)
+                 shiftCounter := mux last (reg shiftCounter + 1, 0)
+                 shift := (reg shift `shiftR` 1) .|. (unsigned ps2Data `shiftL` 7)
+          , IF (reg state .==. pureS Parity) $ do
+                 state := pureS Stop
+                 parityChecked := ps2Data `xor2` parity (reg shift)
+          , IF (reg state .==. pureS Stop) $ do
+                 state := pureS Idle
+                 haveCode := ps2Data .&&. reg parityChecked
+          ]
+
+    return $ packEnabled enableOutput (reg shift)
diff --git a/src/Hardware/KansasLava/SevenSegment.hs b/src/Hardware/KansasLava/SevenSegment.hs
new file mode 100644
--- /dev/null
+++ b/src/Hardware/KansasLava/SevenSegment.hs
@@ -0,0 +1,100 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE DataKinds #-}
+module Hardware.KansasLava.SevenSegment
+       ( Active(..)
+       , SevenSegment(..)
+       , encodeHexSS
+       , showSS
+       , driveSS
+       , driveSS_
+       ) where
+
+import Language.KansasLava
+import Language.KansasLava.Signal.Utils
+import Data.Sized.Matrix as Matrix
+import Data.Sized.Unsigned as Unsigned
+import Data.Maybe (isJust, fromMaybe)
+import Control.Applicative
+
+data Active = ActiveHigh | ActiveLow
+
+data SevenSegment clk (active :: Active) n = SevenSegment
+    { ssAnodes :: Matrix n (Signal clk Bool)
+    , ssSegments :: Matrix X7 (Signal clk Bool)
+    , ssDecimalPoint :: Signal clk Bool
+    }
+
+encodeHexSS :: Unsigned X4 -> Matrix X7 Bool
+encodeHexSS n = matrix $ case n of
+    --        a      b      c      d      e      f      g
+    0x0 -> [  True,  True,  True,  True,  True,  True, False ]
+    0x1 -> [ False,  True,  True, False, False, False, False ]
+    0x2 -> [  True,  True, False,  True,  True, False,  True ]
+    0x3 -> [  True,  True,  True,  True, False, False,  True ]
+    0x4 -> [ False,  True,  True, False, False,  True,  True ]
+    0x5 -> [  True, False,  True,  True, False,  True,  True ]
+    0x6 -> [  True, False,  True,  True,  True,  True,  True ]
+    0x7 -> [  True,  True,  True, False, False, False, False ]
+    0x8 -> [  True,  True,  True,  True,  True,  True,  True ]
+    0x9 -> [  True,  True,  True,  True, False,  True,  True ]
+    0xa -> [  True,  True,  True, False,  True,  True,  True ]
+    0xb -> [ False, False,  True,  True,  True,  True,  True ]
+    0xc -> [  True, False, False,  True,  True,  True, False ]
+    0xd -> [ False,  True,  True,  True,  True, False,  True ]
+    0xe -> [  True, False, False,  True,  True,  True,  True ]
+    0xf -> [  True, False, False, False,  True,  True,  True ]
+
+-- For testing
+showSS :: Matrix X7 Bool -> String
+showSS (toList -> [a, b, c, d, e, f, g])
+  = unlines
+    [ vpad   ++ horiz a ++ vpad
+    , vert f ++ hpad    ++ vert b
+    , vert f ++ hpad    ++ vert b
+    , vpad   ++ horiz g ++ vpad
+    , vert e ++ hpad    ++ vert c
+    , vert e ++ hpad    ++ vert c
+    , vpad   ++ horiz d ++ vpad
+    ]
+  where
+    vpad = replicate 1 ' '
+    hpad = replicate 3 ' '
+    horiz b = replicate 3 $ if b then '#' else ' '
+    vert b = replicate 1 $ if b then '#' else ' '
+
+driveSS_ :: forall clk sig n. (Clock clk, sig ~ Signal clk, Size n, Rep n, Num n, Integral n)
+         => Matrix n (Maybe (Matrix X7 (sig Bool)))
+         -> SevenSegment clk ActiveLow n
+driveSS_ segss = driveSS mask segss'
+  where
+    mask = fmap (pureS . isJust) segss
+    segss' = fmap (fromMaybe noSegs) segss
+
+    noSegs :: Matrix X7 (sig Bool)
+    noSegs = matrix $ replicate 7 low
+
+driveSS :: forall clk sig n. (Clock clk, sig ~ Signal clk, Size n, Rep n, Num n, Integral n)
+        => Matrix n (sig Bool)
+        -> Matrix n (Matrix X7 (sig Bool))
+        -> SevenSegment clk ActiveLow n
+driveSS mask segss = SevenSegment (bitNot <$> anodes') (bitNot <$> segs) high
+  where
+    clkAnode :: sig Bool
+    clkAnode = divideClk (Witness :: Witness X4)
+
+    selector :: sig n
+    selector = counter clkAnode
+
+    segss' :: Matrix X7 (Matrix n (sig Bool))
+    segss' = columns . joinRows $ segss
+
+    segs :: Matrix X7 (sig Bool)
+    segs = fmap (nary selector) segss'
+
+    anodes :: Matrix n (sig Bool)
+    anodes = fmap (.&&. clkAnode) $ rotatorL clkAnode
+
+    anodes' :: Matrix n (sig Bool)
+    anodes' = Matrix.zipWith (.&&.) mask anodes
diff --git a/src/Hardware/KansasLava/VGA.hs b/src/Hardware/KansasLava/VGA.hs
new file mode 100644
--- /dev/null
+++ b/src/Hardware/KansasLava/VGA.hs
@@ -0,0 +1,38 @@
+{-# LANGUAGE RecordWildCards #-}
+module Hardware.KansasLava.VGA
+       ( VGA(..), RawVGA(..)
+       , encodeVGA
+       ) where
+
+import Language.KansasLava
+import Language.KansasLava.Signal.Utils
+import Data.Sized.Matrix as Matrix
+import Data.Sized.Unsigned as Unsigned
+
+data VGA clk r g b =
+    VGA{ vgaR :: Signal clk (Enabled r)
+       , vgaG :: Signal clk (Enabled g)
+       , vgaB :: Signal clk (Enabled b)
+       , vgaVSync, vgaHSync :: Signal clk Bool
+       }
+
+data RawVGA clk r g b =
+    RawVGA{ vgaRawR :: Matrix r (Signal clk Bool)
+          , vgaRawG :: Matrix g (Signal clk Bool)
+          , vgaRawB :: Matrix b (Signal clk Bool)
+          , vgaRawVSync, vgaRawHSync :: Signal clk Bool
+          }
+
+encodeVGA :: (Size r, Size g, Size b)
+          => VGA clk (Unsigned r) (Unsigned g) (Unsigned b)
+          -> RawVGA clk r g b
+encodeVGA VGA{..} = RawVGA{..}
+  where
+    vgaRawR = toColors vgaR
+    vgaRawG = toColors vgaG
+    vgaRawB = toColors vgaB
+
+    vgaRawVSync = vgaVSync
+    vgaRawHSync = vgaHSync
+
+    toColors c = fmap (isEnabled c .&&.) $ fromUnsigned (enabledVal c)
diff --git a/src/Hardware/KansasLava/VGA/Driver.hs b/src/Hardware/KansasLava/VGA/Driver.hs
new file mode 100644
--- /dev/null
+++ b/src/Hardware/KansasLava/VGA/Driver.hs
@@ -0,0 +1,101 @@
+{-# LANGUAGE RecordWildCards #-}
+module Hardware.KansasLava.VGA.Driver
+       ( -- * Generic VGA driver
+         VGAParams(..)
+       , VGATiming(..)
+       , VGADriverIn(..)
+       , VGADriverOut(..)
+       , driveVGA
+         -- * Timing parameters for predefined VGA modes
+       , vga640x480at60
+       ) where
+
+import Language.KansasLava
+import Hardware.KansasLava.VGA as VGA
+
+import Data.Sized.Unsigned as Unsigned
+import Data.Sized.Ix
+
+data VGADriverIn clk r g b = VGADriverIn
+                             { vgaInR :: Signal clk r
+                             , vgaInG :: Signal clk g
+                             , vgaInB :: Signal clk b
+                             }
+
+data VGADriverOut clk w h r g b = VGADriverOut
+                                  { vgaOut :: VGA clk r g b
+                                  , vgaOutClkPhase :: Signal clk Bool
+                                  , vgaOutVBlank :: Signal clk Bool
+                                  , vgaOutX :: Signal clk (Enabled (Unsigned w))
+                                  , vgaOutY :: Signal clk (Enabled (Unsigned h))
+                                  }
+
+data VGAParams w h = VGAParams
+                     { vgaHorizTiming :: VGATiming w
+                     , vgaVertTiming :: VGATiming h
+                     }
+
+data VGATiming a = VGATiming{ visibleSize, pre, syncPulse, post :: Unsigned a }
+
+-- | Assumes a circuit clock at double the frequency of the pixel clock
+driveVGA :: (Clock clk, Rep r, Rep g, Rep b, Size w, Size h)
+         => VGAParams w h
+         -> VGADriverIn clk r g b
+         -> VGADriverOut clk w h r g b
+driveVGA VGAParams{..} VGADriverIn{..} = runRTL $ do
+    hCount <- newReg 0
+    vCount <- newReg 0
+
+    let hEnd = reg hCount .==. pureS hMax
+        vEnd = reg vCount .==. pureS vMax
+
+    let phase = iterateS bitNot False
+    WHEN phase $ do
+        hCount := mux hEnd (reg hCount + 1, 0)
+        WHEN hEnd $ do
+            vCount := mux vEnd (reg vCount + 1, 0)
+
+    let hsync = pureS hSyncStart .<=. reg hCount .&&.
+                reg hCount .<. pureS hSyncEnd
+        vsync = pureS vSyncStart .<=. reg vCount .&&.
+                reg vCount .<. pureS vSyncEnd
+
+    let hVisible = reg hCount .<. pureS hSize
+        vVisible = reg vCount .<. pureS vSize
+        visible = hVisible .&&. vVisible
+
+    let vgaOutClkPhase = phase
+        vgaOutVBlank = phase .&&. reg hCount .==. 0 .&&.
+                       reg vCount .==. pureS vSyncStart
+        vgaOutX = packEnabled visible (reg hCount)
+        vgaOutY = packEnabled visible (reg vCount)
+        vgaOut = VGA{ vgaR = packEnabled visible vgaInR
+                    , vgaG = packEnabled visible vgaInG
+                    , vgaB = packEnabled visible vgaInB
+                    , vgaHSync = bitNot hsync
+                    , vgaVSync = bitNot vsync
+                    }
+
+    return VGADriverOut{..}
+  where
+    hSize = visibleSize vgaHorizTiming
+    hPre = pre vgaHorizTiming
+    hSync = syncPulse vgaHorizTiming
+    hSyncStart = hSize + hPre
+    hSyncEnd = hSyncStart + hSync
+    hPost = post vgaHorizTiming
+    hMax = sum [hSize, hPre, hSync, hPost] - 1
+
+    vSize = visibleSize vgaVertTiming
+    vPre = pre vgaVertTiming
+    vSync = syncPulse vgaVertTiming
+    vSyncStart = vSize + vPre
+    vSyncEnd = vSyncStart + vSync
+    vPost = post vgaVertTiming
+    vMax = sum [vSize, vPre, vSync, vPost] - 1
+
+-- | VGA 640*480@60Hz, 25.175 MHz pixel clock
+vga640x480at60 :: VGAParams X10 X10
+vga640x480at60 = VGAParams{ vgaHorizTiming = VGATiming 640 16 96 48
+                          , vgaVertTiming  = VGATiming 480 16  2 33
+                          }
diff --git a/src/Language/KansasLava/Signal/Utils.hs b/src/Language/KansasLava/Signal/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/KansasLava/Signal/Utils.hs
@@ -0,0 +1,83 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Language.KansasLava.Signal.Utils
+       ( splitByte
+       , debounce
+       , nary
+       , divideClk
+       , counter
+       , rotatorL
+       , fromUnsigned
+       , toUnsigned
+       , parity
+       , whenEnabled
+       ) where
+
+import Language.KansasLava
+import Data.Sized.Matrix as Matrix
+import Data.Sized.Unsigned as Unsigned
+import Data.Bits
+
+splitByte :: (sig ~ Signal c) => sig (Unsigned X8) -> (sig (Unsigned X4), sig (Unsigned X4))
+splitByte sig = (hi, lo)
+  where
+    mtx = fromUnsigned sig
+    hi = toUnsigned . flip cropAt 4 $ mtx
+    lo = toUnsigned . flip cropAt 0 $ mtx
+
+debounce :: forall c sig n. (Clock c, sig ~ Signal c, Size n)
+          => Witness n -> sig Bool -> (sig Bool, sig Bool, sig Bool)
+debounce _ button = runRTL $ do
+    -- Based on http://www.fpga4fun.com/Debouncer2.html
+    counter <- newReg (0 :: Unsigned n)
+    let counter_max = reg counter .==. maxBound
+    toggle <- newReg False
+
+    let idle = reg toggle ./=. button
+        down = bitNot (reg toggle) .&&. bitNot idle .&&. counter_max
+        up = reg toggle .&&. bitNot idle .&&. counter_max
+
+    CASE [ IF idle $ do
+                counter := 0
+         , OTHERWISE $ do
+                counter := reg counter + 1
+                WHEN counter_max $ do
+                    toggle := bitNot (reg toggle)
+         ]
+
+    return (up, down, reg toggle)
+
+nary :: forall a clk sig n. (Clock clk, sig ~ Signal clk, Rep a, Size n, Rep n) => sig n -> Matrix n (sig a) -> sig a
+nary sel inps = pack inps .!. sel
+
+divideClk :: forall c sig ix. (Clock c, sig ~ Signal c, Size ix) => Witness ix -> sig Bool
+divideClk _ = counter high .==. (0 :: sig (Unsigned ix))
+
+counter :: (Rep a, Num a, Bounded a, Eq a, Clock c, sig ~ Signal c) => sig Bool -> sig a
+counter inc = loop
+  where
+    reg = register 0 loop
+    reg' = mux (reg .==. maxBound) (reg + 1, 0)
+    loop = mux inc (reg, reg')
+
+rotatorL :: (Clock c, sig ~ Signal c, Size ix, Integral ix) => sig Bool -> Matrix ix (sig Bool)
+rotatorL step = fromUnsigned loop
+  where
+    reg = register 1 loop
+    loop = mux step (reg, rotateL reg 1)
+
+fromUnsigned :: (sig ~ Signal c, Size ix) => sig (Unsigned ix) -> Matrix ix (sig Bool)
+fromUnsigned = unpack . coerce Unsigned.toMatrix
+
+toUnsigned :: (sig ~ Signal c, Size ix) => Matrix ix (sig Bool) -> sig (Unsigned ix)
+toUnsigned = coerce Unsigned.fromMatrix . pack
+
+parity :: forall clk n. (Clock clk, Size n, Rep n, Integral n, Enum n)
+       => Signal clk (Unsigned n) -> Signal clk Bool
+parity x = foldr xor2 low $ map (testABit x . pureS) [minBound .. maxBound :: n]
+
+whenEnabled :: (Clock clk, Rep a)
+            => Signal clk (Enabled a)
+            -> (Signal clk a -> RTL s clk ())
+            -> RTL s clk ()
+whenEnabled sig = CASE . return . match sig
diff --git a/ucf/Arcade-One.ucf b/ucf/Arcade-One.ucf
new file mode 100644
--- /dev/null
+++ b/ucf/Arcade-One.ucf
@@ -0,0 +1,69 @@
+## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration.
+CONFIG PROHIBIT=P99;
+CONFIG PROHIBIT=P43;
+CONFIG PROHIBIT=P42;
+CONFIG PROHIBIT=P39;
+CONFIG PROHIBIT=P49;
+CONFIG PROHIBIT=P48;
+CONFIG PROHIBIT=P47;
+CONFIG PART=XC3S500E-VQ100-5;
+
+# Clock
+NET "CLK_32MHZ" LOC = "P89" | IOSTANDARD = LVCMOS25 | PERIOD=31.25ns;
+
+# Reset
+NET "RESET" LOC="P67"  | IOSTANDARD=LVTTL | PULLDOWN;
+
+# Joypad
+NET "BTN_UP"      LOC="P54"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;
+NET "BTN_DOWN"    LOC="P41"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;
+NET "BTN_LEFT"    LOC="P58"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;
+NET "BTN_RIGHT"   LOC="P36"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;
+
+# PS/2, port A
+NET "PS2A_DAT"    LOC="P91"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP;
+NET "PS2A_CLK"    LOC="P92"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP;
+
+# PS/2, port B
+NET "PS2B_DAT"    LOC="P70"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP;
+NET "PS2B_CLK"    LOC="P79"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP;
+
+# Joystick, port A
+NET "JOYA_UP"    LOC="P34"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B12
+NET "JOYA_DOWN"  LOC="P25"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B14
+NET "JOYA_LEFT"  LOC="P22"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B15
+NET "JOYA_RIGHT" LOC="P23"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A1
+NET "JOYA_FIRE1" LOC="P32"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B13
+NET "JOYA_FIRE2" LOC="P33"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A3
+NET "JOYA_GND"   LOC="P18"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A0
+
+# Joystick, port B
+NET "JOYB_UP"    LOC="P5"    | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B12
+NET "JOYB_DOWN"  LOC="P10"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B14
+NET "JOYB_LEFT"  LOC="P11"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B15
+NET "JOYB_RIGHT" LOC="P15"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A1
+NET "JOYB_FIRE1" LOC="P9"    | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B13
+NET "JOYB_FIRE2" LOC="P17"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A3
+NET "JOYB_GND"   LOC="P12"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A0
+
+# LEDs
+NET "LED<3>"      LOC="P35"  | IOSTANDARD=LVTTL;                                # A4
+NET "LED<2>"      LOC="P40"  | IOSTANDARD=LVTTL;                                # A5
+NET "LED<1>"      LOC="P53"  | IOSTANDARD=LVTTL;                                # A6
+NET "LED<0>"      LOC="P57"  | IOSTANDARD=LVTTL;                                # A7
+
+# VGA
+NET "VGA_R<0>"    LOC="P98"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # C4
+NET "VGA_R<1>"    LOC="P2"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # C5
+NET "VGA_R<2>"    LOC="P3"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # C6
+NET "VGA_R<3>"    LOC="P4"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # C7
+NET "VGA_G<0>"    LOC="P68"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B4
+NET "VGA_G<1>"    LOC="P66"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B5
+NET "VGA_G<2>"    LOC="P63"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B6
+NET "VGA_G<3>"    LOC="P61"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B7
+NET "VGA_B<0>"    LOC="P85"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B0
+NET "VGA_B<1>"    LOC="P83"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B1
+NET "VGA_B<2>"    LOC="P78"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B2
+NET "VGA_B<3>"    LOC="P71"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B3
+NET "VGA_VSYNC"   LOC="P94"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B3
+NET "VGA_HSYNC"   LOC="P95"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B3
diff --git a/ucf/Arcade-Pro.ucf b/ucf/Arcade-Pro.ucf
new file mode 100644
--- /dev/null
+++ b/ucf/Arcade-Pro.ucf
@@ -0,0 +1,65 @@
+## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration.
+CONFIG PROHIBIT=P60;
+CONFIG PROHIBIT=P69;
+CONFIG PROHIBIT=P144;
+CONFIG PART=XC6SLX9-TQG144-2;
+
+# Clock
+NET "CLK_32MHZ" LOC = "P94" | IOSTANDARD = LVTTL | PERIOD=31.25ns;
+
+# Reset
+NET "RESET" LOC="P85"  | IOSTANDARD=LVTTL | PULLDOWN;
+
+# Joypad
+NET "BTN_UP"      LOC="P95"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;
+NET "BTN_DOWN"    LOC="P62"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;
+NET "BTN_LEFT"    LOC="P74"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;
+NET "BTN_RIGHT"   LOC="P59"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;
+
+# PS/2, port A
+NET "PS2A_DAT"    LOC="P114"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP;
+NET "PS2A_CLK"    LOC="P115"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP;
+
+# PS/2, port B
+NET "PS2B_DAT"    LOC="P88"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP;
+NET "PS2B_CLK"    LOC="P93"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP;
+
+# Joystick, port A
+NET "JOYA_UP"    LOC="P57"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B12
+NET "JOYA_DOWN"  LOC="P50"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B14
+NET "JOYA_LEFT"  LOC="P47"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B15
+NET "JOYA_RIGHT" LOC="P51"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A1
+NET "JOYA_FIRE1" LOC="P55"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B13
+NET "JOYA_FIRE2" LOC="P58"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A3
+NET "JOYA_GND"   LOC="P48"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A0
+
+# Joystick, port B
+NET "JOYB_UP"    LOC="P123"    | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B12
+NET "JOYB_DOWN"  LOC="P126"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B14
+NET "JOYB_LEFT"  LOC="P127"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B15
+NET "JOYB_RIGHT" LOC="P132"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A1
+NET "JOYB_FIRE1" LOC="P124"    | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # B13
+NET "JOYB_FIRE2" LOC="P134"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A3
+NET "JOYB_GND"   LOC="P131"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # A0
+
+# LEDs
+NET "LED<3>"      LOC="P61"  | IOSTANDARD=LVTTL;                                # A4
+NET "LED<2>"      LOC="P66"  | IOSTANDARD=LVTTL;                                # A5
+NET "LED<1>"      LOC="P67"  | IOSTANDARD=LVTTL;                                # A6
+NET "LED<0>"      LOC="P75"  | IOSTANDARD=LVTTL;                                # A7
+
+# VGA
+NET "VGA_R<0>"    LOC="P118"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # C4
+NET "VGA_R<1>"    LOC="P119"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # C5
+NET "VGA_R<2>"    LOC="P120"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # C6
+NET "VGA_R<3>"    LOC="P121"   | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # C7
+NET "VGA_G<0>"    LOC="P84"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B4
+NET "VGA_G<1>"    LOC="P82"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B5
+NET "VGA_G<2>"    LOC="P80"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B6
+NET "VGA_G<3>"    LOC="P78"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B7
+NET "VGA_B<0>"    LOC="P99"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B0
+NET "VGA_B<1>"    LOC="P97"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B1
+NET "VGA_B<2>"    LOC="P92"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B2
+NET "VGA_B<3>"    LOC="P87"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B3
+NET "VGA_VSYNC"   LOC="P116"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B3
+NET "VGA_HSYNC"   LOC="P117"  | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST;          # B3
diff --git a/ucf/LogicStart-One.ucf b/ucf/LogicStart-One.ucf
new file mode 100644
--- /dev/null
+++ b/ucf/LogicStart-One.ucf
@@ -0,0 +1,68 @@
+## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration.
+CONFIG PROHIBIT=P99;
+CONFIG PROHIBIT=P43;
+CONFIG PROHIBIT=P42;
+CONFIG PROHIBIT=P39;
+CONFIG PROHIBIT=P49;
+CONFIG PROHIBIT=P48;
+CONFIG PROHIBIT=P47;
+CONFIG PART=XC3S500E-VQ100-5;
+
+
+# Clock
+NET "CLK_32MHZ" LOC = "P89" | IOSTANDARD = LVCMOS25 | PERIOD=31.25ns;
+
+# 7-segment display
+
+NET "SS_ANODES<0>" LOC="P67";
+NET "SS_ANODES<1>" LOC="P60";
+NET "SS_ANODES<2>" LOC="P26";
+NET "SS_ANODES<3>" LOC="P18";
+
+NET "SS_SEGS<6>" LOC="P62";
+NET "SS_SEGS<5>" LOC="P35";
+NET "SS_SEGS<4>" LOC="P33";
+NET "SS_SEGS<3>" LOC="P53";
+NET "SS_SEGS<2>" LOC="P40";
+NET "SS_SEGS<1>" LOC="P65";
+NET "SS_SEGS<0>" LOC="P57";
+NET "SS_DP"      LOC="P23";
+
+# Joystick
+NET "BTN_UP"      LOC="P25";
+NET "BTN_DOWN"    LOC="P32";
+NET "BTN_LEFT"    LOC="P34";
+NET "BTN_RIGHT"   LOC="P36";
+NET "BTN_CENTER"  LOC="P22";
+
+# Input SW
+NET "SWITCH<7>" LOC = "P91"; # IOSTANDARD=LVTTL;
+NET "SWITCH<6>" LOC = "P92"; # | IOSTANDARD=LVTTL;
+NET "SWITCH<5>" LOC = "P94"; # | IOSTANDARD=LVTTL;
+NET "SWITCH<4>" LOC = "P95"; # | IOSTANDARD=LVTTL;
+NET "SWITCH<3>" LOC = "P98"; # | IOSTANDARD=LVTTL;
+NET "SWITCH<2>" LOC = "P2" ; # | IOSTANDARD=LVTTL;
+NET "SWITCH<1>" LOC = "P3" ; # | IOSTANDARD=LVTTL;
+NET "SWITCH<0>" LOC = "P4" ; # | IOSTANDARD=LVTTL;
+
+# LEDs
+NET "LED<0>" LOC = "P17";
+NET "LED<1>" LOC = "P16";
+NET "LED<2>" LOC = "P15";
+NET "LED<3>" LOC = "P12";
+NET "LED<4>" LOC = "P11";
+NET "LED<5>" LOC = "P10";
+NET "LED<6>" LOC = "P9";
+NET "LED<7>" LOC = "P5";
+
+# VGA
+NET "VGA_R<0>"  LOC = "P61" | IOSTANDARD=LVTTL;
+NET "VGA_R<1>"  LOC = "P58" | IOSTANDARD=LVTTL;
+NET "VGA_R<2>"  LOC = "P54" | IOSTANDARD=LVTTL;
+NET "VGA_G<0>"  LOC = "P68" | IOSTANDARD=LVTTL;
+NET "VGA_G<1>"  LOC = "P66" | IOSTANDARD=LVTTL;
+NET "VGA_G<2>"  LOC = "P63" | IOSTANDARD=LVTTL;
+NET "VGA_B<0>"  LOC = "P78" | IOSTANDARD=LVTTL;
+NET "VGA_B<1>"  LOC = "P71" | IOSTANDARD=LVTTL;
+NET "VGA_VSYNC" LOC = "P85" | IOSTANDARD=LVTTL;
+NET "VGA_HSYNC" LOC = "P83" | IOSTANDARD=LVTTL;
diff --git a/ucf/LogicStart-Pro.ucf b/ucf/LogicStart-Pro.ucf
new file mode 100644
--- /dev/null
+++ b/ucf/LogicStart-Pro.ucf
@@ -0,0 +1,64 @@
+## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration.
+CONFIG PROHIBIT=P60;
+CONFIG PROHIBIT=P69;
+CONFIG PROHIBIT=P144;
+CONFIG PART=XC6SLX9-TQG144-2;
+
+
+# Clock
+NET "CLK_32MHZ" LOC = "P94" | IOSTANDARD = LVTTL | PERIOD=31.25ns;
+
+# 7-segment display
+
+NET "SS_ANODES<0>" LOC="P85";
+NET "SS_ANODES<1>" LOC="P60";
+NET "SS_ANODES<2>" LOC="P56";
+NET "SS_ANODES<3>" LOC="P48";
+
+NET "SS_SEGS<6>" LOC="P62";
+NET "SS_SEGS<5>" LOC="P61";
+NET "SS_SEGS<4>" LOC="P58";
+NET "SS_SEGS<3>" LOC="P67";
+NET "SS_SEGS<2>" LOC="P66";
+NET "SS_SEGS<1>" LOC="P65";
+NET "SS_SEGS<0>" LOC="P75";
+NET "SS_DP"      LOC="P51";
+
+# Joystick
+NET "BTN_UP"      LOC="P50";
+NET "BTN_DOWN"    LOC="P55";
+NET "BTN_LEFT"    LOC="P57";
+NET "BTN_RIGHT"   LOC="P59";
+NET "BTN_CENTER"  LOC="P47";
+
+# Input SW
+NET "SWITCH<7>" LOC = "P114"; # IOSTANDARD=LVTTL;
+NET "SWITCH<6>" LOC = "P115"; # | IOSTANDARD=LVTTL;
+NET "SWITCH<5>" LOC = "P116"; # | IOSTANDARD=LVTTL;
+NET "SWITCH<4>" LOC = "P117"; # | IOSTANDARD=LVTTL;
+NET "SWITCH<3>" LOC = "P118"; # | IOSTANDARD=LVTTL;
+NET "SWITCH<2>" LOC = "P119" ; # | IOSTANDARD=LVTTL;
+NET "SWITCH<1>" LOC = "P120" ; # | IOSTANDARD=LVTTL;
+NET "SWITCH<0>" LOC = "P121" ; # | IOSTANDARD=LVTTL;
+
+# LEDs
+NET "LED<0>" LOC = "P134";
+NET "LED<1>" LOC = "P133";
+NET "LED<2>" LOC = "P132";
+NET "LED<3>" LOC = "P131";
+NET "LED<4>" LOC = "P127";
+NET "LED<5>" LOC = "P126";
+NET "LED<6>" LOC = "P124";
+NET "LED<7>" LOC = "P123";
+
+# VGA
+NET "VGA_R<0>"  LOC = "P78" | IOSTANDARD=LVTTL;
+NET "VGA_R<1>"  LOC = "P74" | IOSTANDARD=LVTTL;
+NET "VGA_R<2>"  LOC = "P95" | IOSTANDARD=LVTTL;
+NET "VGA_G<0>"  LOC = "P84" | IOSTANDARD=LVTTL;
+NET "VGA_G<1>"  LOC = "P82" | IOSTANDARD=LVTTL;
+NET "VGA_G<2>"  LOC = "P80" | IOSTANDARD=LVTTL;
+NET "VGA_B<0>"  LOC = "P92" | IOSTANDARD=LVTTL;
+NET "VGA_B<1>"  LOC = "P87" | IOSTANDARD=LVTTL;
+NET "VGA_VSYNC" LOC = "P99" | IOSTANDARD=LVTTL;
+NET "VGA_HSYNC" LOC = "P97" | IOSTANDARD=LVTTL;
