|
From: Pierre C. <Sup...@us...> - 2010-01-25 23:12:32
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "krobot-resources".
The branch, master has been updated
via 1e545ef9f7ae38acea030fec3f15b1c1a9fb5e58 (commit)
from 32e007d2e96e6c74fb68e0e935756940639e23e9 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 1e545ef9f7ae38acea030fec3f15b1c1a9fb5e58
Author: chambart <cha...@cr...>
Date: Tue Jan 26 00:11:47 2010 +0100
add a begining of a pong game example
-----------------------------------------------------------------------
Changes:
diff --git a/fpga/examples/pong/Makefile b/fpga/examples/pong/Makefile
new file mode 100644
index 0000000..73a6756
--- /dev/null
+++ b/fpga/examples/pong/Makefile
@@ -0,0 +1,35 @@
+PART=xc3s1200e-fg320-5
+
+XST=xst
+NGDBUILD=ngdbuild
+PAR=par
+BITGEN=bitgen
+MAP=map
+
+FILE=truc2
+UCF=pong.ucf
+
+.PHONY: all clean
+all: out.bit
+
+%.ngc : %.vhd
+ echo "run -ifn " $< " -p " $(PART) " -ofn " $@ " -opt_mode AREA -opt_level 0 -ifmt VHDL" | $(XST)
+
+pong.ngc : vga.ngc keyboard.ngc ps2.ngc draw.ngc simple_7seg.ngc game.ngc
+
+pong.ngd : pong.ngc
+ $(NGDBUILD) -p $(PART) -uc $(UCF) $<
+
+tmp.ncd : pong.ngd
+ $(MAP) -p $(PART) -o $@ $<
+
+out.ncd : tmp.ncd
+ $(PAR) -w $< $@
+
+out.bit: out.ncd
+ $(BITGEN) -w out.ncd
+
+clean:
+ rm -fr *.ncd *.ngc *.ngd *.bit *.pcf *.map *.mrp \
+ *.lso *.xml *.xrpt *.bgn *.drc *.bld *.ngm *.lst \
+ xst out* *.log *.twr xlnx_auto*
diff --git a/fpga/examples/pong/draw.vhd b/fpga/examples/pong/draw.vhd
new file mode 100644
index 0000000..57fe679
--- /dev/null
+++ b/fpga/examples/pong/draw.vhd
@@ -0,0 +1,99 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_arith.all;
+
+entity draw is
+ generic (
+ size_x : positive := 400;
+ size_y : positive := 400
+ );
+ port (
+ update : in std_logic;
+ x_pos : in integer range 0 to 639;
+ y_pos : in integer range 0 to 479;
+ ball_x : in integer range 0 to size_x - 1;
+ ball_y : in integer range 0 to size_y - 1;
+
+ color : out std_logic_vector (7 downto 0));
+
+end draw;
+
+architecture draw of draw is
+ type rom_type is array (0 to 3, 0 to 3) of integer range 0 to 3;
+ signal px : integer;
+ signal py : integer;
+ signal locx : integer range 0 to 3;
+ signal locy : integer range 0 to 3;
+ signal tmpx : natural;
+ signal tmpy : natural;
+ constant rom : rom_type :=
+ ((1,3,0,0),
+ (2,1,3,0),
+ (0,2,1,3),
+ (0,0,0,1));
+begin
+
+ px <= ball_x;
+ py <= ball_y;
+
+ tmpx <= abs (x_pos - px);
+ tmpy <= abs (y_pos - py);
+
+
+ --locx <= tmpx when tmpx <= 3 else 3;
+ --locy <= tmpy when tmpy <= 3 else 0;
+
+ --with rom(locx,locy) select
+ -- color <=
+ -- "00000000" when 0,
+ -- "11100000" when 1,
+ -- "00011100" when 2,
+ -- "00000011" when 3;
+
+ color <= "11111111" when (tmpx <= 3) and (tmpy <= 3)
+ else "00000000";
+
+--update_process: process (update)
+-- variable x : integer := 100;
+-- variable y : integer := 100;
+-- variable direction_x : std_logic := '1';
+-- variable direction_y : std_logic := '1';
+--begin
+-- if rising_edge(update) then
+-- if x >= 639 and direction_x = '1'
+-- then
+-- direction_x := '0';
+-- end if;
+-- if x <= 0 and direction_x = '0'
+-- then
+-- direction_x := '1';
+-- end if;
+-- if y >= 479 and direction_y = '1'
+-- then
+-- direction_y := '0';
+-- end if;
+-- if y <= 0 and direction_y = '0'
+-- then
+-- direction_y := '1';
+-- end if;
+
+-- if direction_x = '0' then
+-- x := x - 1;
+-- else
+-- x := x + 1;
+-- end if;
+-- if direction_y = '0' then
+-- y := y - 1;
+-- else
+-- y := y + 1;
+-- end if;
+
+-- end if;
+
+-- px <= x;
+-- py <= y;
+
+--end process update_process;
+
+end draw;
diff --git a/fpga/examples/pong/game.vhd b/fpga/examples/pong/game.vhd
new file mode 100644
index 0000000..d3da725
--- /dev/null
+++ b/fpga/examples/pong/game.vhd
@@ -0,0 +1,120 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_arith.all;
+
+entity game is
+ generic (
+ size_x : positive := 400;
+ size_y : positive := 400);
+ port (
+ clk : in std_logic;
+ scan_code : in std_logic_vector ( 7 downto 0 );
+ up_key : in std_logic;
+ extended_key : in std_logic;
+ key_int : in std_logic;
+ ball_x : out integer range 0 to size_x - 1;
+ ball_y : out integer range 0 to size_y - 1;
+ keys : out std_logic_vector ( 3 downto 0 )
+ );
+end entity game;
+
+architecture game of game is
+ signal game_clk : std_logic;
+ signal key_up : std_logic;
+ signal key_down : std_logic;
+ signal key_left : std_logic;
+ signal key_right : std_logic;
+ signal px : integer;
+ signal py : integer;
+begin
+
+ keys <= key_up & key_down & key_left & key_right;
+
+ ball_x <= px;
+ ball_y <= py;
+
+ process (key_int)
+ variable up : std_logic := '0';
+ variable down : std_logic := '0';
+ variable left_dir : std_logic := '0';
+ variable right_dir : std_logic := '0';
+ begin
+ if rising_edge(key_int) then
+ if (up_key = '0' and scan_code = "0111"&"0101" ) then
+ up := '1';
+ end if;
+ if (up_key = '1' and scan_code = "0111"&"0101" ) then
+ up := '0';
+ end if;
+ if (up_key = '0' and scan_code = "0111"&"0010" ) then
+ down := '1';
+ end if;
+ if (up_key = '1' and scan_code = "0111"&"0010" ) then
+ down := '0';
+ end if;
+ if (up_key = '0' and scan_code = "0111"&"0100" ) then
+ right_dir := '1';
+ end if;
+ if (up_key = '1' and scan_code = "0111"&"0100" ) then
+ right_dir := '0';
+ end if;
+ if (up_key = '0' and scan_code = "0110"&"1011" ) then
+ left_dir := '1';
+ end if;
+ if (up_key = '1' and scan_code = "0110"&"1011" ) then
+ left_dir := '0';
+ end if;
+ end if;
+
+ key_up <= up;
+ key_down <= down;
+ key_left <= left_dir;
+ key_right <= right_dir;
+
+ end process;
+
+
+ process (clk)
+ constant length : integer := 1_000_000;
+ variable counter : integer range 0 to length:= 0;
+ variable tmp : std_logic := '0';
+ begin
+ if rising_edge(clk) then
+ counter := counter + 1;
+ if counter = length / 2 then
+ tmp := not tmp;
+ counter := 0;
+ end if;
+ end if;
+ game_clk <= tmp;
+ end process;
+
+ update_process: process (game_clk)
+ variable x : integer := 100;
+ variable y : integer := 100;
+ begin
+ if rising_edge(game_clk) then
+
+ if key_up = '1' and y > 0 then
+ y := y - 1;
+ end if;
+ if key_down = '1' and y < size_y then
+ y := y + 1;
+ end if;
+ if key_left = '1' and x > 0 then
+ x := x - 1;
+ end if;
+ if key_right = '1' and x < size_x then
+ x := x + 1;
+ end if;
+
+ end if;
+
+ px <= x;
+ py <= y;
+
+ end process update_process;
+
+
+end architecture;
diff --git a/fpga/examples/pong/keyboard.vhd b/fpga/examples/pong/keyboard.vhd
new file mode 100644
index 0000000..88a8882
--- /dev/null
+++ b/fpga/examples/pong/keyboard.vhd
@@ -0,0 +1,57 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity keyboard is
+ port (clk : in std_logic;
+ data_in : in std_logic_vector ( 0 to 7 );
+ int_in : in std_logic;
+
+ extended : out std_logic;
+ up : out std_logic;
+ code : out std_logic_vector ( 0 to 7 );
+ int : out std_logic );
+end entity keyboard;
+
+architecture keyboard of keyboard is
+ type state_type is ( waiting, end_state );
+ signal tmp_extended, tmp_up : std_logic;
+begin
+
+process (clk)
+ variable state : state_type := end_state;
+ variable old_int_in : std_logic := '0';
+begin
+ if(rising_edge(clk))
+ then
+ case state is
+ when end_state =>
+ state := waiting;
+ int <= '0';
+ tmp_extended <= '0';
+ tmp_up <= '0';
+ when waiting =>
+ if(int_in = '1' and old_int_in = '0')
+ then
+ case data_in is
+ when "11100000" =>
+ tmp_extended <= '1';
+ state := waiting;
+ when "11110000" =>
+ tmp_up <= '1';
+ state := waiting;
+ when others =>
+ code <= data_in;
+ extended <= tmp_extended;
+ up <= tmp_up;
+ state := end_state;
+ int <= '1';
+ end case;
+ end if;
+ end case;
+
+ old_int_in := int_in;
+ end if;
+end process;
+
+end keyboard;
diff --git a/fpga/examples/pong/nexys2prog b/fpga/examples/pong/nexys2prog
new file mode 100755
index 0000000..89eb742
--- /dev/null
+++ b/fpga/examples/pong/nexys2prog
@@ -0,0 +1,345 @@
+#!/usr/bin/perl -w
+# Copyright 2009, Andrew Ross <an...@pl...>
+# Distributable under the terms of the GNU GPL licence version 2 or later.
+use strict;
+use POSIX qw(isatty);
+use Time::HiRes qw(usleep);
+
+# nexys2prog - program a Digilent Nexys 2 FPGA board over USB
+#
+# Usage: nexys2prog [-v|--verbose] <Bitstream File>
+#
+# This script automatically finds an attached Nexys 2 board and loads
+# it with the specified Xilinx bitstream with a minimum of fuss,
+# configuration, and external dependencies. Specifically, the
+# hacked/patched firmware for the Cypress FX2 chip is stored inline.
+# The user only needs user-level software installed and a single local
+# configuration change (optional, for the USB device files -- the lazy
+# can just run the script as root).
+#
+# Prerequisites:
+#
+# 1. A working Xilinx ISE installation. This was tested against 10.1,
+# but I believe older versions share the same iMPACT syntax and
+# BSDL file locations.
+#
+# 2. The "fxload" utility is required to reprogram the board's FX2 USB
+# chip, available in Debian and Ubuntu via "apt-get install
+# fxload". Note that fxload requires write access to the raw USB
+# device files under /dev/bus/usb, and that these are by default
+# read-only on Ubuntu Intrepid. You can either run the script as
+# root, or else set the files to be owned by the "plugdev" group by
+# adding the GROUP field to this line in
+# /etc/udev/rules.d/40-basic-permissions.rules:
+# SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0664", GROUP="plugdev"
+#
+# 3. UrJTAG, available from http://urjtag.org. UrJTAG is an active
+# fork of the moribund openwince-jtag project. Note that
+# openwince-jtag is still an available Debian/Ubuntu package, that
+# it shares the same "jtag" binary name and most of its syntax, and
+# that IT DOES NOT WORK with the firmware in this script. You need
+# to install UrJTAG. Also note that you will need libftdi
+# installed for the protocol handler, again available on
+# Debian/Ubuntu via "apt-get install libftdi1". UrJTAG will build
+# without this, but you won't be able to program the Nexys 2
+# without libftdi.
+#
+# Note that this script contains a binary firmware blob built from
+# free software sources. See the note above it for source
+# information.
+
+
+# TODO:
+# + Figure out the JTAG interface for the boot PROM, so it can be
+# flashed with the bitstream instead of (or in addition to) doing a
+# direct load to the FPGA.
+# + Pull down and parse the JTAG chain from the device to verify that
+# it's actually a Nexys 2 and not another device sharing the same
+# firmware family and bus ID. Kolja's firmware runs on other
+# devices too...
+# + Extend the script to recognize arbitrary JTAG chains and find the
+# appropriate part number automatically. So you'd just specify a
+# .bit file (which contains the FPGA type) and it would crawl the
+# JTAG bus looking for a matching FPGA to program.
+
+my $USBID_KOLJA = "16c0:06ad";
+my $USBID_DIGILENT = "1443:0005";
+my $XILINX;
+my $TMPID = sprintf("/tmp/nexys2prog-%8.8X-%4.4X", time(), $$);
+
+my $verbose = 0;
+my $filebase;
+my $bit;
+
+# Parse the command line
+while(@ARGV) {
+ my $arg = shift;
+ if($arg eq "-v" or $arg eq "--verbose") { $verbose = 1; }
+ elsif(!defined $bit and -f $arg and -R $arg) {
+ $bit = $arg;
+ $filebase = $bit;
+ $filebase =~ s/\.bit$//i;
+ } else { usage(); }
+}
+usage() if !defined $bit;
+
+# Find the tools
+check_tools();
+find_xilinx();
+
+# If needed, convert the .bit file to .svf using Xilinx's iMPACT tool.
+update_svf();
+
+# Locate and configure the board's USB interface
+find_board();
+
+# Do it
+play_svf();
+
+########################################################################
+
+sub usage { die "Usage:\n $0 [-v|--verbose] <Bitstream File>\n"; }
+sub vlog { print join("", @_) if $verbose; }
+
+# Idiot-proofing, to help mitigate the Rube Goldbergisms inherent in
+# this process.
+sub check_tools {
+ system("which impact >/dev/null") == 0 or die
+ ("Cannot find iMPACT executable. The Xilinx ISE development kit\n".
+ "must be installed and its settings32.sh script sourced in the\n".
+ "current shell.\n");
+ system("which jtag >/dev/null") == 0 or die
+ ("Cannot find jtag executable. The UrJTAG tools (http://urjtag.org)\n".
+ "must be built, installed, and on the PATH. You will also need to\n".
+ "install libftdi as a prerequisite: \"apt-get install libftdi-dev\" if\n".
+ "needed.\n");
+ system("jtag --version | grep UrJTAG >/dev/null") == 0 or die
+ ("Installed jtag executable is the wrong version. You probably have the\n".
+ "openwince-jtag tools installed. The Nexys2 loader requires UrJTAG\n".
+ "(http://urjtag.org) instead, which is a fork that, sadly, shares the\n".
+ "same command names. Uninstall the existing software, or (carefully!)\n".
+ "install UrJTAG such that it lives before the old tool on your PATH.\n");
+}
+
+sub find_board {
+ my $nx = find_nexys2();
+ die "Cannot find a Nexys 2 board on the USB bus. Plug it in?\n"
+ if(!defined $nx);
+ my ($bus, $dev, $id) = @$nx;
+ if($id ne $USBID_KOLJA) {
+ $dev = blasterize($bus, $dev);
+ } else {
+ vlog("Found already-configured board on bus $bus dev $dev\n");
+ }
+}
+
+sub update_svf {
+ my $svf = "$filebase.svf";
+ if((!-f $svf) or (stat($svf))[9] <= (stat($bit))[9]) {
+ vlog("Generating SVF file...\n");
+ my $impactrc = "$TMPID.impact";
+ open RC, ">$impactrc" or die "can't write to $TMPID.impact";
+ print RC "setMode -bs\n";
+ print RC "setCable -port svf -file $svf\n";
+ print RC "addDevice -p 1 -file $XILINX/xcf/data/xcf04s.bsd\n";
+ print RC "addDevice -p 2 -file $bit\n";
+ print RC "program -p 2\n";
+ print RC "closeCable\n";
+ print RC "quit\n";
+ close RC;
+ if($verbose) { system("sed 's/^/ /' $impactrc"); }
+ run("impact -batch $impactrc");
+ die "iMPACT failed to generate $svf" if ! -f $svf;
+ } else {
+ vlog("$svf is current, not regenerating.\n");
+ }
+}
+
+sub find_xilinx {
+ my $ise = `which impact`;
+ $ise = qx(cd `dirname $ise`; /bin/pwd);
+ chomp $ise;
+ die "Cannot find Xilinx ISE installation directory.\n"
+ if $ise !~ /ISE\/bin\/lin$/;
+ $ise =~ s/\/bin\/lin$//;
+ die "Cannot understand Xilinx ISE installation tree.\n"
+ if !-d "$ise/spartan3e/data" or !-f "$ise/xcf/data/xcf04s.bsd";
+ $XILINX = $ise;
+ vlog("Located Xilinx ISE installation in $XILINX.\n");
+}
+
+# Run an external tool, emitting the output only if it fails. iMPACT
+# and UrJTAG are annoyingly verbose...
+sub run {
+ my $cmd = shift;
+ print($cmd, "\n") if $verbose;
+ open CMD, "$cmd 2>&1|" or die;
+ # FIXME: if the subprocess crashes (as jtag does without a cable),
+ # we get incomplete output...
+ my $out = join "", <CMD>;
+ close CMD;
+ die "Command failure:\n $cmd\n\n$out" if $?;
+}
+
+sub find_nexys2 {
+ my ($bus, $dev, $id);
+ open LSUSB, "lsusb|" or die "Cannot run lsusb";
+ while(<LSUSB>) {
+ next if ! /Bus (\d+) Device (\d+): ID ([0-9a-f]{4}:[0-9a-f]{4})/;
+ next if !($3 eq $USBID_DIGILENT or $3 eq $USBID_KOLJA);
+ ($bus, $dev, $id) = ($1, $2, $3);
+ }
+ close LSUSB;
+ if(defined $bus) {
+ vlog("Found USB device $id on bus $bus device $dev\n");
+ return [$bus, $dev, $id];
+ }
+ return undef;
+}
+
+# Reprogram a connected FX2 device with Kolja Waschk's usb_jtag
+# firmware, patched to support the Nexys 2 pin assignments and FPGA
+# bitstream sizes as per Morgan Delahaye's instructions at
+# http://m-del.net/info.html. Uses the fxload tool from the
+# linux-hotplug project. The end result is an interface compatible
+# with the FTDI-based Altera USBBlaster product.
+sub blasterize {
+ my ($bus, $dev) = @_;
+ my $usbfile = "/dev/bus/usb/$bus/$dev";
+ if(!-w $usbfile) {
+ die ("Cannot write to $usbfile.\n\n" .
+ "Either run this tool as root or modify your udev settings to\n" .
+ "allow write access to USB device files.\n");
+ }
+ my $firmware = gen_fx2();
+ vlog("Loading 8051 firmware into board...\n");
+ run("/sbin/fxload -t fx2 -D $usbfile -I $firmware");
+ my $nx;
+ # Wait for it to reboot, renumerate and appear on the bus.
+ for(my $i=0; $i<20; $i++) {
+ usleep 10000;
+ last if defined($nx = find_nexys2()) and $nx->[2] eq $USBID_KOLJA;
+ }
+ if(!defined $nx or $nx->[2] ne $USBID_KOLJA) {
+ die ("Reprogrammed FX2 device not found on USB bus.\n",
+ "fxload failure? device unplugged? ... !?\n");
+ }
+ return $nx->[1];
+}
+
+sub play_svf {
+ open JTAG, ">$TMPID.jtag" or die "cannot write to $TMPID.jtag";
+ # Just the BSDL directories needed for the 2 chips on the Nexys2...
+ print JTAG "bsdl path $XILINX/spartan3e/data;$XILINX/xcf/data\n";
+ print JTAG "cable usbblaster\n";
+ print JTAG "detect\n";
+ print JTAG "part 1\n";
+ print JTAG "svf $filebase.svf\n";
+ print JTAG "quit\n";
+ close JTAG;
+ run("jtag $TMPID.jtag");
+}
+
+
+# Firmware for the FX2 chip
+# Original source (GPLv2) -- http://www.ixo.de/info/usb_jtag
+# Modifications:
+# hw_nexys.c -- http://www.m-del.net/files/nexys/hw_nexys2.c
+# bit_fpga.patch -- http://www.m-del.net/files/nexys/big_fpga.patch
+# It was built with the sdcc-nf ("non-free") compiler from Ubuntu 8.10
+# multiverse, and the resulting Intel hex file was filtered through
+# bzip2 and then base64 to produce the string below.
+sub gen_fx2 {
+ my $filename = "$TMPID.fx2";
+ vlog("Unpacking FX2 firmware to $filename\n");
+ open FX2, "|base64 -d | bzip2 -d > $filename"
+ or die "cannot write to $filename";
+ print FX2 <<__EOF__
+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
+__EOF__
+;
+ close FX2;
+ return $filename;
+}
+
diff --git a/fpga/examples/pong/pong.ucf b/fpga/examples/pong/pong.ucf
new file mode 100644
index 0000000..785eb95
--- /dev/null
+++ b/fpga/examples/pong/pong.ucf
@@ -0,0 +1,56 @@
+# NET "sw<0>" LOC= "G18";
+# NET "sw<1>" LOC= "H18";
+# NET "sw<2>" LOC= "K18";
+# NET "sw<3>" LOC= "K17";
+# NET "sw<4>" LOC= "L14";
+# NET "sw<5>" LOC= "L13";
+# NET "sw<6>" LOC= "N17";
+# NET "sw<7>" LOC= "R17";
+
+# NET "btn<0>" LOC= "B18"; # Bank = 1 , Pin name = IP , Type = INPUT , Sch name = BTN0
+# NET "btn<1>" LOC= "D18"; # Bank = 1 , Pin name = IP/VREF_1 , Type = VREF , Sch name = BTN1
+# NET "btn<2>" LOC= "E18"; # Bank = 1 , Pin name = IP , Type = INPUT , Sch name = BTN2
+# NET "btn<3>" LOC= "H13"; # Bank = 1 , Pin name = IP , Type = INPUT , Sch name = BTN3
+
+# Pin assignment for Leds
+# Connected to Nexys 2
+NET "Led<0>" LOC= "J14"; # Bank = 1 , Pin name = IO_L14N_1/A3/RHCLK7 , Type = RHCLK/DUAL , Sch name = JD10/LD0
+NET "Led<1>" LOC= "J15"; # Bank = 1 , Pin name = IO_L14P_1/A4/RHCLK6 , Type = RHCLK/DUAL , Sch name = JD9/LD1
+NET "Led<2>" LOC= "K15"; # Bank = 1 , Pin name = IO_L12P_1/A8/RHCLK2 , Type = RHCLK/DUAL , Sch name = JD8/LD2
+NET "Led<3>" LOC= "K14"; # Bank = 1 , Pin name = IO_L12N_1/A7/RHCLK3/TRDY1 , Type = RHCLK/DUAL , Sch name = JD7/LD3
+NET "Led<4>" LOC= "E16"; # Bank = 1 , Pin name = N.C. , Type = N.C. , Sch name = LD4? other than s3e500
+NET "Led<5>" LOC= "P16"; # Bank = 1 , Pin name = N.C. , Type = N.C. , Sch name = LD5? other than s3e500
+NET "Led<6>" LOC= "E4"; # Bank = 3 , Pin name = N.C. , Type = N.C. , Sch name = LD6? other than s3e500
+NET "Led<7>" LOC= "P4"; # Bank = 3 , Pin name = N.C. , Type = N.C. , Sch name = LD7? other than s3e500
+
+ NET "seg<0>" LOC= "L18"; # Bank = 1 , Pin name = IO_L10P_1 , Type = I/O , Sch name = CA
+ NET "seg<1>" LOC= "F18"; # Bank = 1 , Pin name = IO_L19P_1 , Type = I/O , Sch name = CB
+ NET "seg<2>" LOC= "D17"; # Bank = 1 , Pin name = IO_L23P_1/HDC , Type = DUAL , Sch name = CC
+ NET "seg<3>" LOC= "D16"; # Bank = 1 , Pin name = IO_L23N_1/LDC0 , Type = DUAL , Sch name = CD
+ NET "seg<4>" LOC= "G14"; # Bank = 1 , Pin name = IO_L20P_1 , Type = I/O , Sch name = CE
+ NET "seg<5>" LOC= "J17"; # Bank = 1 , Pin name = IO_L13P_1/A6/RHCLK4/IRDY1 , Type = RHCLK/DUAL , Sch name = CF
+ NET "seg<6>" LOC= "H14"; # Bank = 1 , Pin name = IO_L17P_1 , Type = I/O , Sch name = CG
+ NET "dp" LOC= "C17"; # Bank = 1 , Pin name = IO_L24N_1/LDC2 , Type = DUAL , Sch name = DP
+
+ NET "an<0>" LOC= "F17"; # Bank = 1 , Pin name = IO_L19N_1 , Type = I/O , Sch name = AN0
+ NET "an<1>" LOC= "H17"; # Bank = 1 , Pin name = IO_L16N_1/A0 , Type = DUAL , Sch name = AN1
+ NET "an<2>" LOC= "C18"; # Bank = 1 , Pin name = IO_L24P_1/LDC1 , Type = DUAL , Sch name = AN2
+ NET "an<3>" LOC= "F15"; # Bank = 1 , Pin name = IO_L21P_1 , Type = I/O , Sch name = AN3
+
+NET "clk" LOC= "B8"; # Bank = 0 , Pin name = IP_L13P_0/GCLK8 , Type = GCLK , Sch name = GCLK0
+
+NET "PS2C" LOC= "R12" | PULLUP; # Bank = 2 , Pin name = IO_L20N_2 , Type = I/O , Sch name = PS2C
+NET "PS2D" LOC= "P11" | PULLUP; # Bank = 2 , Pin name = IO_L18P_2 , Type = I/O , Sch name = PS2D
+
+ NET "vga_out<0>" LOC= "R9"; # Bank = 2 , Pin name = IO/D5 , Type = DUAL , Sch name = RED0
+ NET "vga_out<1>" LOC= "T8"; # Bank = 2 , Pin name = IO_L10N_2 , Type = I/O , Sch name = RED1
+ NET "vga_out<2>" LOC= "R8"; # Bank = 2 , Pin name = IO_L10P_2 , Type = I/O , Sch name = RED2
+ NET "vga_out<3>" LOC= "N8"; # Bank = 2 , Pin name = IO_L09N_2 , Type = I/O , Sch name = GRN0
+ NET "vga_out<4>" LOC= "P8"; # Bank = 2 , Pin name = IO_L09P_2 , Type = I/O , Sch name = GRN1
+ NET "vga_out<5>" LOC= "P6"; # Bank = 2 , Pin name = IO_L05N_2 , Type = I/O , Sch name = GRN2
+ NET "vga_out<6>" LOC= "U5"; # Bank = 2 , Pin name = IO/VREF_2 , Type = VREF , Sch name = BLU1
+ NET "vga_out<7>" LOC= "U4"; # Bank = 2 , Pin name = IO_L03P_2/DOUT/BUSY , Type = DUAL , Sch name = BLU2
+
+ NET "Hsync" LOC= "T4" | PULLUP; # Bank = 2 , Pin name = IO_L03N_2/MOSI/CSI_B , Type = DUAL , Sch name = HSYNC
+ NET "Vsync" LOC= "U3" | PULLUP; # Bank = 2 , Pin name = IO_L01P_2/CSO_B , Type = DUAL , Sch name = VSYNC
+
diff --git a/fpga/examples/pong/pong.vhd b/fpga/examples/pong/pong.vhd
new file mode 100644
index 0000000..e41641e
--- /dev/null
+++ b/fpga/examples/pong/pong.vhd
@@ -0,0 +1,211 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_arith.all;
+
+entity pong is
+ port (
+ clk : in std_logic;
+
+-- btn : in std_logic_vector(3 downto 0);
+ Led : out std_logic_vector(7 downto 0);
+-- usb : in std_logic;
+-- sw : in std_logic_vector(7 downto 0);
+
+ seg : out std_logic_vector(6 downto 0);
+ dp : out std_logic;
+ an : out std_logic_vector(3 downto 0);
+
+ ps2c : in std_logic;
+ ps2d : in std_logic;
+
+ vga_out : out std_logic_vector(7 downto 0);
+ hsync : out std_logic;
+ vsync : out std_logic
+ );
+end entity pong;
+
+architecture pong of pong is
+
+ component draw is
+ generic (
+ size_x : positive := 400;
+ size_y : positive := 400
+ );
+ port (
+ update : in std_logic;
+ x_pos : in integer range 0 to 639;
+ y_pos : in integer range 0 to 479;
+ ball_x : in integer range 0 to size_x - 1;
+ ball_y : in integer range 0 to size_y - 1;
+ color : out std_logic_vector (7 downto 0));
+ end component;
+
+ component vga is
+ port(clk : in std_logic;
+ hsync : out std_logic;
+ vsync : out std_logic;
+ active : out std_logic;
+ pixel_clk : out std_logic;
+ x_pos : out integer range 0 to 639;
+ y_pos : out integer range 0 to 479
+ );
+ end component;
+
+ component driver_ps2 is
+ port (clk : in std_logic;
+ ps2d : in std_logic;
+ ps2c : in std_logic;
+ data : out std_logic_vector ( 0 to 7 );
+ int : out std_logic );
+ end component;
+
+ component keyboard is
+ port (clk : in std_logic;
+ data_in : in std_logic_vector ( 0 to 7 );
+ int_in : in std_logic;
+ extended : out std_logic;
+ up : out std_logic;
+ code : out std_logic_vector ( 0 to 7 );
+ int : out std_logic );
+ end component;
+
+ component simple_7seg is
+ port(clk : in std_logic;
+ value : in std_logic_vector (15 downto 0);
+ pti : in std_logic_vector(3 downto 0);
+ seg : out std_logic_vector(6 downto 0);
+ pto : out std_logic;
+ an : out std_logic_vector(3 downto 0) );
+ end component;
+
+ component game is
+ generic (
+ size_x : positive := 400;
+ size_y : positive := 400);
+ port (
+ clk : in std_logic;
+ scan_code : in std_logic_vector ( 7 downto 0 );
+ up_key : in std_logic;
+ extended_key : in std_logic;
+ key_int : in std_logic;
+ ball_x : out integer range 0 to size_x - 1;
+ ball_y : out integer range 0 to size_y - 1;
+ keys : out std_logic_vector ( 3 downto 0 )
+ );
+ end component;
+
+ constant size_x : integer := 400;
+ constant size_y : integer := 400;
+
+ signal vga_color : std_logic_vector ( 7 downto 0 );
+ signal internal_vsync : std_logic;
+ signal vga_x : integer range 0 to 639;
+ signal vga_y : integer range 0 to 479;
+
+ signal active_output : std_logic;
+ signal pixel_clk : std_logic;
+
+-- ps2 keyboard signals
+ signal ps2_data : std_logic_vector ( 7 downto 0 );
+ signal scan_code : std_logic_vector ( 7 downto 0 );
+ signal ps2_int : std_logic;
+ signal key_up : std_logic;
+ signal key_extended : std_logic;
+ signal key_int : std_logic;
+
+ signal slow_clk : std_logic;
+ signal value_7seg : std_logic_vector ( 15 downto 0 );
+ signal point_7seg : std_logic_vector ( 3 downto 0 );
+
+-- game data
+ signal ball_x : integer range 0 to size_x - 1;
+ signal ball_y : integer range 0 to size_y - 1;
+begin
+
+ vsync <= internal_vsync;
+ vga_out <= vga_color;
+
+ draw_1 : draw
+ generic map
+ (
+ size_x,
+ size_y
+ )
+ port map
+ ( internal_vsync,
+ vga_x,
+ vga_y,
+ ball_x,
+ ball_y,
+ vga_color
+ );
+
+ game_1 : game
+ generic map (
+ size_x,
+ size_y)
+ port map (
+ clk,
+ scan_code,
+ key_up,
+ key_extended,
+ key_int,
+ ball_x,
+ ball_y,
+ led ( 3 downto 0 )
+ );
+
+ led ( 7 downto 4 ) <= "0000";
+
+ vga_1 : vga port map
+ ( clk,
+ hsync,
+ internal_vsync,
+ active_output,
+ pixel_clk,
+ vga_x,
+ vga_y
+ );
+
+ driver_ps2_1 : driver_ps2 port map
+ ( clk,
+ ps2d,
+ ps2c,
+ ps2_data,
+ ps2_int
+ );
+
+ keyboard_1 : keyboard port map
+ ( clk,
+ ps2_data,
+ ps2_int,
+ key_extended,
+ key_up,
+ scan_code,
+ key_int
+ );
+
+ simple_7seg_1 : simple_7seg port map
+ ( slow_clk,
+ value_7seg,
+ point_7seg,
+ seg,
+ dp,
+ an
+ );
+
+
+ process (clk)
+ variable count : integer range 0 to 65535 := 0;
+ variable tmp_std : std_logic_vector ( 15 downto 0 );
+ begin
+ if rising_edge(clk) then
+ count := count + 1;
+ end if;
+ tmp_std := conv_std_logic_vector(count,16);
+ slow_clk <= tmp_std(15);
+ end process;
+
+end architecture;
+
diff --git a/fpga/examples/pong/ps2.vhd b/fpga/examples/pong/ps2.vhd
new file mode 100644
index 0000000..1981c56
--- /dev/null
+++ b/fpga/examples/pong/ps2.vhd
@@ -0,0 +1,95 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity driver_ps2 is
+ port (clk : in std_logic;
+ ps2d : in std_logic;
+ ps2c : in std_logic;
+ data : out std_logic_vector ( 0 to 7 );
+ int : out std_logic );
+end entity driver_ps2;
+
+architecture driver_ps2 of driver_ps2 is
+type state_type is ( bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7,
+ bit8, bit9, end_state, error_state );
+signal tmp : std_logic_vector ( 8 downto 1 ) := "00000000";
+signal state : state_type := bit0;
+signal int_l : std_logic := '0';
+signal data_l : std_logic_vector ( 0 to 7 ) := "00000000";
+signal ps2_clk : std_logic := '1';
+signal ps2_data : std_logic := '1';
+begin
+
+process (clk)
+begin
+ if (rising_edge(clk)) then
+ ps2_clk <= ps2c;
+ end if;
+end process;
+
+process (clk)
+begin
+ if (rising_edge(clk)) then
+ ps2_data <= ps2d;
+ end if;
+end process;
+
+int <= int_l;
+data <= data_l;
+
+process (ps2_clk)
+begin
+ if (falling_edge(ps2_clk))
+ then
+ case state is
+ when bit0 =>
+ if ps2_data = '0'
+ then state <= bit1;
+ else state <= error_state;
+ end if;
+ when bit1 =>
+ state <= bit2;
+ tmp(1) <= ps2_data;
+ when bit2 =>
+ state <= bit3;
+ tmp(2) <= ps2_data;
+ when bit3 =>
+ state <= bit4;
+ tmp(3) <= ps2_data;
+ when bit4 =>
+ state <= bit5;
+ tmp(4) <= ps2_data;
+ when bit5 =>
+ state <= bit6;
+ tmp(5) <= ps2_data;
+ when bit6 =>
+ state <= bit7;
+ tmp(6) <= ps2_data;
+ when bit7 =>
+ state <= bit8;
+ tmp(7) <= ps2_data;
+ when bit8 =>
+ state <= bit9;
+ tmp(8) <= ps2_data;
+ when bit9 =>
+ state <= end_state;
+ -- tmp(9) <= ps2_data;
+ -- should verify parity
+ int_l <= '1';
+ data_l <= tmp(8 downto 1);
+ when end_state =>
+ int_l <= '0';
+ if ps2_data = '1'
+ then state <= bit0;
+ else state <= error_state;
+ end if;
+ when error_state =>
+ state <= error_state;
+ -- should make something to recover
+ end case;
+
+ end if;
+end process;
+
+end driver_ps2;
diff --git a/fpga/examples/pong/simple_7seg.vhd b/fpga/examples/pong/simple_7seg.vhd
new file mode 100644
index 0000000..32bdc6d
--- /dev/null
+++ b/fpga/examples/pong/simple_7seg.vhd
@@ -0,0 +1,97 @@
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+package decoder is
+
+ function decoder (
+ signal val : std_logic_vector (3 downto 0))
+ return std_logic_vector;
+
+end decoder;
+
+package body decoder is
+
+ function decoder (signal val : std_logic_vector(3 downto 0))
+ return std_logic_vector is
+ variable tmp : std_logic_vector ( 6 downto 0 );
+ begin
+ case val is
+ when "0000" => tmp := "0111111";
+ when "0001" => tmp := "0000110";
+ when "0010" => tmp := "1011011";
+ when "0011" => tmp := "1001111";
+ when "0100" => tmp := "1100110";
+ when "0101" => tmp := "1101101";
+ when "0110" => tmp := "1111101";
+ when "0111" => tmp := "0000111";
+ when "1000" => tmp := "1111111";
+ when "1001" => tmp := "1101111";
+ when "1010" => tmp := "1110111";
+ when "1011" => tmp := "1111100";
+ when "1100" => tmp := "0111001";
+ when "1101" => tmp := "1011110";
+ when "1110" => tmp := "1111001";
+ when "1111" => tmp := "1110001";
+ when others => tmp := "0000000"; -- shouldn't happen
+ end case;
+ return (not tmp);
+ end function decoder;
+
+end decoder;
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+use work.decoder.ALL;
+
+entity simple_7seg is
+ port(clk : in std_logic;
+ value : in std_logic_vector (15 downto 0);
+ pti : in std_logic_vector(3 downto 0);
+ seg : out std_logic_vector(6 downto 0);
+ pto : out std_logic;
+ an : out std_logic_vector(3 downto 0) );
+end simple_7seg;
+
+architecture simple_7seg of simple_7seg is
+signal selected_value : std_logic_vector ( 3 downto 0 );
+begin
+
+seg <= decoder(selected_value);
+
+process (clk)
+ variable state : std_logic_vector (3 downto 0) := "0111";
+ variable out_value : std_logic_vector (3 downto 0) := "0000";
+ variable out_pt : std_logic;
+begin
+ if rising_edge(clk) then
+ case state is
+ when "0111" =>
+ state := "1011";
+ out_value := value (15 downto 12);
+ out_pt := pti(3);
+ when "1011" =>
+ state := "1101";
+ out_value := value (11 downto 8);
+ out_pt := pti(2);
+ when "1101" =>
+ state := "1110";
+ out_value := value (7 downto 4);
+ out_pt := pti(1);
+ when others =>
+ state := "0111";
+ out_value := value (3 downto 0);
+ out_pt := pti(0);
+ end case;
+ end if;
+ an <= state;
+ selected_value <= out_value;
+ pto <= not out_pt;
+end process;
+
+end simple_7seg;
diff --git a/fpga/examples/pong/vga.vhd b/fpga/examples/pong/vga.vhd
new file mode 100644
index 0000000..9d6a2f8
--- /dev/null
+++ b/fpga/examples/pong/vga.vhd
@@ -0,0 +1,124 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+entity vga is
+ port(clk : in std_logic;
+ hsync : out std_logic;
+ vsync : out std_logic;
+ active : out std_logic;
+ pixel_clk : out std_logic;
+ x_pos : out integer range 0 to 639;
+ y_pos : out integer range 0 to 479
+ );
+end vga;
+
+architecture vga of vga is
+ signal internal_hsync : std_logic;
+ signal internal_vsync : std_logic;
+ signal internal_pixel_clk : std_logic;
+ signal h_active : std_logic;
+ signal v_active : std_logic;
+
+begin
+
+ pixel_clk <= internal_pixel_clk;
+ hsync <= internal_hsync;
+ vsync <= internal_vsync;
+ active <= '1' when ( h_active = '1' ) and ( v_active = '1' ) else '0';
+
+ pixel_clock: process (clk)
+ variable tmp : std_logic := '0';
+ begin
+ if rising_edge(clk) then
+ tmp := not tmp;
+ end if;
+ internal_pixel_clk <= tmp;
+ end process pixel_clock;
+
+ h_pixel_counter : process (internal_pixel_clk)
+ constant line_length : integer := 800;
+ constant pulse_length : integer := 96;
+ constant front_porch : integer := 16;
+ constant back_porch : integer := 48;
+ variable counter : integer range 0 to line_length + 1 := 0;
+ variable sync_state : std_logic := '1';
+ variable h_state : std_logic := '0';
+ variable x_pos_v : integer range 0 to 640 := 0;
+ begin
+ if (rising_edge(internal_pixel_clk))
+ then
+ if counter = 0 then
+ sync_state := '0';
+ x_pos_v := 0;
+ end if;
+ if counter = pulse_length then
+ sync_state := '1';
+ end if;
+
+ if h_state = '1' then
+ x_pos_v := x_pos_v + 1;
+ end if;
+
+ if counter = front_porch + pulse_length then
+ h_state := '1';
+ end if;
+ if counter = line_length - back_porch then
+ h_state := '0';
+ end if;
+
+ counter := counter + 1;
+ if counter = line_length then
+ counter := 0;
+ end if;
+ end if;
+
+ internal_hsync <= sync_state;
+ h_active <= h_state;
+ x_pos <= x_pos_v;
+ end process h_pixel_counter;
+
+ v_pixel_counter : process (internal_hsync)
+ constant line_length : integer := 521;
+ constant pulse_length : integer := 2;
+ constant front_porch : integer := 10;
+ constant back_porch : integer := 29;
+ variable counter : integer range 0 to line_length + 1 := 0;
+ variable sync_state : std_logic := '1';
+ variable v_state : std_logic := '0';
+ variable y_pos_v : integer range 0 to 480 := 0;
+ begin
+ if (falling_edge(internal_hsync))
+ then
+ if counter = 0 then
+ sync_state := '0';
+ y_pos_v := 0;
+ end if;
+ if counter = pulse_length then
+ sync_state := '1';
+ end if;
+
+ if v_state = '1' then
+ y_pos_v := y_pos_v + 1;
+ end if;
+
+ if counter = pulse_length + front_porch then
+ v_state := '1';
+ end if;
+ if counter = line_length - back_porch then
+ v_state := '0';
+ end if;
+
+ counter := counter + 1;
+ if counter = line_length then
+ counter := 0;
+ end if;
+ end if;
+
+ internal_vsync <= sync_state;
+ v_active <= v_state;
+ y_pos <= y_pos_v;
+ end process v_pixel_counter;
+
+end vga;
hooks/post-receive
--
krobot-resources
|