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 |