OpenCores
URL https://opencores.org/ocsvn/openarty/openarty/trunk

Subversion Repositories openarty

[/] [openarty/] [trunk/] [doc/] [src/] [spec.tex] - Diff between revs 36 and 48

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 36 Rev 48
Line 36... Line 36...
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%%
%%
%%
\usepackage{import}
\usepackage{import}
\usepackage{bytefield}
\usepackage{bytefield}
 
\usepackage{listings}
\project{OpenArty}
\project{OpenArty}
\title{Specification}
\title{Specification}
\author{Dan Gisselquist, Ph.D.}
\author{Dan Gisselquist, Ph.D.}
\email{dgisselq (at) opencores.org}
\email{dgisselq (at)  ieee.org}
\revision{Rev.~0.0}
\revision{Rev.~0.0}
\begin{document}
\begin{document}
\pagestyle{gqtekspecplain}
\pagestyle{gqtekspecplain}
\titlepage
\titlepage
\begin{license}
\begin{license}
Line 63... Line 64...
with this program.  If not, see \texttt{http://www.gnu.org/licenses/} for a copy.
with this program.  If not, see \texttt{http://www.gnu.org/licenses/} for a copy.
\end{license}
\end{license}
\begin{revisionhistory}
\begin{revisionhistory}
0.0 &  6/20/2016 & Gisselquist & First Draft \\\hline
0.0 &  6/20/2016 & Gisselquist & First Draft \\\hline
0.0 & 10/21/2016 & Gisselquist & More Comments Added\\\hline
0.0 & 10/21/2016 & Gisselquist & More Comments Added\\\hline
 
0.0 & 11/18/2016 & Gisselquist & Added a getting started section\\\hline
\end{revisionhistory}
\end{revisionhistory}
% Revision History
% Revision History
% Table of Contents, named Contents
% Table of Contents, named Contents
\tableofcontents
\tableofcontents
\listoffigures
\listoffigures
Line 76... Line 78...
 
 
\chapter{Introduction}\label{ch:intro}
\chapter{Introduction}\label{ch:intro}
\pagenumbering{arabic}
\pagenumbering{arabic}
\setcounter{page}{1}
\setcounter{page}{1}
 
 
 
At {\$ 99}, the Arty is a very economical FPGA platform for doing
 
a lot of things.  It was designed to support the MicroBlaze soft CPU platform,
 
and as a result it has a lot more memory plus ethernet support.  Put together,
 
it feels like it was designed for soft--core CPU development.  Indeed, it has
 
an amazing capability for its price.
 
 
 
Instructions and examples for using the Arty, however, tend to focus on
 
schematic design development techniques.  While these may seem like an
 
appropriate way to introduce a beginner to hardware design, these techniques
 
introduce a whole host of problems.
 
 
 
The first and perhaps biggest problem is that it can be difficult to trouble
 
shoot what is going on.  This is a combination of two factors.  The first is
 
that many of the reference schematic designs make use of proprietary IP.  In
 
an effort to protect both their IP and themselves, companies providing such
 
IP resources often make them opaque, and difficult to see the internals of.
 
As a result, it can be difficult to understand why that IP isn't working in
 
your design.  Further, while many simulation tools exist, only the Xilinx tools
 
will allow full simulation of Xilinx proprietary IP.  Finally, while it may be
 
simple to select a part and ``wire'' it up within a schematic, most IP
 
components have many, many configuration options which are then hidden from the
 
user within the simplified component.  These options may be the difference
 
between successfully using the component and an exercise in frustration.
 
Put together, all of these features of schematic design make the design more
 
difficult to troubleshoot, and often even impossible to troubleshoot using
 
open source tools such as Verilator.
 
 
 
Another problem is that schematic based designs often hide their FPGA resource
 
usage.  They can easily become resource hogs, leaving the designer unaware
 
of the consequences of what he/she is implementing.  As an example, the memory
 
interface generated by Xilinx's Memory Interface Generator (MIG) consumes
 
nearly a full quarter of the Arty's FPGA resources, while delaying responses
 
to requests by upwards of 250~ns.  Further, while Xilinx touts its MicroBlaze
 
processor as only using 800--2500 LUTs, the MicroBlaze architecture requires
 
it be connected to four separate AXI busses, with each of those having
 
five channels, all with their requests and acknowledgement flags.  These
 
can therefore easily consume all of the resources within an architecture, before
 
providing any of the benefit the designer was looking for when they chose to
 
use an FPGA.
 
 
 
 
% What is old
% What is old
%       Arty, XuLA
%       Arty, XuLA, Learnables using schematic drawing techniques
% What does the old lack?
% What does the old lack?
%       Arty lacks open interfaces, instead using MIG and CoreGen w/ AXI bus
%       Arty lacks open interfaces, instead using MIG and CoreGen w/ AXI bus
% What is new
% What is new
%       OpenArty has its own memory interface controller, and runs everything
%       OpenArty has its own memory interface controller, and runs everything
%       off of an open Wishbone bus structure.
%       off of an open Wishbone bus structure.
% What does the new have that the old lacks
% What does the new have that the old lacks
%
%
% What performance gain can be expected?
% What performance gain can be expected?
%
%
 
 
The goals of this project include:
Here in this project, we present another alternative.
 
 
 
First, the OpenArty is entirely built in Verilog, and (with the exception of
 
the MIG controller), it is entirely buit out of OpenSource IP.\footnote{I'm
 
still hoping to place an open memory controller into this design.  This
 
controller is written in logic, but does not yet connect to any hardware ports.}
 
 
 
Second, configuration options, such as cache sizes, can be fine tuned via a
 
CPU options file.
 
 
 
Third, as you will find from examining the RTL sources, this project uses only
 
one bus, and that bus has ony one channel associated with it: a Wishbone Bus.
 
This helps to limit the logic associated with trying to read and write from
 
the CPU, although it may increase problems with fanout.
 
 
 
Finally, because the OpenArty project is made from open source components, the
 
entire design, together with several of its peripherals, can be simulated using
 
Verilator.  This makes it possible to run programs on the ZipCPU within the
 
OpenArty design, and find and examine where such programs (or their peripherals)
 
fail.
 
 
 
Overall, the goals of this OpenArty project include:
\begin{enumerate}
\begin{enumerate}
\item Use entirely open interfaces
\item Use entirely open interfaces
 
 
        This means not using the Memory Interface Generator (MIG), the
        This means not using the Memory Interface Generator (MIG), the
        Xilinx CoreGen IP, etc.  Further, I wish to use all of Arty's on--board
        Xilinx CoreGen IP, etc.
        hardware: Flash, DDR3-SDRAM, Ethernet, and everything else at their
 
        full and fastest speed(s).  For example, the flash will need to be
 
        clocked at 82~MHz, not the 50~MHz I've clocked it at before.  The
 
        memory should also be able to support pipelined 32--bit interactions
 
        over the Wishbone bus at a 162~MHz clock.  Finally, the Ethernet
 
        controller should be supported by a DMA capable interface that can
 
        drive the ethernet at its full 100Mbps rate.
 
 
 
\item Run using a 162.5~MHz clock, if for no other reason than to gain the
        (This goal has not yet been achieved.)
        experience of building logic that can run that fast.\footnote{The
 
 
\item Use all of Arty's on--board hardware: Flash, DDR3-SDRAM, Ethernet, and
 
        everything else at their full and fastest speed(s).  For example, the
 
        flash will need to be clocked at 82~MHz, not the 50~MHz I've clocked
 
        it at in previous projects.  The DDR3 SDRAM memory should also be able
 
        to support pipelined 32--bit interactions over the Wishbone bus at a
 
        162~MHz clock.  Finally, the Ethernet controller should be supported
 
        by a DMA capable interface that can drive the ethernet at its full
 
        100Mbps rate.
 
 
 
        (Of these, only the ethernet goal has been met.)
 
 
 
\item Run using a 162.5~MHz system clock, if for no other reason than to gain
 
        the experience of building logic that can run that fast.\footnote{The
        original goal was to run at 200~MHz.  However, the memory controller
        original goal was to run at 200~MHz.  However, the memory controller
        cannot run faster than 83~MHz.  If we run it at 81.25~MHz and double
        cannot run faster than about 82~MHz.  If we run it at 81.25~MHz and
        that clock to get our logic clock, that now places us at 162.5~MHz.
        double that clock to get our logic clock, that now places us at
        200~MHz is \ldots too fast for DDR3 transfers using the Artix--7 chip
        162.5~MHz.  200~MHz is \ldots too fast for DDR3 transfers using the
        on the Arty.}
        Artix--7 chip on the Arty.}
 
 
 
        While the wishbone bus has been upgraded so that it may run at
 
        200~MHz, the CPU and memory controller cannot handle this speed (yet).
 
 
\item Modify the ZipCPU to support an MMU and a data cache, and perhaps even
\item Modify the ZipCPU to support an MMU and a data cache, and perhaps even
        a floating point unit.
        a floating point unit.
 
 
\item The default configuration will also include three Pmods: a USBUART,
        (These are still in development.)
        an SDCard, and the GPS Pmod.
 
 
\item The default configuration will also include four Pmods: a USBUART,
 
        a GPS, an SDCard, and an OLEDrgb.
 
 
 
        (These have all been tested, and are known to work.)
\end{enumerate}
\end{enumerate}
 
 
I intend to demonstrate this project with a couple programs:
I intend to demonstrate this project with a couple programs:
\begin{enumerate}
\begin{enumerate}
\item NTP Server
\item An NTP Server
\item A ZipOS that can actually load and run programs from the SD Card
 
 
        While the GPS tracking circuit is in place, and while it appears to be
 
        able to track a GPS signal to within about 100ns or so, the
 
        network stack has yet to be built.
 
 
 
\item A ZipOS that can actually load and run programs from the SD Card, rather
 
        than just a static memory image stored in flash on start-up.
 
 
        This will require a functioning memory management unit (MMU), which
        This will require a functioning memory management unit (MMU), which
        will be a new addition to the ZipCPU created to support this project.
        will be a new addition to the ZipCPU created to support this project.
 
 
        For those not familiar with MMU's, an MMU translates memory addresses
        For those not familiar with MMU's, an MMU translates memory addresses
        from a virtual address space to a physical address space.  This allows
        from a virtual address space to a physical address space.  This allows
        every program running on the ZipCPU to believe that they own the entire
        every program running on the ZipCPU to believe that they own the entire
        memory address space, while allowing the operating system to allocate
        memory address space, while allowing the operating system to allocate
        actual physical memory addresses as necessary to support whatever
        actual physical memory addresses as necessary to support whatever
        program needs more (or less) memory.
        program needs more (or less) memory.
 
 
 
        At this point, the MMU has been written and has passed its bench
 
        testing phase.  It has not (yet) been integrated with the CPU.
\end{enumerate}
\end{enumerate}
 
 
 
 
 
\chapter{Getting Started}\label{ch:getting-started}
 
\section{Building the Core}
 
%
 
\section{Building the board support files}
 
The OpenArty project comes with a series of board support programs that are
 
designed to run from a Linux command line.  The C++ source code for these
 
programs can be found in the sw/host directory.  These programs have two
 
dependencies: the ZipCPU load program depends upon libelf, and the ZipCPU
 
debugger depends upon the ncurses library.  If you have these two libraries,
 
your build should proceed without problems.
 
 
 
% TODO: Remove the dependency on ZIPD.
 
 
 
A make in the sw/host directory should build all of these support programs.
 
These include:
 
\begin{itemize}
 
\item {\tt wbregs}: a program to read and write addresses on the wishbone bus,
 
        and hence to test peripherals independent of the CPU.
 
\item {\tt netuart}: a program to convert the UART device provided by the board
 
        to a TCP/IP device that can be connected to anywhere.
 
\item {\tt wbsettime}: a simple program to set the time on the real-time clock
 
        core within the board.
 
\item {\tt dumpflash}: reads the current contents from the flash memory into a
 
        local file
 
\item {\tt wbprogram}: programs new configuations into the flash
 
\item {\tt netsetup}: reads and decodes the MDIO interface from the ethernet
 
        PHY controller
 
\item {\tt manping}: pings a computer using the ethernet packet interface.
 
        This program does not have any ARP handling, so while it will wait
 
        for a reply, the reply typically comes back in the form of an ARP
 
        request rather than the ping response.
 
\item {\tt zipload}: Loads a program onto the ZipCPU, adjusting flash, block
 
        RAM, and or SDRAM memory to do so.  May also start the program running
 
        if requested.
 
\item {\tt zipstate}: Returns information about whether or not the CPU is
 
        running, is running in user mode, is waiting for an interrupt,
 
        has halted, etc.
 
\item {\tt zipdbg}: a debugger with the capability to halt, reset and step
 
        the CPU, as well as to inspect the state of the CPU following any
 
        unexpected halt.
 
\end{itemize}
 
 
 
 
 
 
 
\section{Initially installing the core}
 
The OpenArty core may be installed onto the board via the Xilinx Hardware
 
Manager.  If properly set up, you should be able to open the hardware
 
manager after you build an initial bit stream, open the Arty, select the
 
toplevel bit file, and request Xilinx to load the file.
 
 
 
If you are successful, the four color LEDs will blank while the hardware
 
manager is loading the hardware, and then turn to varying intensities of red.
 
 
 
\section{Connecting the PMods}
 
The OpenArty project is designed to work with four PMods: PModUSBUART,
 
PModGPS, PModSD, and PModOLEDrgb.  These four provide the device with
 
serial port access, absolute time and position information, access to an
 
SD card, and the ability to control a small display.
 
 
 
If you do not have any of these devices, and wish to recover the logic used
 
by them, you may comment out the defines for {\tt GPS\_CLOCK},
 
{\tt SDCARD\_ACCESS}, and {\tt OLEDRGBACCESS} found in the {\tt rtl/busmaster.v}
 
file.  This will recover all but the logic used by the PModUSBUART and PModGPS
 
serial ports, while replacing the registers with read--only memory values of
 
zero.
 
 
 
 
 
\section{Testing the peripherals}
 
OpenArty has been designed so that all of the peripherals live on a
 
memory--mapped wishbone bus.  This bus can be accessed, either by the ZipCPU
 
or by the host controller.  Because of this model, peripherals may be tested
 
and known to work before the CPU is ever turned on.  Two programs make this
 
possible: netuart and wbregs.  Other programs may be built upon this model,
 
as long as they access the bus using the interface outlined in devbus.h.
 
 
 
Of the two programs, netuart simply turns the USB serial port interface of
 
the device into a TCP/IP interface.  Netuart takes one argument, the
 
name of the serial port device which the Arty USB driver has created.  In
 
my case, this tends to be /dev/ttyUSB1, although it has been known to change
 
from time to time:
 
 
 
\begin{lstlisting}[language=bash]
 
% netuart /dev/ttyUSB1
 
\end{lstlisting}
 
 
 
All of the other board support files connect to the TCP/IP port generated
 
by netuart.  The port.h file is a compiled-in file, outlining where this
 
port can be found.  By default, netuart listens to port {\tt 6510} on
 
{\tt localhost}, but it can be configured to listen to any port.  The other
 
board support files will try to connect to netuart at the host and port
 
listed in port.h.  Hence, if properly configured, you should be able to
 
access your Arty to command it, configure it, reload it, etc., from anywhere
 
you have internet access--in my case, from anywhere in the house.
 
 
 
Once you run netuart, you should then be able to watch, as a part of the
 
standard output stream of netuart, all of the interaction with the board.
 
While this may be useful for debugging, it's not all that legible to the
 
user.   Lines that start with \hbox{``\#''} are lines from the device that are not
 
going to any client.  A common line you will see is \hbox{``\# 0''}.  This is
 
just the device saying that its command capability is idle.  Lines that start
 
with \hbox{``< ''} are commands going to the device, and lines starting with
 
\hbox{``> ''} are responses from the core.  So, at this point, run netuart and
 
wait a couple of seconds.  If you do not see a \hbox{``\# 0''} line, then try a
 
different serial port, check that your core is properly configured, etc.  Once
 
you do see a \hbox{``\# 0''} line, then you are ready for the next step.
 
 
 
The easiest way to test the peripherals is via the wbregs command.  This
 
command is similar to the ancient peek and poke commands.  It takes one
 
or two arguments.  If given one argument, it reads from that address on the
 
bus.  If given two arguments, it writes the value of the second argument to
 
the bus location given by the first argument.  Hence one argument peeks
 
at the memory bus, two arguments pokes a value onto the memory bus.
 
 
 
Perhaps an example will help.  At this point, try typing:
 
 
 
\begin{lstlisting}[language=bash]
 
% wbregs version
 
\end{lstlisting}
 
 
 
This should return and print a 32-bit hexadecimal value to your screen,
 
indicating the date of when you last ran make in the root directory before
 
building and installing your configuration into the device.  This can be
 
very useful to know what configuration you are running, and whether or not
 
you have made the changes you thought you had made.
 
 
 
You may have noticed that wbregs read from address 0x0100, but did so by name.
 
Most of the peripherals have names for their addresses.  The C language
 
names for these addresses can be found in regdefs.h, and a mapping to
 
wbregs address names can be found in regdefs.cpp.
 
 
 
Shall we try another?  Let's try adjusting the LEDs.  To turn all the LEDs off,
 
\begin{lstlisting}[language=bash]
 
% wbregs leds 0x0f0
 
\end{lstlisting}
 
To turn them all back on again,
 
\begin{lstlisting}[language=bash]
 
% wbregs leds 0x0ff
 
\end{lstlisting}
 
To turn the low order LED off without changing any others, write
 
\begin{lstlisting}[language=bash]
 
% wbregs leds 0x010
 
\end{lstlisting}
 
 
 
Having fun?  Try running the program startupex.sh from the sw directory.
 
This will set some LEDs and Color LEDs in a fun, startup--looking, pattern.
 
 
 
Ready to test the UART?   Using minicom, connect to the PModUSBUART.  It
 
should also be connected to a /dev/ttyUSBx serial port device.  If you aren't
 
sure, start minicom with:
 
\begin{lstlisting}[language=bash]
 
% minicom -D /dev/ttyUSB2
 
\end{lstlisting}
 
Then, configure minicom to use 115,200 Baud, 8-data bits, one stop bit, and
 
no parity.
 
 
 
Once you've done that, we can test it by sending a character across the UART
 
port:
 
\begin{lstlisting}[language=bash]
 
% wbregs tx 90
 
\end{lstlisting}
 
This should send a `Z' over the UART port.  Did you see a `Z' in minicom?
 
If not, did you set the baud rate right?  The UART is supposed to be set
 
for 115,200 Baud, 8N1 by default.  If not, you can set it to that by writing
 
wbregs setup 705.  The 705 comes from the clock rate, in Hz, divided by
 
115200.  By leaving other higher order bits at zero, this becomes the default
 
baud rate of an 8N1 serial port channel.
 
 
 
Another fun program to run is {\tt netsetup}.  This program takes no arguments,
 
and just reads and decodes the network registers via the MDIO port.  The
 
decoded result will be sent to the screen.
 
 
 
\section{Subsequent Core Updates}
 
The board support file {\tt wbprogram} can be used to write .bit or .bin
 
files to the flash, so that the core can be updated once an initial core
 
is installed and running.
 
Although wbprogram expects the filename to end in either '.bit' or '.bin',
 
this is primarily to keep a user from doing something they don't intend to
 
do.
 
 
 
The basic usage of the wbprogram command is:
 
\begin{lstlisting}[language=bash]
 
% wbprogram [@address] file
 
\end{lstlisting}
 
wbprogram then copies the file to the flash, starting at the Arty address
 
of {\tt @address}.  If no address is given, wbprogram writes the file at the
 
beginning of flash.
 
 
 
An example of how to do this can be found in the {\tt program.sh}.
 
{\tt program.sh} places the new configuration file into the alternate
 
configuration location.  (An alternate script, zprog.sh, places the new
 
configuration at the beginning of the flash, where the FPGA loader will look
 
for it upon power up.)  Once {\tt program.sh} places the new configuration
 
into flash, it then commands the FPGA via the ICAPE2 interface and an IPROG
 
command to reconfigure itself using this new configuration.  As a result, this
 
can be used to load subsequent configurations into the FLASH.
 
 
 
\section{Building the ZipCPU tool-chain}
 
At this point, you should have some confidence that your configuration and
 
hardware are working.  Therefore, let's transition to getting the ZipCPU
 
on the hardware up and running.  To do this, we'll start with getting a copy
 
of the ZipCPU toolchain and building it.  Pick a directory to work in, and
 
then issue:
 
\begin{lstlisting}[language=bash]
 
% git clone https://github.com/ZipCPU/zipcpu
 
\end{lstlisting}
 
to get a copy of the ZipCPU project, together with toolchain, and then
 
in the master directory, type:
 
\begin{lstlisting}[language=bash]
 
% cd zipcpu; make
 
\end{lstlisting}
 
(you may need to issue the make command a couple of times \ldots)
 
 
 
This will build the GCC compiler for the ZipCPU from source.
 
It will also install this new compiler into the zipcpu/sw/install/cross-tools.
 
This new compiler will be called zip-gcc.
 
 
 
This will also build a copy of the binutils programs for the ZipCPU.  These
 
include the assembler, {\tt zip-gas}, linker, {\tt zip-ld}, disassembler,
 
{\tt zip-objdump}, and many more useful programs.
 
 
 
The next step to using this toolchain is to place it into your path.
 
\begin{lstlisting}[language=bash]
 
% export PATH=$PATH:$PWD/zipcpu/install/cross-tools/bin
 
\end{lstlisting}
 
Once the toolchain is in your path,
 
\begin{lstlisting}[language=bash]
 
% which zip-gcc
 
/home/.../zipcpu/sw/install/cross-tools/bin/zip-gcc
 
\end{lstlisting}
 
should return the location of where this toolchain exists in your path.
 
 
 
\section{Building your first ZipCPU program}
 
Several example programs for the OpenArty project can be found in the
 
{\tt sw/board} directory.  These can be used to test various peripherals from
 
the perspective of the CPU itself.
 
 
 
As a test of the build process, a good first progam to build would be
 
{\tt exstartup}.  This program is very similar to the {\tt startupex.sh} shell
 
script you tried earlier.  It simply plays with the color LEDs and some
 
on board timers.   Once that is finished, it goes into a loop controlling
 
both the normal and the color LEDs based upon the button state and the switch
 
settings.
 
 
 
To build {\tt exstartup}, simply type {\tt make exstartup} from the
 
{\tt sw/board} directory of the {\tt openarty} project.  (Don't forget to
 
include the ZipCPU toolchain into your path before you do this!)
 
 
 
\section{Loading a program}
 
Now that you have built your {\tt exstartup} program, it's time to load it
 
onto the board and start it up.  The {\tt zipload} program can be used to
 
do this.  {\tt zipload} can be found in the sw/host directory.  To load a
 
ZipCPU program into the Arty, just type {\tt zipload} and the program name,
 
such as {\tt exstartup} in this case.  To start the program immediately
 
after loading it, pass the `-r' option to {\tt zipload}.  In our case, you
 
would type:
 
\begin{lstlisting}[language=bash]
 
% zipload -r exstartup
 
\end{lstlisting}
 
 
 
Hopefully, you can see the {\tt exstartup} program now toggling the LED's.
 
Once the initial display stops, you can adjust the switches and press buttons
 
to see how that affects the result.
 
 
 
If you wish to restart the {\tt exstartup} program, or indeed to run another
 
program, you can just run {\tt zipload} again with the new program name.  This
 
will halt the previous program, and then load the new one into memory.  As
 
before, if you use the `-r' option, the program will be started automatically.
 
 
 
\section{Some other test programs}
 
If you have the PModUSBUART, you might wish to try running a ``Hello, World''
 
program.  This can be found in the hello.c file.  It prints ``Hello, World''
 
to the PModUSBUART once every ten seconds.  Had enough of it?  You can stop
 
the CPU by typing {\tt wbregs cpu 0x0400}.  This sends a halt command to the
 
debug register of the ZipCPU.  More information about this debug register, and
 
other things that can be done via the debug register, can be found in the
 
ZipCPU specification.
 
 
 
If you have both the PModUSBUART as well as the PModGPS, the {\tt gpsdump.c}
 
program can be used to forward the NMEA stream from the GPS to the USBUART.
 
This should give you some confidence that the PModGPS is working.
 
 
 
As a third test, {\tt oledtest.c} will initialize the OLEDrgb device and cause
 
it to display one of two images in an alternating fashion.
 
 
\chapter{Architecture}\label{ch:architecture}
\chapter{Architecture}\label{ch:architecture}
My philosophy in peripherals is to keep them simple.  If there is a default
My philosophy in peripherals is to keep them simple.  If there is a default
mode on the peripheral, setting that mode should not require turning any bits
mode on the peripheral, setting that mode should not require turning any bits
on.  If a peripheral encounters an error condition, a bit may be turned on to
on.  If a peripheral encounters an error condition, a bit may be turned on to
Line 502... Line 870...
\subsection{Scheduler}
\subsection{Scheduler}
 
 
\chapter{Operation}\label{ch:operation}
\chapter{Operation}\label{ch:operation}
 
 
\chapter{Registers}\label{ch:registers}
\chapter{Registers}\label{ch:registers}
There are several address regions on the S6~SoC, as shown in
There are several address regions within the {\tt OpenArty}, as shown in
Tbl.~\ref{tbl:memregions}.
Tbl.~\ref{tbl:memregions}.
\begin{table}[htbp]
\begin{table}[htbp]
\begin{center}\begin{tabular}{|p{2.25in}|p{0.6in}|p{0.45in}|p{2.0in}|}\hline
\begin{center}\begin{tabular}{|p{2.25in}|p{0.6in}|p{0.45in}|p{2.0in}|}\hline
\rowcolor[gray]{0.85} Binary Address & Base & Size(W) & Purpose \\\hline\hline
\rowcolor[gray]{0.85} Binary Address & Base & Size(W) & Purpose \\\hline\hline
\scalebox{0.9}{\tt 0000 0000 0000 0000 0001 000x xxxx} & \scalebox{0.9}{\tt 0x00000100} & \hfill 32 & Peripheral I/O Control \\\hline
\scalebox{0.9}{\tt 0000 0000 0000 0000 0001 000x xxxx} & \scalebox{0.9}{\tt 0x00000100} & \hfill 32 & Peripheral I/O Control \\\hline
Line 534... Line 902...
\scalebox{0.9}{\tt 01xx xxxx xxxx xxxx xxxx xxxx xxxx} & \scalebox{0.9}{\tt 0x04000000} & \hfill 64M & DDR3 SDRAM\\\hline
\scalebox{0.9}{\tt 01xx xxxx xxxx xxxx xxxx xxxx xxxx} & \scalebox{0.9}{\tt 0x04000000} & \hfill 64M & DDR3 SDRAM\\\hline
\scalebox{0.9}{\tt 1000 0000 0000 0000 0000 0000 000x} & \scalebox{0.9}{\tt 0x08000000} & \hfill 2 & ZipCPU debug control port---only visible to debug WB master\\\hline
\scalebox{0.9}{\tt 1000 0000 0000 0000 0000 0000 000x} & \scalebox{0.9}{\tt 0x08000000} & \hfill 2 & ZipCPU debug control port---only visible to debug WB master\\\hline
\end{tabular}
\end{tabular}
\caption{Address Regions}\label{tbl:memregions}
\caption{Address Regions}\label{tbl:memregions}
\end{center}\end{table}
\end{center}\end{table}
 
These address regions include both read and write memory regions, such as the
 
block RAM, the SDRAM, and the Ethernet TX buffer, as well as read only memory
 
regions, such as the flash memory and the Ethernet RX buffer, as well as a
 
whole lot of memory mapped peripherals.  The purpose of this chapter will be
 
to describe how these memory mapped peripherals are organized, as well as
 
the specific details of how they may be used.
 
 
 
This address map information is also contained in a couple other locations.
 
First, {\tt sw/host/regdefs.h} maps all of the OpenArty registers to
 
C++ names, whereas {\tt sw/host/regdefs.cpp} maps these C++ names to a more
 
human readable form which is used by {\tt wbregs}.  Second, these registers
 
are also given names as part of several various structures within
 
{\tt sw/board/artyboard.h}.  And then, of course, they are also listed here.
 
 
 
\section{ZipSystem}
 
The ZipSystem wrapper around the ZipCPU provides access to roughly twenty
 
registers that are tightly integrated with the ZipCPU.  These registers are
 
shown in Tbl.~\ref{tbl:zipio}
\begin{table}[htbp]
\begin{table}[htbp]
\begin{center}\begin{tabular}{|p{0.9in}|p{0.45in}|p{3.5in}|}\hline
\begin{center}\begin{tabular}{|p{0.9in}|p{0.45in}|p{3.5in}|}\hline
\rowcolor[gray]{0.85} Base & Size(W) & Purpose \\\hline\hline
\rowcolor[gray]{0.85} Base & Size(W) & Purpose \\\hline\hline
\scalebox{0.9}{\tt 0x0c0000000} & 1 & Primary Zip PIC\\\hline
\scalebox{0.9}{\tt 0xc0000000} & 1 & Primary Zip PIC\\\hline
\scalebox{0.9}{\tt 0x0c0000001} & 1 & Watchdog Timer\\\hline
\scalebox{0.9}{\tt 0xc0000001} & 1 & Watchdog Timer\\\hline
\scalebox{0.9}{\tt 0x0c0000002} & 1 & Bus Watchdog Timer\\\hline
\scalebox{0.9}{\tt 0xc0000002} & 1 & Bus Watchdog Timer\\\hline
\scalebox{0.9}{\tt 0x0c0000003} & 1 & Alternate Zip PIC\\\hline
\scalebox{0.9}{\tt 0xc0000003} & 1 & Alternate Zip PIC\\\hline
\scalebox{0.9}{\tt 0x0c0000004} & 1 & ZipTimer-A\\\hline
\scalebox{0.9}{\tt 0xc0000004} & 1 & ZipTimer-A\\\hline
\scalebox{0.9}{\tt 0x0c0000005} & 1 & ZipTimer-B\\\hline
\scalebox{0.9}{\tt 0xc0000005} & 1 & ZipTimer-B\\\hline
\scalebox{0.9}{\tt 0x0c0000006} & 1 & ZipTimer-C\\\hline
\scalebox{0.9}{\tt 0xc0000006} & 1 & ZipTimer-C\\\hline
\scalebox{0.9}{\tt 0x0c0000007} & 1 & ZipJiffies\\\hline
\scalebox{0.9}{\tt 0xc0000007} & 1 & ZipJiffies\\\hline
\scalebox{0.9}{\tt 0x0c0000008} & 1 & Master task counter\\\hline
\scalebox{0.9}{\tt 0xc0000008} & 1 & Master task counter\\\hline
\scalebox{0.9}{\tt 0x0c0000009} & 1 & Master prefetch stall counter\\\hline
\scalebox{0.9}{\tt 0xc0000009} & 1 & Master prefetch stall counter\\\hline
\scalebox{0.9}{\tt 0x0c000000a} & 1 & Master memory stall counter\\\hline
\scalebox{0.9}{\tt 0xc000000a} & 1 & Master memory stall counter\\\hline
\scalebox{0.9}{\tt 0x0c000000b} & 1 & Master instruction counter\\\hline
\scalebox{0.9}{\tt 0xc000000b} & 1 & Master instruction counter\\\hline
\scalebox{0.9}{\tt 0x0c000000c} & 1 & User task counter\\\hline
\scalebox{0.9}{\tt 0xc000000c} & 1 & User task counter\\\hline
\scalebox{0.9}{\tt 0x0c000000d} & 1 & User prefetch stall counter\\\hline
\scalebox{0.9}{\tt 0xc000000d} & 1 & User prefetch stall counter\\\hline
\scalebox{0.9}{\tt 0x0c000000e} & 1 & User memory stall counter\\\hline
\scalebox{0.9}{\tt 0xc000000e} & 1 & User memory stall counter\\\hline
\scalebox{0.9}{\tt 0x0c000000f} & 1 & User instruction counter\\\hline
\scalebox{0.9}{\tt 0xc000000f} & 1 & User instruction counter\\\hline
\scalebox{0.9}{\tt 0x0c0000010} & 1 & DMA command register\\\hline
\scalebox{0.9}{\tt 0xc0000010} & 1 & DMA command register\\\hline
\scalebox{0.9}{\tt 0x0c0000011} & 1 & DMA length\\\hline
\scalebox{0.9}{\tt 0xc0000011} & 1 & DMA length\\\hline
\scalebox{0.9}{\tt 0x0c0000012} & 1 & DMA source address\\\hline
\scalebox{0.9}{\tt 0xc0000012} & 1 & DMA source address\\\hline
\scalebox{0.9}{\tt 0x0c0000013} & 1 & DMA destination address\\\hline
\scalebox{0.9}{\tt 0xc0000013} & 1 & DMA destination address\\\hline
\scalebox{0.9}{\tt 0x0c0000040} & 1 & {\em Reserved for MMU context register}\\\hline
\scalebox{0.9}{\tt 0xc0000040} & 2 & {\em Reserved for MMU context register}\\\hline
\scalebox{0.9}{\tt 0x0c0000080} & 32 & {\em Reserved for MMU TLB}\\\hline
\scalebox{0.9}{\tt 0x0c0000080} & 32 & {\em Reserved for MMU TLB}\\\hline
\end{tabular}
\end{tabular}
\caption{ZipSystem Addresses}\label{tbl:zipio}
\caption{ZipSystem Addresses}\label{tbl:zipio}
\end{center}\end{table}
\end{center}\end{table}
 
and described in detail within the ZipCPU specification.
 
 
 
Unlike the rest of the address map, these registers are only visible to the
 
ZipCPU.  While many of them may be read via the debug port, in general accessing
 
these registers via the {\tt wbregs} command is not so straight forward.
 
 
\section{Peripheral I/O Control}
\section{Peripheral I/O Control}
Tbl.~\ref{tbl:ioregs}
The first section of memory--mapped I/O for the ZipCPU is found near address
 
{\tt 0x100}.  These peripherals are specifically peripherals that can be
 
accessed without ever stalling the bus, and with a known and fixed (minimum)
 
delay.  Tbl.~\ref{tbl:ioregs}
\begin{table}[htbp]
\begin{table}[htbp]
\begin{center}\begin{reglist}
\begin{center}\begin{reglist}
VERSION  &\scalebox{0.8}{\tt 0x0100} & 32 & R & Build date\\\hline
VERSION  &\scalebox{0.8}{\tt 0x0100} & 32 & R & Build date\\\hline
PIC      &\scalebox{0.8}{\tt 0x0101} & 32 & R/W & Bus Interrupt Controller \\\hline
PIC      &\scalebox{0.8}{\tt 0x0101} & 32 & R/W & Bus Interrupt Controller \\\hline
BUSERR   &\scalebox{0.8}{\tt 0x0102} & 32 & R & Last Bus Error Address\\\hline
BUSERR   &\scalebox{0.8}{\tt 0x0102} & 32 & R & Last Bus Error Address\\\hline
Line 583... Line 976...
GPIO     &\scalebox{0.8}{\tt 0x010d} & 32 & R/W & {\em Reserved for} GPIO controller\\\hline
GPIO     &\scalebox{0.8}{\tt 0x010d} & 32 & R/W & {\em Reserved for} GPIO controller\\\hline
UARTRX   &\scalebox{0.8}{\tt 0x010e} & 32 & R/W & Aux UART receive byte\\\hline
UARTRX   &\scalebox{0.8}{\tt 0x010e} & 32 & R/W & Aux UART receive byte\\\hline
UARTTX   &\scalebox{0.8}{\tt 0x010f} & 32 & R/W & Aux UART transmit byte\\\hline
UARTTX   &\scalebox{0.8}{\tt 0x010f} & 32 & R/W & Aux UART transmit byte\\\hline
GPSRX    &\scalebox{0.8}{\tt 0x0110} & 32 & R/W & GPS UART receive byte\\\hline
GPSRX    &\scalebox{0.8}{\tt 0x0110} & 32 & R/W & GPS UART receive byte\\\hline
GPSTX    &\scalebox{0.8}{\tt 0x0111} & 32 & R/W & GPS UART transmit byte\\\hline
GPSTX    &\scalebox{0.8}{\tt 0x0111} & 32 & R/W & GPS UART transmit byte\\\hline
GPSSECS  &\scalebox{0.8}{\tt 0x0110} & 32 & R/W & {\em Reserved for a one-up seconds counter}\\\hline
GPSSECS  &\scalebox{0.8}{\tt 0x0112} & 32 & R/W & {\em Reserved for a one-up seconds counter}\\\hline
GPSSUB   &\scalebox{0.8}{\tt 0x0110} & 32 & R/W & GPS PPS tracking subsecond info\\\hline
GPSSUB   &\scalebox{0.8}{\tt 0x0113} & 32 & R/W & GPS PPS tracking subsecond info\\\hline
GPSSTEP  &\scalebox{0.8}{\tt 0x0111} & 32 & R/W & Current GPS step size, units TBD\\\hline
GPSSTEP  &\scalebox{0.8}{\tt 0x0114} & 32 & R/W & Current GPS step size, units TBD\\\hline
% 0x010c-0x010f
% 0x010c-0x010f
\end{reglist}
\end{reglist}
\caption{I/O Peripheral Registers}\label{tbl:ioregs}
\caption{I/O Peripheral Registers}\label{tbl:ioregs}
\end{center}\end{table}
\end{center}\end{table}
shows the addresses of various I/O peripherals included as part of the SoC.
shows the addresses of these I/O peripherals included as part of OpenArty.
We'll walk through each of these peripherals in turn, describing how they work.
We'll walk through each of these peripherals in turn, describing how they work.
 
 
 
\subsection{Version}
 
One of the simpler peripherals on the board is the {\tt VERSION} peripheral.
 
This simple returns the date stamp found within {\tt rtl/builddate.v}.  This
 
stamp is updated any time a {\tt make} command is issued in the main OpenArty
 
project directory.  Reads from this address return this value, writes to this
 
address are ignored.
 
 
 
This peripheral is {\em very} useful, especially when trying to determine which
 
version of your configuration you are using, and whether or not the
 
configuration has been changed or updated as you had intended by loading a new
 
configuration, by writing a configuration to the flash and issuing an IPROG
 
command, etc.
 
 
\subsection{Interrupt Controller}
\subsection{Interrupt Controller}
The OpenArty design maintains three interrupt controllers.  Two of them
The OpenArty design maintains three interrupt controllers.  Two of them
are found within the ZipSystem, and the third is located on the bus
(a primary and an auxiliary) are found within the ZipSystem, and the third is
itself.  Of these, the primary interrupt controller is located in the ZipSystem.
located on the bus itself.  In terms of functionality, all three interrupt
This interrupt controller accepts, as interrupt inputs, the outputs of both
controllers are the same, and documented in the ZipCPU specification.  Of
the auxilliary interrupt controller as well as the bus interrupt controller.
these, the primary interrupt controller for the
Hence, even though the CPU only supports a single interrupt line, by using
entire design is the primary interrupt controller within the ZipSystem.
these three interrupt controllers many more interrupts can be supported.
This interrupt controller accepts as inputs, the output of the auxilliary
 
interrupt controller.
 
Hence, even though the CPU only supports a single interrupt line, by cascading
 
it with a second controller, many more interrupts can be supported.
 
 
 
The third interrupt controller is the bus interrupt controller.  While the
 
CPU can read and write this controller, the interrupt line from this controller
 
goes to the host interface.  If you see, as an example, an \hbox{``> 4''} in
 
your {\tt netuart} window, then you will know that OpenArty has sent an
 
interrupt to a waiting host program.  If what you saw instead was a
 
\hbox{``\# 4''}, then the interrupt was sent, but no one was listening.
 
 
The primary interrupt controller handles interrupts from the sources listed
The primary interrupt controller handles interrupts from the sources listed
in Tbl.~\ref{tbl:sys-ints}.  These interrupts are listed together with the
in Tbl.~\ref{tbl:sys-ints}.
mask that would need to be used when referencing them to the interrupt
 
controller.  In a similar fashion, the auxilliary interrupt controller accepts
 
inputs from the sources listed in Tbl.~\ref{tbl:aux-ints}.  Finally, the
 
bus interrupt controller handles the interrupts from the sources listed in
 
Tbl.~\ref{tbl:bus-ints}.
 
 
 
\begin{table}[htbp]
\begin{table}[htbp]
\begin{center}\begin{tabular}{|p{0.9in}|p{0.75in}|p{0.75in}|p{3.00in}|}\hline
\begin{center}\begin{tabular}{|p{0.9in}|p{0.75in}|p{0.75in}|p{3.00in}|}\hline
\rowcolor[gray]{0.85} Name & Bit Mask & DMAC ID &Description \\\hline\hline
\rowcolor[gray]{0.85} Name & Bit Mask & DMAC ID &Description \\\hline\hline
SYS\_DMAC   & 0x0001 && The DMA controller is idle.\\\hline
SYS\_DMAC   & 0x0001 && The DMA controller is idle.\\\hline
SYS\_JIF    & 0x0002 & 1 & A Jiffies timer has expired.\\\hline
SYS\_JIF    & 0x0002 & 1 & A Jiffies timer has expired.\\\hline
Line 633... Line 1043...
SYS\_SDCARD & 0x2000 & 13 & The SD-Card controller has become idle\\\hline
SYS\_SDCARD & 0x2000 & 13 & The SD-Card controller has become idle\\\hline
SYS\_OLED   & 0x4000 & 14 & The OLED port is idle\\\hline
SYS\_OLED   & 0x4000 & 14 & The OLED port is idle\\\hline
\end{tabular}
\end{tabular}
\caption{Primary System Interrupts}\label{tbl:sys-ints}
\caption{Primary System Interrupts}\label{tbl:sys-ints}
\end{center}\end{table}
\end{center}\end{table}
%%%%%%%%%%%%%
These interrupts are listed together with the
 
mask that would need to be used when referencing them to the interrupt
 
controller.  In a similar fashion, the auxilliary interrupt controller accepts
 
inputs from the sources listed in Tbl.~\ref{tbl:aux-ints}.
\begin{table}[htbp]
\begin{table}[htbp]
\begin{center}\begin{tabular}{|p{0.9in}|p{0.75in}|p{0.75in}|p{3.00in}|}\hline
\begin{center}\begin{tabular}{|p{0.9in}|p{0.75in}|p{0.75in}|p{3.00in}|}\hline
\rowcolor[gray]{0.85} Name & Bit Mask & DMAC ID &Description \\\hline\hline
\rowcolor[gray]{0.85} Name & Bit Mask & DMAC ID &Description \\\hline\hline
AUX\_UIC & 0x0001 & 16 & The user instruction counter has overflowed.\\\hline
AUX\_UIC & 0x0001 & 16 & The user instruction counter has overflowed.\\\hline
AUX\_UPC & 0x0002 & 17 & The user prefetch stall counter has overflowed.\\\hline
AUX\_UPC & 0x0002 & 17 & The user prefetch stall counter has overflowed.\\\hline
Line 655... Line 1068...
AUX\_SCOPE  & 0x1000 & 28 & The Scope has completed its collection\\\hline
AUX\_SCOPE  & 0x1000 & 28 & The Scope has completed its collection\\\hline
AUX\_GPIO   & 0x2000 & 29 & The GPIO input lines have changed values.\\\hline
AUX\_GPIO   & 0x2000 & 29 & The GPIO input lines have changed values.\\\hline
\end{tabular}
\end{tabular}
\caption{Auxilliary System Interrupts}\label{tbl:aux-ints}
\caption{Auxilliary System Interrupts}\label{tbl:aux-ints}
\end{center}\end{table}
\end{center}\end{table}
 
These interrupt mask constants are also defined in {\tt sw/board/artyboard.h}
 
and {\tt sw/board/zipsys.h}.
 
 
 
Finally, the bus interrupt controller handles the interrupts from the sources
 
listed in Tbl.~\ref{tbl:bus-ints}.
\begin{table}[htbp]
\begin{table}[htbp]
\begin{center}\begin{tabular}{|p{0.9in}|p{0.75in}|p{3.75in}|}\hline
\begin{center}\begin{tabular}{|p{0.9in}|p{0.75in}|p{3.75in}|}\hline
\rowcolor[gray]{0.85} Name & Bit Mask & Description \\\hline\hline
\rowcolor[gray]{0.85} Name & Bit Mask & Description \\\hline\hline
BUS\_BUTTON & 0x0001 & A Button has been pressed. \\\hline
BUS\_BUTTON & 0x0001 & A Button has been pressed. \\\hline
BUS\_SWITCH & 0x0002 & The Scope has completed its collection\\\hline
BUS\_SWITCH & 0x0002 & The Scope has completed its collection\\\hline
Line 682... Line 1099...
BUS\_OLED   & 0x2000 & The OLED interface has become idle\\\hline
BUS\_OLED   & 0x2000 & The OLED interface has become idle\\\hline
BUS\_ZIP    & 0x4000 & True if the ZipCPU has come to a halt\\\hline
BUS\_ZIP    & 0x4000 & True if the ZipCPU has come to a halt\\\hline
\end{tabular}
\end{tabular}
\caption{Bus Interrupts}\label{tbl:bus-ints}
\caption{Bus Interrupts}\label{tbl:bus-ints}
\end{center}\end{table}
\end{center}\end{table}
 
You may notice that there is a lot of overlap between these interrupt sources.
 
That is so that the host can also receive many of the same interrupts the ZipCPU
 
can receive.
 
 
\subsection{Last Bus Error Address}
\subsection{Last Bus Error Address}
 
Should an attempt be made to access a non--existant memory address, or should
 
multiple devices all return their data at the same time on the bus, a bus
 
error will be created.  When and if this happens, the address on the bus
 
when this error was created will be placed into the last bus error address.
 
This is the only way to set this address.
 
 
 
\subsection{Power counter}
 
Some peripherals may require a certain amount of time from power up or startup
 
until they can be accessed.  Guaranteeing this amount of time is the purpose
 
of the power counter.  This simple read only register simply counts up from
 
zero on every clock, with the exception that once the high order bit is set
 
then it is never cleared.
 
 
 
\subsection{Button and Switch Register}
 
btn-now / 4'h0 / btncfg / swcfg / btnstate / swstate
 
The button and switch register includes a variety of fields for reading the
 
current state of the buttons and switches, and for controlling the two related
 
interrupts.  The register is separated into several fields, however, as shown
 
in Fig.~\ref{fig:btnsw}.
 
\begin{figure}\begin{center}\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31}\\
 
\bitbox{8}{\em Ignored}
 
\bitbox{4}{BNOW}
 
\bitbox{4}{4'h0}
 
\bitbox{4}{BCFG}
 
\bitbox{4}{SCFG}
 
\bitbox{4}{BTN}
 
\bitbox{4}{SW}
 
\end{bytefield}
 
\caption{Button/Switch register layout}\label{fig:btnsw}
 
\end{center}\end{figure}
 
The current state of the buttons and switches can be read through the {\tt BNOW}
 
and {\tt SW} bit--fields.
 
 
 
The {\tt BTN} field contains one bit per button.  When a button is pressed,
 
the respective bit in this field will be set.  It will then remain set until
 
cleared.  To clear a value in this bit--field, write a `1' to the position you
 
wish to clear.
 
 
 
Then {\tt BCFG} field controls which buttons will trigger a button interrupt.
 
Should a button be pressed while its corresponding value within this field
 
is a `1', a button interrupt pulse will be issued.  To set a bit within this
 
field, you need to not only write the corresponding bit value, but you must
 
also set an enable bit within the {\tt BTN} field.  Hence, writing a
 
{\tt 0x0f0f0} will set all of the bits within this field, while {\tt 0x0f000}
 
will have no effect, and {\tt 0x0030} will clear two bits.  Notice also that,
 
when clearing a button press from the {\tt BTN} bits, the corresponding
 
{\tt BCFG} bits will also be cleared.
 
 
 
Finally, the {\tt SCFG} field controls whether or not changing a switch value
 
will cause an interrupt.  As with the {\tt BCFG} field, changing a value
 
in this register requires writing to the {\tt SW} field as an enable.
 
 
 
The use of the enable bit--field lines was added so that reads and writes to
 
this register wouldn't need special atomic access protections, so that some
 
configuration bits could be changed without setting all of them, and so that
 
changes during writes wouldn't go unnoticed.
 
 
 
\subsection{LED control register}
 
The LED control register has a layout similar and enable field similar to that
 
of the button/switch control register.  These fields can be seen in
 
Fig.~\ref{fig:ledctrl}
 
\begin{figure}\begin{center}\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31}\\
 
\bitbox{24}{\em Ignored}
 
\bitbox{4}{ENB}
 
\bitbox{4}{LED}
 
\end{bytefield}
 
\caption{LED control register layout}\label{fig:ledctrl}
 
\end{center}\end{figure}
 
The bottom four {\tt LED} bits of this register will always contain the current
 
state of the LEDs.  To change an LED's state, write to this register the new
 
state with the corresponding {\tt ENB} (enable) bit set.  Hence writing a
 
{\tt 0x0c0} will turn off LED's two and three, while writing a {\tt 0x033} will
 
set LED's zero and one, and writing a {\tt 0x0f} will be ignored.
 
 
 
\subsection{UART setup registers}
 
There are two UART setup registers: one for controlling the PModUSBUART setup
 
and the other for controlling the PMod GPS NMEA UART.  These follow the format
 
given in the {\tt wbuart32} project, with a bit field shown in
 
Fig.~\ref{fig:uartsetup}.
 
\begin{figure}\begin{center}\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31}\\
 
\bitbox{2}{00}
 
\bitbox{2}{N}
 
\bitbox{1}{S}
 
\bitbox{1}{P}
 
\bitbox{1}{F}
 
\bitbox{1}{T}
 
\bitbox{24}{Clocks per Baud}
 
\end{bytefield}
 
\caption{UART setup register format}\label{fig:uartsetup}
 
\end{center}\end{figure}
 
In general, the only control needed to set these registers is to set their
 
baud rate based upon the number of clocks per baud.  Hence, to set a
 
9600~baud rate, given an 82.5~MHz clock rate, one would set this register to
 
{\tt 8594}.  The high order bits are designed so that writing a zero to them
 
sets the interface for 8--data bits, no parity, and one stop bit.
 
 
 
The number of data bits may be adjusted by changing the $N$ field from zero,
 
for eight data bits, on up to three, for five data bits.
 
 
 
The $S$ bit determines whether or not the system will insert and require an
 
extra stop bit.  Setting it to zero sets the system to require only a single
 
stop bit.
 
 
 
The $P$ bit controls whether or not parity is enabled, and the $F$ bit controls
 
whether or not the parity is fixed.  $T$ controls what type of parity is then
 
used.  By setting $P$ to zero, parity checking and generation is turned off.
 
 
 
Finally, the auxiliary UART (i.e. the PMod USBUART) defaults to 115,200 Baud,
 
8N1, whereas the GPS UART defaults to 9600 Baud, 8N1.  Both may be adjusted
 
via this register.
 
 
 
\subsection{Color LED registers}
 
 
 
Since the Arty has four color LEDs, the OpenArty has four register words to
 
control those LEDs.  These registers are split into three bit fields, an
 
8--bit red, 8--bit green, and an 8--bit blue bit field.  The top eight bits
 
are ignored.  Unlike many of the other OpenArty registers, these bit fields
 
may be read or written with no special enable values.
 
 
 
\subsection{RTC date register}
 
The real--time--clock date register format is shown in Fig.~\ref{fig:rtcdate}.
 
\begin{figure}\begin{center}\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31}\\
 
\bitbox{16}{Year}
 
        \bitbox{8}{Month}
 
        \bitbox{8}{Day}\\
 
\bitbox{4}{Y}
 
        \bitbox{4}{Y} \bitbox{4}{Y} \bitbox{4}{Y}
 
\bitbox{4}{M} \bitbox{4}{M}
 
\bitbox{4}{D} \bitbox{4}{D}\\
 
\end{bytefield}
 
\caption{RTC Date register layout}\label{fig:rtcdate}
 
\end{center}\end{figure}
 
This is also a very simple register, containing eight binary coded decimal
 
(BCD) digits.  Due to the nature of this setup, the date can be read quickly
 
from the hexadecimal value of the register, and dates can be compared validly
 
to determine if a date is earlier or later than any other.  Writes to the
 
date register will set the date, otherwise the date will automatically
 
increment whenever the Real Time Clock rolls over into the next day.
 
 
 
Unlike the Linux {\tt ctime} system call, the month value ranges from
 
one to twelve.  The day of the month ranges from 1~to 31, or whatever is
 
appropriate for the current month.
 
 
\subsection{General Purpose I/O}
\subsection{General Purpose I/O}
\subsection{UART Data Register}
% TODO
 
The General Purpose I/O controller will be the same as the controller from the
 
S6~SoC once installed.
 
 
 
\subsection{UART Data Registers}
 
Each of the two UARTs, PMod USBUART and PMod GPS, has two data registers and
 
two interrupts associated with it: one for receive and one for transmit.
 
As with the rest of the Arty I/O design, these are designed so that unused
 
extra bits will be zero, and can (usually) quietly be ignored.
 
 
 
The receive UART register format is shown in Fig.~\ref{fig:rxuart}.
 
\begin{figure}\begin{center}\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31}\\
 
\bitbox{20}{\em Always zero}
 
\bitbox{1}{B} \bitbox{1}{F} \bitbox{1}{P} \bitbox{1}{I}
 
\bitbox{8}{Data}\\
 
\end{bytefield}
 
\caption{Receive UART register layout}\label{fig:rxuart}
 
\end{center}\end{figure}
 
This register may only be read, writes are silently ignored.  If no receive
 
value is present, the $I$ bit will be set.  If either a parity error, $P$, or
 
frame error (stop bit not high), $F$, have occurred, those respective bits will
 
be high.  The error bits are cleared upon successfully receiving a word across
 
the interface.  Finally, the $B$ bit indicates the line is in a {\tt BREAK}
 
condition.
 
 
 
The interface has been designed for one of two means of accessing it.  The
 
interface may be polled.  In that case, anding the result with {\tt 0x0f00}
 
will tell whether the result is invalid.  The interface may also be read upon
 
a receive interrupt.  In that case, the same bit fields apply, but the $I$ bit
 
will be guaranteed to be low.  Finally, the interrupt line will continue
 
generating an interrupt input to the interrupt controller until it has been
 
read.  Therefore, handling receive UART interrupts requires reading the receive
 
data and then resetting the interrupt controller.  This also means, though, that
 
the receive port should work quite well with the DMA controller.
 
 
 
As currently implemented, neither transmit nor receive UARTs have attached
 
FIFOs.  Hence, once a value is ready to be read, it must be read before the
 
next value is available to be read.
 
 
 
The transmit UART register is shown in Fig.~\ref{fig:txuart}.
 
\begin{figure}\begin{center}\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31}\\
 
\bitbox{20}{\em Always zero}
 
        \bitbox{1}{R}
 
        \bitbox{1}{O}
 
        \bitbox{1}{B}
 
        \bitbox{1}{S}
 
        \bitbox{8}{Data}\\
 
\end{bytefield}
 
\caption{Transmit UART register layout}\label{fig:txuart}
 
\end{center}\end{figure}
 
Of these bits, the data register is the most important.  Writes to the transmit
 
UART, with only the bottom eight bits set, will send those bits out the
 
data port.  Writes with the $B$, or {\tt BREAK} bit, set will place the
 
transmitter into a {\tt BREAK} condition.  This condition is only cleared by
 
writing with the $B$ bit clear.  The $S$ bit is a read-only busy bit, true if
 
the device is still busy sending the last character.  Finally, the $R$ and $O$
 
bits reflect the current value read on the receive port and the current value
 
being placed onto the transmit port respectively.
 
 
 
As with the receive register, the transmit register has been designed to either
 
be used in a polling or interrupt fashion.  When polled, the $S$ bit may be
 
checked to determine if the transmitter is still busy sending the last
 
character.  When the $S$ bit is clear, the UART transmitter will be responsive
 
to another character written to it.  In interrupt mode, the device will
 
constantly trigger an interrupt into the interrupt controller whenever  it is
 
idle.  As with the receive, the only way to reset this interrupt is to send
 
a character and then reset the bit in the interrupt controller.
 
 
 
\subsection{System seconds counter}
 
As part of tracking the current time, it is important to have an accurate
 
seconds counter that increments with every second.  That's what this register
 
provides.  This plus the subsecond register should be the current time.
 
 
 
The problem is setting this register.  While the subsecond time register can be
 
set using the PPS signal from the GPS, this seconds register will need to be
 
calculated from the NMEA data stream.  To make this work, this register has been
 
set up so that not only does it increment by one on the top of any second, but
 
when written to the register will be bumped by whatever value is written to it.
 
Hence, to step it forward by a second, write a {\tt 32'h1} to it.  To step it
 
backwards, write a {\tt 32'hffffffff}.
 
 
 
\subsection{GPS Subsecond time}
 
As part of being able to provide highly accurate time resolution, it is
 
important to be able to read the current time at any given time.  This
 
register provides the sub--seconds value associated with the current time.
 
It is specifically the amount of time since the top of the last second
 
times $2^{32}$.  As such, it rolls over at the top of each second.  The
 
top bit can be used as an indication of the second half of the second, etc.
 
 
 
\subsection{GPS derived clock step}
 
This 32--bit value is closely related to the sytem clock frequency.  It is a
 
{\tt step} value designed so that a $2^{48}$ bit counter, incremented by this
 
{\tt step} value on every clock tick, will roll over after one second.  To
 
convert this to the GPS derived clock frequency, apply the formula:
 
\begin{eqnarray}
 
f_{\mbox{\tiny CLK}} &=& \frac{2^{48}}{\mbox{\tt STEP}}
 
\end{eqnarray}
 
 
\section{Debugging Scopes}
\section{Debugging Scopes}
\section{Internal Configuration Access Port}
 
\section{Real--Time Clock}
\section{Real--Time Clock}
\section{On-Chip Block RAM}
% TODO write something more meaningful
 
The real--time clock controller is part of the {\tt rtcclock} project which
 
should also be found near this distribution.  The manual for that project
 
should describe the four registers, clock, timer, stopwatch, and alarm, that
 
can be controlled herein.
 
 
 
\section{SD Card controller}
 
% TODO write something more meaningful
 
The SD card controller is part of the {\tt sdspi} project which
 
should also be found near this distribution.  The manual for that project
 
should describe the four registers, control, data, and the two FIFO's registers,
 
that can be controlled herein.
 
 
 
\section{GPS PPS Tracking Loop control}
 
The coefficients for the PLL that tracks the GPS PPS can be controlled via the
 
registers listed in Tbl.~\ref{tbl:gpsctrl}.
 
\begin{table}
 
\begin{center}\begin{reglist}
 
alpha  &\scalebox{0.8}{\tt 0x0130} & 8 & R/W & Recursive Error Averaging Coefficient\\\hline
 
beta   &\scalebox{0.8}{\tt 0x0131} & 32 & R/W & Phase Tracking Coefficient\\\hline
 
gamma  &\scalebox{0.8}{\tt 0x0132} & 32 & R/W & Frequency Tracking Coefficient\\\hline
 
defstep&\scalebox{0.8}{\tt 0x0133} & 32 & R/W & Default clock step\\\hline
 
\end{reglist}
 
\caption{GPS PPS Tracking Control Registers}\label{tbl:gpsctrl}
 
\end{center}\end{table}
 
 
 
\section{GPS testbench info}
 
 
 
The GPS PPS tracking core found within the Arty was originally tested using
 
a GPS testbench.  Since simulation and performance measurement was a chalelnge,
 
that testbench has been given a permanent place within the Arty.  Within it,
 
there are eight registers, grouped into five variables.  These registers are
 
designed so that, if read in a burst fashion, none of the registers will
 
change during the burst--guaranteeing their coherency.
 
 
 
The first two registers will be ignored, unless specifically enabled by
 
defining {\tt GPSTB} in busmaster.v.  They are designed to see how the
 
GPS tracking circuit will respond to an absolutely accurate input.  The
 
first, the {\tt tb\_maxcount} value, sets the number of clocks per simulated
 
PPS tick.  The second, the {\tt tb\_jump} value, when written to will cause
 
the PPS to suddenly be displaced in phase by the value written.  Both of these
 
are ignored unless the test bench was configured to produce a simulated
 
PPS signal.
 
 
 
The third register is the 64--bit error.  Specifically, this is the value of
 
the GPS step counter at the top of the second.  In a perfect world, with
 
perfect tracking, it should be zero.  In a wonderful world with nearly perfect
 
tracking, this register should be less than the GPS step size.
 
 
 
The fourth register is the 64--bit count register.  This indicates the current
 
time, in 64--bit precision.  The top 32--bits of this register are the same
 
as the sub--seconds register presented earlier.
 
 
 
The final register is the 64--bit step register.  This register is very similar
 
to the 32--bit {\tt STEP} register discussed earlier.  It is designed so that,
 
when multiplied by the clock frequency in Hertz, the result should equal
 
$2^{64}$.  The register, though, captures the current state of the GPS tracking
 
circuit's estimate of the clock speed of the processor in this fashion.
 
 
 
\section{OLEDrgb control}
 
The OLEDrgb can be controlled by four registers, listed in
 
Tbl.~\ref{tbl:oledctrl}.
 
\begin{table}
 
\begin{center}\begin{reglist}
 
CTRL &\scalebox{0.8}{\tt 0x0130} & 32 & R/W & Control register\\\hline
 
REGA &\scalebox{0.8}{\tt 0x0131} & 32 & R/W & First excess control word\\\hline
 
REGB &\scalebox{0.8}{\tt 0x0132} & 32 & R/W & Second excess control word\\\hline
 
DATA &\scalebox{0.8}{\tt 0x0133} & 32 & R/W & Data and power register\\\hline
 
\end{reglist}
 
\caption{OLED Control Registers}\label{tbl:oledctrl}
 
\end{center}\end{table}
 
The first three are used to send information across the control port of the
 
OLEDrgb, the last is used to adjust the power, reset, and I/O line voltage,
 
as well as to send data values to the device.
 
 
 
Unlike the flash, network MDIO registers, or ICAPE port, reads and writes
 
of this device will not stall the wishbone bus, and will complete immediately.
 
Commands issued to the device while the controller is busy will therefore be
 
quietly ignored.
 
 
 
Working with the device starts by powering it up.  This sequence is given
 
by the manufacturer, and it requires the use of data register.  This data
 
register has one of two interpretations, as shown in Fig.~\ref{fig:odata}.
 
\begin{figure}\begin{center}\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31}\\
 
        \bitbox{16}{16'h00}
 
        \bitbox{16}{Data}\\
 
\bitbox{13}{13'h00}
 
        \bitbox{1}{R} \bitbox{1}{V} \bitbox{1}{E}
 
        \bitbox{13}{13'h00}
 
        \bitbox{1}{R} \bitbox{1}{V} \bitbox{1}{E} \\
 
\end{bytefield}
 
\caption{OLED data register: Data write format, and power control read/write format}\label{fig:odata}
 
\end{center}\end{figure}
 
In the first interpretation, data may be sent to the port by simply
 
writing that data to the port, while leaving the top sixteen bits zero.
 
(We'll get to this later.)  In the second interpretation, the reset and
 
power bits may be adjusted by setting the upper bit high (an enable bit),
 
together with the corresponding lower bit to the value desired.
 
 
 
The $R$ bit will be zero if the device is in a reset state (an active low
 
reset).  The $V$ bit is one if the VCC output is enabled.  The $E$ bit is one
 
if the PMod is enabled, otherwise the power to the PMod is cut.  Adjusting
 
these bits requires writing a `1' to the bit you wish to change, and then
 
at the same time writing the value you wish to change it to in the lower order
 
bits.  Hence writing a {\tt 0x010001} to the device will turn the power on,
 
whereas a {\tt 0x010000} will turn it off.  Likewise {\tt 0x040000} will place
 
the device into reset (active low), and {\tt 0x040004} will release the reset
 
line.
 
 
 
Reads from this port simply return the current values of the $R$, $V$, and
 
$E$ bits in the least significant 3--bits.
 
 
 
The power--up sequence for the device is shown below:
 
\begin{enumerate}
 
\item Wait a quarter second from configuration start
 
\item Power up the device, writing a {\tt 0x050005} to the data port to
 
        power up, but without setting the reset line yet.
 
\item Wait four microseconds.
 
\item Activate the reset line, by writing a {\tt 0x040000} to this data port.
 
\item Wait another four microseconds.
 
\item Clear the reset, by writing a {\tt 0x040004} to this data port.
 
\item Wait another four microseconds.
 
\item Initialize the display.
 
\end{enumerate}
 
 
 
At this point, a series of commands need to be sent to the devices control
 
port.  These commands are written to the control register.  The control
 
register accepts several different types of writes, as shown in
 
Fig.~\ref{fig:octrl}.
 
\begin{figure}\begin{center}\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31}\\
 
        \bitbox{24}{24'h00}
 
        \bitbox{8}{8'data}\\
 
\bitbox{15}{15'h00}\bitbox{1}{1}\bitbox{16}{16'data} \\
 
\bitbox{4}{4'h2}\bitbox{4}{}\bitbox{24}{24'data} \\
 
\bitbox{4}{N-1}\bitbox{4}{}\bitbox{24}{24'data} \\
 
\end{bytefield}
 
\caption{Four separate OLED control register write formats}\label{fig:octrl}
 
\end{center}\end{figure}
 
To send a single byte of data, write that byte to the control port.
 
Two bytes require setting bit sixteen, and they are sent high order byte first.
 
Sending three or more bytes requires setting the number of bytes you wish to
 
send, $N$, minus one to the top four bits, followed by the first three bytes,
 
high order byte first.  To send longer commands, place the next four bytes
 
into register {\tt A}, and the next four after that into register {\tt B}.
 
In this manner, the device can send commands of up to 11~bytes in length,
 
although most commands may be sent and received with writing only a single
 
word to the control port.
 
 
 
The actual set of commands used to initialize the display is rather complex.
 
Please examine the {\tt oledtest.c} ZipCPU program for an example of how
 
this might be accomplished.  That program sends a series of commands to the
 
control port, waiting for the port to become idle inbetween.  When using polled
 
I/O, the low order bit of the control register will be `1' if the port is busy,
 
zero if not.
 
 
 
\section{Internal Configuration Access Port}
 
% TODO write something more meaningful
 
The Xilinx ICAPE2 controller is part of the {\tt wbicapetwo} project which
 
should also be found near this distribution.  The ICAPE port offers access to
 
the internal Xilinx configuration registers.  The exact meaning of these registers is rather complex, and so users are referred to the Xilinx configuration
 
user guide for more detail.
 
 
 
For now, two registers are worth mentioning.  The first is the WBSTAR register,
 
{\tt 0x01f0}, and the second is the command register, {\tt 0x01e4}.
 
Writes to the {\tt WBSTAR} register will set the address that the Xilinx
 
chip will configure itself from upon any warm start configuration request.
 
(Cold starts always configure from the beginning of flash.)  This address
 
is relative to the start of the flash, and counted in octets rather than
 
bus words.  Hence, to command the Xilinx chip to configure itself from an
 
OpenArty address of {\tt 0x470000}, you would drop the four and multiply by
 
four, and write {\tt 0x1c0000} to this register.
 
 
 
The second register worth mentioning is the command register.  Writing a
 
15~to this register issues an {\tt IPROG} command, causing the FPGA to
 
reload itself from the address given in the {\tt WBSTAR} register.
 
 
 
Put together, this is the meaning of the two lines in {\tt program.sh}:
 
\begin{lstlisting}[language=bash]
 
$WBREGS wbstar 0x01c00000
 
$WBREGS fpgacmd 15
 
\end{lstlisting}
 
 
 
The success of this configuration request may be determined from the
 
{\tt BOOTSTS} register, as discussed in the Xilinx's
 
{\em 7 Series FPGAs Configuration: User Guide}.
 
 
 
\section{Network Packet interface control}
 
Tbl.~\ref{tbl:netpkt}
 
\begin{table}
 
\begin{center}\begin{reglist}
 
NETRX  &\scalebox{0.8}{\tt 0x0138} & 32 & R/W & Packet receive control register\\\hline
 
NETTX  &\scalebox{0.8}{\tt 0x0139} & 32 & R/W & Packet transmit control register\\\hline
 
MACHI &\scalebox{0.8}{\tt 0x013a} & 16 & R/W & Ethernet MAC, hi order 16-bits\\\hline
 
MACLO &\scalebox{0.8}{\tt 0x013b} & 32 & R/W & Ethernet MAC, low order 32-bits\\\hline
 
RXMISS  &\scalebox{0.8}{\tt 0x013c} & 32 & R & Number of valid receive packets missed\\\hline
 
RXERR&\scalebox{0.8}{\tt 0x013d} & 32 & R & Number of packets not properly received\\\hline
 
RXCRC&\scalebox{0.8}{\tt 0x013e} & 32 & R & Packets received with CRC errors\\\hline
 
{\em Unused} &\scalebox{0.8}{\tt 0x013f} & 32 & R & Reads zero (Reserved for transmit collision counting)\\\hline
 
\end{reglist}
 
\caption{Network Packet control registers}\label{tbl:netpkt}
 
\end{center}\end{table}
 
 
 
From the standpoint of configuring this interface, the network transmit
 
control register needs to be configured first.  The bits in this register
 
are shown in Fig.~\ref{fig:nettx}.
 
\begin{figure}\begin{center}\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31}\\
 
        \bitbox{4}{0000}
 
        \bitbox{4}{AW}
 
        \bitbox{5}{00000}
 
        \bitbox{1}{I}
 
        \bitbox{1}{R}
 
        \bitbox{1}{M}
 
        \bitbox{1}{C}
 
        \bitbox{1}{B}
 
        \bitbox{4}{}
 
        \bitbox{10}{Len}\\
 
\end{bytefield}
 
\caption{Network transmit control register, NETTX}\label{fig:nettx}
 
\end{center}\end{figure}
 
By default, the network device is held in a reset state until released by
 
writing a `0' to the $R$ value of this register.  Other bits in this register
 
include the $I$ bit, which turns off the hardware IP packet header checksum
 
check when set, the $M$, which turns off hardware MAC filtering when set,
 
and $C$, which turns off hardware CRC checking and filtering.  These bits
 
are designed so that the natural state of the register is to set them to
 
zero, enabling all hardware checking.  Finally, the $B$ bit will be set to
 
indicate the interface is busy sending a packet.
 
 
 
The other field of this control register is the log address width field.
 
This field specifies the size of the packet buffers, such that there are
 
a maximum of $2^{\mbox{\tiny AW}}$ octets in each packet.
 
 
 
To use the network transmitter:
 
\begin{enumerate}
 
\item Set the $R$ bit to zero.  This will activate the interface,
 
        removing it from reset.
 
\item Set the local hardware MAC address into the {\tt MACHI}
 
        and {\tt MACLO} registers.  (The {\tt MACHI} register holds the top
 
        16~bits, in its lower 16~bits.)
 
\item Write a packet into the transmit packet memory area, starting at the
 
        zero address.
 
        \begin{enumerate}
 
        \item If the hardware MAC option, $M$ bit, is set to zero, then
 
                hardware MAC generation is on.  Place bits {\tt 47\ldots 16}
 
                of the destination MAC in the first word (address 0 of the
 
                TX memory), and fill the next word with the last bits of the
 
                destination MAC and the sixteen bits of the EtherType.
 
        \item If the hardware MAC option is off, i.e. $M=0$, then the
 
                first two words contain the destination MAC as before,
 
                but the second word also contains the top 16--bits of the
 
                source MAC.  The third word contains the bottom bits of the
 
                source MAC.  The fourth word then contains the EtherType
 
                field twice.  Any IP packet then begins on the fifth word.
 
        \item If the hardware CRC option is off, $C=1$, then a CRC will need
 
                to be generated and placed into the last 4--octets of the
 
                message.
 
        \item Octets are transmitted from from high order bits to low order
 
                bits.  Hence the first octet transmitted will be from
 
                bits 31--24 of a given word, the second octet from bits
 
                23--16, etc.
 
        \end{enumerate}
 
\item Once the memory for the packet has been set, sending the packet
 
        is as simple as writing the packet length (in octets), together with
 
        any flag bits, to the network transmit control register.
 
\item If using polled I/O, the transmit control register may be examined to
 
        see when its busy bit clears.  At that point, another packet may be
 
        loaded into memory.
 
\item If using interrupt driven I/O, a network transmit idle interrupt will be
 
        generated once the transmission is complete.  (This interrupt will
 
        remain high until another packet transmit command is issued.)
 
\item To send a subsequent packet, one need only set the memory and write
 
        the transmit command to the control register.  This will reset the
 
        interrupt input to the interrupt controller, so a transmit complete
 
        interrupt may be noticed again.
 
\end{enumerate}
 
 
 
The network receive command register is similar to the transmit
 
command register.  It is shown in Fig.~\ref{fig:netrx}.
 
\begin{figure}\begin{center}\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31}\\
 
        \bitbox{4}{0000}
 
        \bitbox{4}{AW}
 
        \bitbox{4}{0000}
 
        \bitbox{1}{B}
 
        \bitbox{1}{C}
 
        \bitbox{1}{E}
 
        \bitbox{1}{M}
 
        \bitbox{1}{S}
 
        \bitbox{1}{V}
 
        \bitbox{4}{}
 
        \bitbox{10}{Len}\\
 
\end{bytefield}
 
\caption{Network receive control register, NETRX}\label{fig:netrx}
 
\end{center}\end{figure}
 
Unlike the transmit command register, there are no configuration fields in
 
the network receive command register.  The receive configuration bits,
 
controlling such things as whether or not the device it in reset, or whether
 
or not to have the hardware filter out bad
 
CRC's, bad IP header checksums, or MAC addresses not for our machine---these
 
bits are shared with the transmit configuration register.  On receive,
 
bits are set to indicate the success or failure of a received packet.
 
$C$ is set if a packet is received with a CRC error.  $E$ is set if there
 
was some error in packet receiption.  $M$ is set if a packet is received
 
and the memory still contains the last packet, causing a packet Miss.
 
$S$ is set if the receive port is busy.  $V$ is set if a valid packet can be
 
found in the receive memory.  Each of these status bits may be individually
 
cleared by writing a `1' to that respective bit.  Writing a `1' to the valid
 
bit, $V$, also clears the receive port so that another packet may be
 
received.
 
 
 
If the interface is on and no valid packet has been received, then the
 
packet receive logic is activated.  Any packet received with a valid length
 
(64~bytes or more), a valid CRC (if hardware CRC checking is on), either our
 
MAC address (as programmed into the configuration) or a broadcast address,
 
and a valid IP header (if it's an IP packet), will be copied into the receive
 
memory.  Once the packet has been received, the $V$ bit will be set high.
 
If the packet was a broadcast packet, the $B$ bit will also be set.  Writing
 
a `1' to the $V$ bit of this port will clear the packet firmware, and release
 
it to receive another packet.
 
 
 
This port may be operated as either polled or interrupt drive I/O.  If polled,
 
then check the $V$ bit.  Once the $V$ bit is one, a packet is ready to be
 
read from the port.  At the same time $V$ is set to one, an interrupt will
 
be generated.  This interrupt will not clear until $V$ is cleared.
 
 
 
 
 
\section{Ethernet MDIO configuration registers}
 
The ethernet PHY has 32~address configuration address registers available
 
to the board via an MDIO interface.  These are 16--bit registers that may be
 
read from, or written to the device.  The current implementation locks the
 
bus while reading from or writing to the device until the operation is
 
complete.
 
 
 
Using these registers, one can tell if the Ethernet is in 10Mbps mode, or
 
100Mbps mode, or even whether or not a cable is connected.
 
 
 
A simple register to query to know if this interface is working is the LEDCR
 
register, {\tt 0x01b8}.
 
This register will be set to {\tt 0x0ffff} upon startup, and until the network
 
port has been turned on.  Once turned on, this register will default to all
 
zeros.  To manually turn both the LEDs on, write a {\tt 0x030} to the LEDCR
 
register.  To manually turn them off, write a {\tt 0x036}.  A value of
 
{\tt 0x00} will set them back to the default mode of indicating the link
 
status and speed.
 
 
 
Please examine the specification for the ethernet PHY for more information
 
about these registers, what their bits mean, and how the device can be
 
controlled.
 
 
\section{Flash Memory}
\section{Flash Memory}
 
% \section{Extended Flash configuration port}
 
From the standpoint of a user program, flash memory should just work.  This
 
flash memory was designed with that purpose in mind.  Reads are designed to
 
just work.
 
 
 
If only all that a flash required was reading, life would be good.  However,
 
flash chips have a rather complex protocol for reading, erasing, and programming
 
them.  This has made the interface more complex.
 
 
 
Still, reads are \ldots nearly simple.  Reads from the flash
 
memory will automatically be done in Quad--SPI mode and leave the device in
 
Execuste--In--Place (XIP) mode upon completion.  This means that any initial
 
read burst will take $22+8N$ QSPI clocks for $N$ words, whereas subsequent
 
reads will only require $14+8N$ QSPI clocks.  Reading from any of the device
 
registers will transition the device out of XIP mode, and back into the
 
extended register mode.
 
 
 
Writes are more difficult.  Changing the contents of a flash chip requires
 
either erasing a sector (or subsector) in order to turns all the zeros to ones
 
in that sector (or subsector), or it requires writing a page in order to
 
selectively turn some of the ones back to zeros.  The interface used in the
 
OpenArty is designed to allow the user complete flexibility over the control
 
of the flash device, without requiring the device to be commanded explicitly
 
over a SPI (or QSPI) port.  (The device is connected via such a port, the
 
interface tries to hide that fact.)
 
 
 
The result is that there are many registers used for reading, writing, and
 
controlling the flash.  A quick list of these registers is shown in
 
Tbl.~\ref{tbl:flctl}.
\begin{table}
\begin{table}
\begin{center}\begin{reglist}
\begin{center}\begin{reglist}
ewreg  &\scalebox{0.8}{\tt 0x0180} & 32 & R & Erase/write control and status\\\hline
ewreg  &\scalebox{0.8}{\tt 0x0180} & 32 & R & Erase/write control and status\\\hline
status      &\scalebox{0.8}{\tt 0x0181} & 8 & R/W & Bus Interrupt Controller \\\hline
status      &\scalebox{0.8}{\tt 0x0181} & 8 & R/W & Bus Interrupt Controller \\\hline
nvconf   &\scalebox{0.8}{\tt 0x0182} & 16 & R & Last Bus Error Address\\\hline
nvconf   &\scalebox{0.8}{\tt 0x0182} & 16 & R & Last Bus Error Address\\\hline
Line 711... Line 1756...
        &\scalebox{0.8}{\hfill\tt -0x19f} & & & \\\hline
        &\scalebox{0.8}{\hfill\tt -0x19f} & & & \\\hline
% 0x010c-0x010f
% 0x010c-0x010f
\end{reglist}
\end{reglist}
\caption{Flash control registers}\label{tbl:flctl}
\caption{Flash control registers}\label{tbl:flctl}
\end{center}\end{table}
\end{center}\end{table}
 
Many of these registers are defined by the flash itself, and the interface
 
just provides access to them.  These include the status, non--volatile
 
configuration, volatile configuration, the extended volatile configuration,
 
and flag status registers.  In a similar fashion, the Device ID may be read
 
from the device as well.  These registers are defined in the flash
 
specification.
 
 
 
One piece of configuration is required, though, before this interface will work
 
properly either reading or writing.  That is that the fast read (or write)
 
delay must be set to eight clocks.  To do this, write a {\tt 0x08b} needs to be
 
written to the volatile configuration register.\footnote{To get the ZipCPU to
 
start automatically upon power up, or indeed to have the flash start up in a
 
working mode, the non--volatile configuration register will need to be adjusted
 
to contain this information on power up.  Please consult the chip specification
 
to determine what to set that register to.}  To set the volatile configuration
 
register, disable the write protect found in the erase/write control register,
 
and then write the new value to the volatile configuration register.
 
 
 
Perhaps the most important register of this interface is the erase/write
 
control register.  This register enables or disables the write protect for
 
the flash, and issues any erase sector or subsector commands.  The register
 
itself is a bitfield, shown in Fig.~\ref{fig:fewbits}.
 
\begin{figure}\begin{center}\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31}\\
 
        \bitbox{1}{W}
 
        \bitbox{1}{E}
 
        \bitbox{1}{Q}
 
        \bitbox{1}{S}
 
        \bitbox{1}{I}
 
        \bitbox{1}{V}
 
        \bitbox{1}{X}
 
        \bitbox{1}{}
 
        \bitbox{10}{Sector}
 
        \bitbox{4}{Sub}
 
        \bitbox{10}{Key}\\
 
\end{bytefield}
 
\caption{Flash Erase/Write control register layout}\label{fig:fewbits}
 
\end{center}\end{figure}
 
The bits in this register are:
 
 
 
$W$ is a Write-In-Progress bit.  It will be one when read if the device
 
is busy erasing or writing.  Upon any transition back to zero, the controller
 
will issue an interrupt.  This bit is also the Erase Command bit.  Write a
 
`1' to this bit to command the flash to erase either a sector or a subsector.
 
 
 
$E$ is a write--enable bit.  Write a `1' to this bit to disable write
 
protection, and a `0' to this bit to re-enable write protection.  (I highly
 
recommend keeping write protection enabled.  I had an error in one of my
 
programs once that erroneously started walking through peripheral register
 
space and \ldots)
 
 
 
$Q$ is set if Quad SPI mode is enabled.  This is currently hardwired to true
 
within the design, so this bit will never change.
 
 
 
$S$ is the subsector erase bit.  Upon any command to erase the device, if this
 
bit is set then only a subsector will be erased.  If this bit is cleared,
 
the erase command will erase an entire sector.
 
 
 
The $I$ bit is set when the device ID has been read into a local RAM memory.
 
Hence, reading from the device ID initially takes many clocks, but subsequent
 
reads should be very fast.
 
 
 
The $V$ bit will be set upon any write violation, such as trying to write to
 
the device with the write protect enabled.  This bit is cleared upon any
 
write to the erase/write control register.
 
 
 
$X$ is the XIP mode.  This is set any time bit 3 of the volatile configuration
 
register is set, and cleared upon any read from non--flash memory.
 
 
 
Twenty four bits constitute the sector address.  When commanding the device
 
to erase a sector, the register neds to know the top 10 of them.  When
 
commanding the device to erase a subsector, the controller needs the top
 
14~bits.  The bottom 10~bits are a key.  Set these to {\tt 10'h1be} in order
 
to command a (sub)sector erase, or even to just adjust the sector address
 
kept and maintained in this register.
 
 
 
Erasing a sector requires two writes to the erase/write command register.
 
The first write simply disables the write protect.  To do this, write a
 
{\tt 0x40000000} to the register.  The second write must be the sector
 
address added or OR'd to {\tt 0xc00001be}.  When erasing a subsector,
 
set the subsector bit for these two commands.
 
 
 
Writing to a page is similar.  In that case, first disable the write protect
 
as before, and then write (via burst mode) the new page values to the device.
 
The actual write is sent to the device as soon as the burst mode is complete.
 
Hence, writing in separate commands, or writing more than a page (64~words),
 
will stall the bus.
 
 
 
While the write or erase is going on, the erase/write control register may be
 
read.  Once the erase or write has completed, an interrupt will be generated.
 
Unlike the UART interrupts, this interrupt does not perpetually generate itself
 
until cleared.  Hence, you may wish to clear the flash interrupt before
 
an erase/write operation, and then check for the interrupt upon completion.
 
Further, while the erase/write operation is ongoing, you must not try to read
 
from flash memory.  (It is likely to cause a bus error \ldots)
 
 
 
The EQSPI lock register returns the lock register value associated with the
 
currently selected sector.
 
 
 
The OTP registers reference one--time--programmable memory on the flash.
 
This memory, once programmed, {\em can not be cleared}!  Programming this
 
memory constitues changing certain of the default `1's to zeros, depending
 
upon the values you write to these registers.  They are written in a fashion
 
similar to writing/programming a page as described above.
 
 
\chapter{Wishbone Datasheet}\label{ch:wishbone}
\chapter{Wishbone Datasheet}\label{ch:wishbone}
 
 
The master and slave interfaces have been simplified with the following
The master and slave interfaces have been simplified with the following
requirement: the {\tt STB} line is not allowed to be high unless the {\tt CYC}
requirement: the {\tt STB} line is not allowed to be high unless the {\tt CYC}
Line 727... Line 1876...
\begin{clocklist}
\begin{clocklist}
{\tt i\_clk\_100mhz} & Ext & \multicolumn{2}{c|}{100} &
{\tt i\_clk\_100mhz} & Ext & \multicolumn{2}{c|}{100} &
        100~MHz Crystal Oscillator \\\hline
        100~MHz Crystal Oscillator \\\hline
{\em Future }{\tt s\_clk} & PLL & 152 & 166 & Internal Logic, Wishbone Clock \\\hline
{\em Future }{\tt s\_clk} & PLL & 152 & 166 & Internal Logic, Wishbone Clock \\\hline
{\tt s\_clk} & PLL & 83.33 & 75.76& DDR3 SDRAM Controller Clock \\\hline
{\tt s\_clk} & PLL & 83.33 & 75.76& DDR3 SDRAM Controller Clock \\\hline
\multicolumn{2}{|c|}{\tt mem\_clk\_200mhz} & 200~MHz & & MIG Reference clock for PHASERs\\\hline
\multicolumn{2}{|c|}{\tt mem\_clk\_200mhz} & 200~MHz & & MIG Reference clock for PHASER generation\\\hline
{\tt ddr3\_ck\_}$x$ & DDR & 166.67 & 303 & DDR3 Command Clock\\\hline
{\tt ddr3\_ck\_}$x$ & DDR & 166.67 & 303 & DDR3 Command Clock\\\hline
{\tt o\_qspi\_sck} & DDR & 95 & & QSPI Flash clock \\\hline
{\tt o\_qspi\_sck} & DDR & 95 & & QSPI Flash clock \\\hline
{\tt o\_sd\_clk} & Logic & 50 & 0.100 & SD--Card clock \\\hline
{\tt o\_sd\_clk} & Logic & 50 & 0.100 & SD--Card clock \\\hline
{\tt o\_oled\_sck} & Logic & 166 & & OLED SPI clock \\\hline
{\tt o\_oled\_sck} & Logic & 166 & & OLED SPI clock \\\hline
{\tt o\_eth\_mdclk} & Logic & 25 & 2.5 & Ethernet MDIO controller clock\\\hline
{\tt o\_eth\_mdclk} & Logic & 25 & 2.5 & Ethernet MDIO controller clock\\\hline

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.