URL
https://opencores.org/ocsvn/openarty/openarty/trunk
Subversion Repositories openarty
Compare Revisions
- This comparison shows the changes necessary to convert path
/openarty/trunk
- from Rev 47 to Rev 48
- ↔ Reverse comparison
Rev 47 → Rev 48
/doc/spec.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/doc/src/spec.tex
38,10 → 38,11
%% |
\usepackage{import} |
\usepackage{bytefield} |
\usepackage{listings} |
\project{OpenArty} |
\title{Specification} |
\author{Dan Gisselquist, Ph.D.} |
\email{dgisselq (at) opencores.org} |
\email{dgisselq (at) ieee.org} |
\revision{Rev.~0.0} |
\begin{document} |
\pagestyle{gqtekspecplain} |
65,6 → 66,7
\begin{revisionhistory} |
0.0 & 6/20/2016 & Gisselquist & First Draft \\\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} |
% Revision History |
% Table of Contents, named Contents |
78,8 → 80,49
\pagenumbering{arabic} |
\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 |
% Arty, XuLA |
% Arty, XuLA, Learnables using schematic drawing techniques |
% What does the old lack? |
% Arty lacks open interfaces, instead using MIG and CoreGen w/ AXI bus |
% What is new |
90,42 → 133,83
% 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} |
\item Use entirely open interfaces |
|
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 |
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. |
Xilinx CoreGen IP, etc. |
|
\item Run using a 162.5~MHz clock, if for no other reason than to gain the |
experience of building logic that can run that fast.\footnote{The |
(This goal has not yet been achieved.) |
|
\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 |
cannot run faster than 83~MHz. If we run it at 81.25~MHz and double |
that clock to get our logic clock, that now places us at 162.5~MHz. |
200~MHz is \ldots too fast for DDR3 transfers using the Artix--7 chip |
on the Arty.} |
cannot run faster than about 82~MHz. If we run it at 81.25~MHz and |
double that clock to get our logic clock, that now places us at |
162.5~MHz. 200~MHz is \ldots too fast for DDR3 transfers using the |
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 |
a floating point unit. |
|
\item The default configuration will also include three Pmods: a USBUART, |
an SDCard, and the GPS Pmod. |
(These are still in development.) |
|
\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} |
|
I intend to demonstrate this project with a couple programs: |
\begin{enumerate} |
\item NTP Server |
\item A ZipOS that can actually load and run programs from the SD Card |
\item An NTP Server |
|
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 |
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 |
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 |
132,12 → 216,296
memory address space, while allowing the operating system to allocate |
actual physical memory addresses as necessary to support whatever |
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} |
|
|
\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} |
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 |
504,7 → 872,7
\chapter{Operation}\label{ch:operation} |
|
\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}. |
\begin{table}[htbp] |
\begin{center}\begin{tabular}{|p{2.25in}|p{0.6in}|p{0.45in}|p{2.0in}|}\hline |
536,38 → 904,63
\end{tabular} |
\caption{Address Regions}\label{tbl:memregions} |
\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{center}\begin{tabular}{|p{0.9in}|p{0.45in}|p{3.5in}|}\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 0x0c0000001} & 1 & Watchdog Timer\\\hline |
\scalebox{0.9}{\tt 0x0c0000002} & 1 & Bus Watchdog Timer\\\hline |
\scalebox{0.9}{\tt 0x0c0000003} & 1 & Alternate Zip PIC\\\hline |
\scalebox{0.9}{\tt 0x0c0000004} & 1 & ZipTimer-A\\\hline |
\scalebox{0.9}{\tt 0x0c0000005} & 1 & ZipTimer-B\\\hline |
\scalebox{0.9}{\tt 0x0c0000006} & 1 & ZipTimer-C\\\hline |
\scalebox{0.9}{\tt 0x0c0000007} & 1 & ZipJiffies\\\hline |
\scalebox{0.9}{\tt 0x0c0000008} & 1 & Master task counter\\\hline |
\scalebox{0.9}{\tt 0x0c0000009} & 1 & Master prefetch stall counter\\\hline |
\scalebox{0.9}{\tt 0x0c000000a} & 1 & Master memory stall counter\\\hline |
\scalebox{0.9}{\tt 0x0c000000b} & 1 & Master instruction counter\\\hline |
\scalebox{0.9}{\tt 0x0c000000c} & 1 & User task counter\\\hline |
\scalebox{0.9}{\tt 0x0c000000d} & 1 & User prefetch stall counter\\\hline |
\scalebox{0.9}{\tt 0x0c000000e} & 1 & User memory stall counter\\\hline |
\scalebox{0.9}{\tt 0x0c000000f} & 1 & User instruction counter\\\hline |
\scalebox{0.9}{\tt 0x0c0000010} & 1 & DMA command register\\\hline |
\scalebox{0.9}{\tt 0x0c0000011} & 1 & DMA length\\\hline |
\scalebox{0.9}{\tt 0x0c0000012} & 1 & DMA source address\\\hline |
\scalebox{0.9}{\tt 0x0c0000013} & 1 & DMA destination address\\\hline |
\scalebox{0.9}{\tt 0x0c0000040} & 1 & {\em Reserved for MMU context register}\\\hline |
\scalebox{0.9}{\tt 0xc0000000} & 1 & Primary Zip PIC\\\hline |
\scalebox{0.9}{\tt 0xc0000001} & 1 & Watchdog Timer\\\hline |
\scalebox{0.9}{\tt 0xc0000002} & 1 & Bus Watchdog Timer\\\hline |
\scalebox{0.9}{\tt 0xc0000003} & 1 & Alternate Zip PIC\\\hline |
\scalebox{0.9}{\tt 0xc0000004} & 1 & ZipTimer-A\\\hline |
\scalebox{0.9}{\tt 0xc0000005} & 1 & ZipTimer-B\\\hline |
\scalebox{0.9}{\tt 0xc0000006} & 1 & ZipTimer-C\\\hline |
\scalebox{0.9}{\tt 0xc0000007} & 1 & ZipJiffies\\\hline |
\scalebox{0.9}{\tt 0xc0000008} & 1 & Master task counter\\\hline |
\scalebox{0.9}{\tt 0xc0000009} & 1 & Master prefetch stall counter\\\hline |
\scalebox{0.9}{\tt 0xc000000a} & 1 & Master memory stall counter\\\hline |
\scalebox{0.9}{\tt 0xc000000b} & 1 & Master instruction counter\\\hline |
\scalebox{0.9}{\tt 0xc000000c} & 1 & User task counter\\\hline |
\scalebox{0.9}{\tt 0xc000000d} & 1 & User prefetch stall counter\\\hline |
\scalebox{0.9}{\tt 0xc000000e} & 1 & User memory stall counter\\\hline |
\scalebox{0.9}{\tt 0xc000000f} & 1 & User instruction counter\\\hline |
\scalebox{0.9}{\tt 0xc0000010} & 1 & DMA command register\\\hline |
\scalebox{0.9}{\tt 0xc0000011} & 1 & DMA length\\\hline |
\scalebox{0.9}{\tt 0xc0000012} & 1 & DMA source address\\\hline |
\scalebox{0.9}{\tt 0xc0000013} & 1 & DMA destination address\\\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 |
\end{tabular} |
\caption{ZipSystem Addresses}\label{tbl:zipio} |
\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} |
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{center}\begin{reglist} |
VERSION &\scalebox{0.8}{\tt 0x0100} & 32 & R & Build date\\\hline |
585,33 → 978,50
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 |
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 |
GPSSUB &\scalebox{0.8}{\tt 0x0110} & 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 |
GPSSECS &\scalebox{0.8}{\tt 0x0112} & 32 & R/W & {\em Reserved for a one-up seconds counter}\\\hline |
GPSSUB &\scalebox{0.8}{\tt 0x0113} & 32 & R/W & GPS PPS tracking subsecond info\\\hline |
GPSSTEP &\scalebox{0.8}{\tt 0x0114} & 32 & R/W & Current GPS step size, units TBD\\\hline |
% 0x010c-0x010f |
\end{reglist} |
\caption{I/O Peripheral Registers}\label{tbl:ioregs} |
\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. |
|
\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} |
The OpenArty design maintains three interrupt controllers. Two of them |
are found within the ZipSystem, and the third is located on the bus |
itself. Of these, the primary interrupt controller is located in the ZipSystem. |
This interrupt controller accepts, as interrupt inputs, the outputs of both |
the auxilliary interrupt controller as well as the bus interrupt controller. |
Hence, even though the CPU only supports a single interrupt line, by using |
these three interrupt controllers many more interrupts can be supported. |
(a primary and an auxiliary) are found within the ZipSystem, and the third is |
located on the bus itself. In terms of functionality, all three interrupt |
controllers are the same, and documented in the ZipCPU specification. Of |
these, the primary interrupt controller for the |
entire design is the primary interrupt controller within the ZipSystem. |
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 |
in Tbl.~\ref{tbl:sys-ints}. 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}. Finally, the |
bus interrupt controller handles the interrupts from the sources listed in |
Tbl.~\ref{tbl:bus-ints}. |
|
in Tbl.~\ref{tbl:sys-ints}. |
\begin{table}[htbp] |
\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 |
635,7 → 1045,10
\end{tabular} |
\caption{Primary System Interrupts}\label{tbl:sys-ints} |
\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{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 |
657,7 → 1070,11
\end{tabular} |
\caption{Auxilliary System Interrupts}\label{tbl:aux-ints} |
\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{center}\begin{tabular}{|p{0.9in}|p{0.75in}|p{3.75in}|}\hline |
\rowcolor[gray]{0.85} Name & Bit Mask & Description \\\hline\hline |
684,15 → 1101,643
\end{tabular} |
\caption{Bus Interrupts}\label{tbl:bus-ints} |
\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} |
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{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{Real--Time Clock} |
% 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} |
\section{Real--Time Clock} |
\section{On-Chip Block RAM} |
% 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{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{center}\begin{reglist} |
ewreg &\scalebox{0.8}{\tt 0x0180} & 32 & R & Erase/write control and status\\\hline |
713,7 → 1758,111
\end{reglist} |
\caption{Flash control registers}\label{tbl:flctl} |
\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} |
|
The master and slave interfaces have been simplified with the following |
729,7 → 1878,7
100~MHz Crystal Oscillator \\\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 |
\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 o\_qspi\_sck} & DDR & 95 & & QSPI Flash clock \\\hline |
{\tt o\_sd\_clk} & Logic & 50 & 0.100 & SD--Card clock \\\hline |