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

Subversion Repositories s6soc

[/] [s6soc/] [trunk/] [doc/] [src/] [spec.tex] - Diff between revs 18 and 36

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

Rev 18 Rev 36
Line 24... Line 24...
 
 
You should have received a copy of the GNU General Public License along
You should have received a copy of the GNU General Public License along
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.2 & 5/14/2016 & Gisselquist & Updated Draft, still not complete \\\hline
0.1 & 4/22/2016 & Gisselquist & First Draft \\\hline
0.1 & 4/22/2016 & Gisselquist & First Draft \\\hline
\end{revisionhistory}
\end{revisionhistory}
% Revision History
% Revision History
% Table of Contents, named Contents
% Table of Contents, named Contents
\tableofcontents
\tableofcontents
Line 48... Line 49...
to change without notice.
to change without notice.
 
 
This project comes from my desire to demonstrate the Zip CPU's utility in a
This project comes from my desire to demonstrate the Zip CPU's utility in a
challenging environment.  The CMod~S6 board fits this role nicely.
challenging environment.  The CMod~S6 board fits this role nicely.
\begin{enumerate}
\begin{enumerate}
\item The Spartan--6 LX4 FPGA is very limited in it's resources:
\item The Spartan--6 LX4 FPGA is very limited in its resources:
        It only has 2,400 look--up tables (LUTs), and can only support
        It only has 2,400 look--up tables (LUTs), and can only support
        a 4,096~Word RAM memory (16 kB).
        a 4,096~Word RAM memory (16 kB).
\item With only 4kW RAM, the majority of any program will need to be placed into
\item With only 4kW RAM, the majority of any program will need to be placed into
        and run from flash.  (The chip will actually support more, just not
        and run from flash.  (The chip will actually support more, just not
        8k RAM.)
        8k RAM.)
Line 103... Line 104...
\end{center}\end{figure}
\end{center}\end{figure}
Using this alternate architecture, it should be possible to test the peripherals
Using this alternate architecture, it should be possible to test the peripherals
and program the flash memory.  Both architectures may be loaded into the flash,
and program the flash memory.  Both architectures may be loaded into the flash,
together with the programming code for the Zip CPU.
together with the programming code for the Zip CPU.
 
 
The basic approach is simple: up and until the software works, the S6 will
The basic approach to loading the board is actually quite simple.  Using the
power up into the alternate architecture of Fig.~\ref{fig:altarchitecture}.
Digilent ADEPT JTAG configuration program, {\tt djtgcfg}, the alternate
While in this state, the flash may be examined and programmed.  Once complete,
configuration may be written directly to the device.  Once this alternate
a UART command to the ICAPE port will tell the S6 to load the (primary)
configuration has been loaded, the flash may be examined and programmed.
FPGA configuration from an alternate flash location.  This alternate location
This includes programming a primary and alternate configuration into the
will contain a configuration image containing the CPU.  The CPU will then begin
configuration section of the flash.  Once complete, the system may then be
following the instructions given to it from the flash.
reloaded with the primary configuration file which will contain an image of
 
the CPU.  The CPU will then begin following the instructions found in flash
 
memory.
 
 
 
 
 
\chapter{Software}
 
\section{Directory Structure}
 
\begin{itemize}
 
\item[{\tt trunk/bench}] Contains software for emulating the S6 without the S6
 
        present.
 
  \begin{itemize}
 
        \item[{\tt trunk/bench/cpp}]  All of the bench testing software is
 
                written in C++, so it is found in this directory.  Primary
 
                among these programs is the {\tt zip\_sim} program which will
 
                simulate the ZipCPU within the S6--Soc.  Specifically, it
 
                simulates everything at or below the {\tt busmaster.v} level.
 
 
 
                Some, although not all, of the peripherals have been simulated
 
                and made a part of this simulation.  These include the
 
                Quad--SPI flash, the UART, and the LED's.
 
 
 
  \end{itemize}
 
\item[{\tt trunk/doc}] All of the documentation for the S6SoC project may be
 
        found in this documentation directory.  Specifically, I would commend
 
        your attention to anything with a {\tt .pdf} extension, as these
 
        are the completed documents.  Among these you should find a copy of the
 
        GPL copyright under which this software is released, as well as a
 
        pre--built copy of this document.
 
  \begin{itemize}
 
        \item[{\tt trunk/doc/gfx}] Here is where the graphics are located in
 
                support of this specification document.
 
        \item[{\tt trunk/doc/src}] And here is where the \LaTeX files are
 
                kept that were used in building both this document as well as
 
                the GPL copyright.
 
  \end{itemize}
 
\item[{\tt trunk/rtl}] Verilog files
 
  \begin{itemize}
 
        \item[{\tt trunk/rtl/cpu}]      Verilog files containing the ZipCPU
 
                core and peripherals.  The toplevel file here is the
 
                {\tt zipbones.v} file, although some of the peripherals, such
 
                as the {\tt ziptimer.v} are referenced independently.
 
  \end{itemize}
 
\item[{\tt trunk/sw}] The main software directory, primarily a repository
 
        for software subdirectories beneath it.
 
  \begin{itemize}
 
        \item[{\tt trunk/sw/dev}]  This directory holds a variety of
 
                simple programs for the ZipCPU, such as {\tt helloworld},
 
                {\tt doorbell} and {\tt doorbell2}, as well as software drivers
 
                for various peripherals, such as the real--time clock simulator,
 
                and the keypad and display device drivers.
 
        \item[{\tt trunk/sw/host}]  This directory holds support software which
 
                can be built on and run on the host machine.  Building this
 
                software will involve adjusting the Makefile so that it knows
 
                where your local ADEPT installation directory is.\footnote{Many
 
                of the programs also depend upon the serial number of my CMod
 
                S6 device.  This will need to be adjusted in any new install.}
 
                Once built, you will find a variety of very useful programs
 
                within here.
 
        \item[{\tt trunk/sw/zipos}]  This directory contains the source code for
 
                        a rudimentary, very basic, operating system that I
 
                        call the ZipOS.
 
  \end{itemize}
 
\end{itemize}
 
 
 
\section{ZipCPU Tool Chain}
 
To build programs for the ZipCPU, you will need the ZipCPU toolchain.  You
 
can find this as part of the ZipCPU project, available at OpenCores.  Building
 
the ZipCPU project should result in a set of binaries in the
 
\hbox{\tt trunk/sw/install/cross-tools/bin} directory.  Make this directory
 
a part of your path, and you should be able to build the CMod S6 ZipCPU
 
software.  Specifically, you will need to use {\tt zip-gcc}, {\tt zip-as}
 
{\tt zip-ld}, and {\tt zip-cpp}.  Other tools, such as {\tt zip-objdump} and
 
{\tt zip-readelf}, may also prove to be very useful when trying to figure out
 
what is going on within the SoC.
 
 
 
\section{Bench Test Software}
 
 
 
Bench testing software currently consists of the {\tt zip\_sim} program found
 
within {\tt trunk/bench/cpp}.  This program requires Verilator to run, and
 
simulates in a cycle accurate fashion, the entire S6SoC from {\tt busmaster.v}
 
on down.  Further, the external Quad--SPI flash memory, UART, and LED's are
 
also simulated, although the 2--line display, audio, and keypad are not.
 
 
 
\section{Host Software}
 
These include:
 
\begin{itemize}
 
\item {\tt dumpuart}: My current approach to debugging involves
 
        dumping the state of the registers and memory to the
 
        UART upon reboot.  The dumpuart command found here is
 
        designed to make certain that the UART is first set
 
        up correctly at 9600~Baud, and that second everything
 
        read from the UART is directly sent to both a file and
 
        to the screen.  In this fashion, it is similar to the
 
        UNIX {\tt tee} program, save for its serial port
 
        attachment.
 
\item {\tt readflash}: As I am loathe to remove anything from
 
        a device that came factory installed, the
 
        {\tt readflash} program reads the original installed
 
        configuration from the flash and dumps it to a file.
 
\item {\tt wbregs}
 
\item {\tt zipload}: This is the primary program you will need
 
        to get your software loaded on the CMod.  It takes three
 
        arguments.  The first is the name of the primary
 
        Xilinx configuration file, the second is the name
 
        of the alternate Xilinx configuration file, and the
 
        third is the name of the ZipCPU program you wish to
 
        write to Flash memory.
 
 
 
        Each of these arguments is optional.  For example, if
 
        only one configuration file is given, the loader will
 
        load the primary configuration.  If only one ZipCPU
 
        program is given, the program will be loaded into
 
        the program memory area and the configuration file areas
 
        will be left untouched.
 
\end{itemize}
 
\section{ZipCPU Programs}
 
\begin{itemize}
 
\item {\tt helloworld}: The first program any programmer should build,
 
        ``Hello, world!''  This program sends the string, ``Hello, world!''
 
        over the UART connection once per second.  It is a very valuable
 
        program because, if you can get this program running, you know you have
 
        a lot of things working and working correctly.  For example, running
 
        this program means you can run the {\tt zip-gcc} compiler, load
 
        the auxiliar configuration, load the program info flash memory, load
 
        the primary configuration, and read from the UART port.  It also means
 
        that you must have the UART port properly configured and wired to your
 
        CMod board.
 
\item {\tt doorbell}: This annoying program verifies the functionality of the
 
        audio device by playing a doorbell sound to the audio port.  It will
 
        then wait ten seconds, and play the doorbell sound again (and again,
 
        and again).  (It gets old after a while ...)
 
\item {\tt doorbell2}: This adds to the functionality of the {\tt doorbell}
 
        program a wait for keypress, and a display of the current time on the
 
        2--line display.  While almost our fully functional program, this
 
        does not include any menus to configure the device or set time, since
 
        it doesn't include any keypad functionality.
 
\item {\tt kptest}: A test of whether or not they keypad driver works.  When
 
        run, anytime a key is pressed, the key's value (in hex) will be
 
        sent to the UART.  Further, pressing an `F' on the keypad will also
 
        send a newline over the UART, in case you wish to keep your lines from
 
        getting too long.
 
\end{itemize}
 
\section{ZipOS}
 
This operating system is pre--emptive and multitasking, although with many
 
limitations.  Those familiar with the internals of the Linux kernel may laugh
 
that I call this an Operating System at all: it has no memory management unit,
 
no paging, no virtual memory, no file I/O access, no network stack, no ability
 
to dynamically add or remove tasks, indeed it hardly has any of the things
 
most often associated with an Operating System.  It does, however, handle
 
interrupts, support multiple pre--emptive tasks in a multitasking, timesharing
 
fashion, and it supports some very basic and rudimentary system calls.  In a
 
similar fashion, it does contain just about all of the functionality necessary
 
for a multi--tasking microcontroller built around a do--forever loop.  For its
 
size, I consider it an impressive achievement.  You are welcome to disagree
 
with me, however.
 
 
 
This version of the ZipOS starts in the resetdump.s code, so that upon
 
any startup the ZipOS will dump register contents, the BusError register, and
 
any scope contents to the UART.  This can take some time, so you may wish to
 
configure what you really wish to send--if anything.  If desired, this will
 
also dump the entire memory as well.  All of this is quite useful in case the
 
ZipCPU encounters a bus error or other sort of error that causes it to hang,
 
stall, or reboot, as these registers are very carefully not touched prior to
 
being sent to the UART output port.
 
 
 
{\tt resetdump.s} also calls a rudimentary bootloader, to load the parts of
 
the ZipOS that need to run faster into Block RAM.  The choice of what parts
 
to load into Block RAM is made on a file by file basis, and found within
 
the linker script, {\tt cmodram.ld}.
 
 
 
Upon completion, {\tt resetdump.s} calls the entry routine for the O/S,
 
{\tt kernel\_entry()} found in {\tt kernel.c}.  This is the main task loop for
 
the entire O/S, and worth studying if you are interested in understanding how
 
the O/S works.
 
 
 
The user tasks are found (mostly) within {\tt doorbell.c}, also found in the
 
ZipOS directory.  This file contains two kernel entry points, {\tt kntasks()},
 
which returns the number of tasks the kernel needs to know about, and
 
{\tt kinit()}, which builds each of the tasks and connects their file
 
descriptors to the various devices they will be referencing.
 
\subsection{Traps}
 
The ZipCPU supports a variety of traps, listed here:
 
\begin{itemize}
 
\item WAIT: Halts the execution of a process until an event takes place, or
 
        a timeout has been reached.  The events that can take place are a
 
        bitmask of the various interrupts the CPU supports, together with a
 
        bitmask of the values found in {\tt swint.h}.
 
 
 
        The timeout value can either be zero, to return immediately with the
 
        list of events that have taken place, negative, to wait indefinitely,
 
        or a positive number of milliseconds in order to wait at least that
 
        time for the event of interest to take place.
 
 
 
        This also allows a process to sleep for any number of milliseconds.
 
 
 
        When wait returns, any events returned by the wait have been cleared.
 
 
 
        The other thing to be aware of is that events may accumulate before the
 
        wait system call.  They will only be returned and cleared, though, if
 
        the wait call indicates an interest in those events.
 
\item CLEAR: This system call works closely with the wait system call.
 
        Indeed, it is very similar to a wait system call with a zero timeout.
 
        It clears any of the requested events which may be pending.  If given
 
        a timeout (in milliseconds), it will start a timer and generate a
 
        {\tt SWINT\_TIMEOUT} event to be sent to this process when the timer
 
        completes.
 
\item POST: Certain devices, such as the real--time clock and the doorbell
 
        reader, need the ability of being able to post events to any listener
 
        within the O/S.  The POST system call allows them to POST events in
 
        this manner.
 
\item YIELD: This is simply a way of being nice to other processes.  This system
 
        call takes no arguments and simply asks the scheduler to schedule the
 
        next process.  It does not take this process off of the ready to run
 
        list, so the next process may be this one.  However, since the scheduler
 
        is a round--robin scheduler, it will only return to this process if
 
        nothing else is available to run.
 
\item READ: This is roughly the same system call as the POSIX read() system
 
        call.  It reads some number of memory addresses (words, not octets),
 
        to the given file descriptor.  If the memory requested is unavailable,
 
        the read will wait until it is available, possibly indefinitely.
 
\item WRITE: This is roughly the same system call as the POSIX write() system
 
        call.  It writes some number of memory addresses (words, not octets),
 
        to the given file descriptor.  If nothing is reading from the device,
 
        the write stall the task forever, otherwise it will only stall the task
 
        until the data is either written to the receiving task, or copied into
 
        a memory buffer.
 
\item TIME: Returns the number of seconds since startup.  Eventually, this will
 
        return the number of seconds since January 1, 1970, and be identical
 
        to the UNIX system time() command, but that may not happen on this
 
        project.
 
% \item SEMGET
 
% \item SEMPUT
 
\item MALLOC: Allocates memory from the system/kernel heap.  This is a very
 
        low overhead memory allocator that, while it does allocate memory,
 
        cannot free it later.  It is nearly 100\% efficient since only
 
        one memory address, the top of the heap, is used to determine what
 
        memory has been allocated.
 
\item FREE: Not currently implemented.
 
\end{itemize}
 
\subsection{Scheduler}
 
The ZipCPU currently supports only a round--robin scheduler.  Tasks are executed
 
in the order they were created, as long as they are available to be executed.
 
If no tasks are available to be run, the Scheduler will run the idle task which
 
puts the CPU to sleep while waiting for an interrupt.
 
 
\chapter{Operation}
\chapter{Operation}
 
 
\chapter{Registers}
\chapter{Registers}
There are several address regions on the S6~SoC, as shown in
There are several address regions on the S6~SoC, as shown in
Line 139... Line 381...
This isn't quite so true with the other address regions.  Accessing the I/O
This isn't quite so true with the other address regions.  Accessing the I/O
region, while it may be read/write, may have side-effects.  For example, reading
region, while it may be read/write, may have side-effects.  For example, reading
from the debugging scope device's data port will read a word from the scope's
from the debugging scope device's data port will read a word from the scope's
buffer and advance the buffer pointer.
buffer and advance the buffer pointer.
 
 
\section{Debugging Scope}
\section{Peripheral I/O Control}
The debugging scope consists of two registers, a control register and a data
 
register.  It needs to be internally wired to 32--wires, internal to the S6
 
SoC, that will be of interest later.  For further details on how to configure
 
and use this scope, please see the {\tt WBSCOPE} project on OpenCores.
 
 
 
\section{Internal Configuration Access Port}
 
The Internal Configuration Access Port (ICAP) provides access to the internal
 
configuration details of the FPGA.  This access was designed so as to provide
 
the CPU with the capability to command a different FPGA load.  In particular,
 
the code in Fig.~\ref{fig:reload} should reconfigure the FPGA from any given
 
Quad SPI {\tt address}.\footnote{According to Xilinx's technical support, this
 
will only work if the JTAG port is not busy.}
 
\begin{figure}\begin{center}\begin{tabbing}
 
{\tt warmboot(uint32 address) \{} \\
 
\hbox to 0.25in{}\={\tt uint32\_t *icape6 = (volatile uint32\_t *)0x{\em <ICAPE port address>};}\\
 
 \>{\tt icape6[13] = (address<<2)\&0x0ffff;}\\
 
 \>{\tt icape6[14] = ((address>>14)\&0x0ff)|((0x03)<<8);}\\
 
 \>{\tt icape6[4] = 14;}\\
 
 \>{\em // The CMod~S6 is now reconfiguring itself from the new address.}\\
 
 \>{\em // If all goes well, this routine will never return.}\\
 
{\tt \}}
 
\end{tabbing}
 
\caption{Spartan--6 ICAPE Usage}\label{fig:reload}
 
\end{center}\end{figure}
 
 
 
For further details, please see either the {\tt WBICAPETWO} project on OpenCores
 
as well as Xilinx's ``Spartan-6 FPGA Configuration User Guide''.
 
 
 
\section{Real--Time Clock}
 
The Real Time Clock will be included if there is enough area to support it.
 
The four registers correspond to a clock, a timer, a stopwatch, and an alarm.
 
If space is tight, the timer and stopwatch, or indeed the entire clock, may be
 
removed from the design.  For further details regarding how to set and use this
 
clock, please see the {\tt RTCCLOCK} project on OpenCores.
 
 
 
\section{I/O Peripherals}
 
Tbl.~\ref{tbl:ioregs}
Tbl.~\ref{tbl:ioregs}
\begin{table}[htbp]
\begin{table}[htbp]
\begin{center}\begin{reglist}
\begin{center}\begin{reglist}
PIC    &\scalebox{0.8}{\tt 0x0100} & 32 & R/W & Interrupt Controller \\\hline
PIC    &\scalebox{0.8}{\tt 0x0100} & 32 & R/W & Interrupt Controller \\\hline
BUSERR &\scalebox{0.8}{\tt 0x0101} & 32 & R & Last Bus Error Address\\\hline
BUSERR &\scalebox{0.8}{\tt 0x0101} & 32 & R & Last Bus Error Address\\\hline
TIMA   &\scalebox{0.8}{\tt 0x0102} & 32 & R/W & ZipTimer A\\\hline
TIMA   &\scalebox{0.8}{\tt 0x0102} & 32 & R/W & ZipTimer A\\\hline
TIMB   &\scalebox{0.8}{\tt 0x0103} & 32 & R/W & ZipTimer B\\\hline
TIMB   &\scalebox{0.8}{\tt 0x0103} & 32 & R/W & ZipTimer B\\\hline
PWM    &\scalebox{0.8}{\tt 0x0104} & 32 & R/W & PWM Audio Controller\\\hline
PWM    &\scalebox{0.8}{\tt 0x0104} & 32 & R/W & PWM Audio Controller\\\hline
KYPAD  &\scalebox{0.8}{\tt 0x0105} & 32 & R/W & Special Purpose I/O, Keypad, LED Controller \\\hline
SPIO   &\scalebox{0.8}{\tt 0x0105} & 32 & R/W & Special Purpose I/O, Keypad, LED Controller \\\hline
GPIO   &\scalebox{0.8}{\tt 0x0106} & 32 & R/W & GPIO Controller \\\hline
GPIO   &\scalebox{0.8}{\tt 0x0106} & 32 & R/W & GPIO Controller \\\hline
UART   &\scalebox{0.8}{\tt 0x0107} & 32 & R/W & UART data\\\hline
UART   &\scalebox{0.8}{\tt 0x0107} & 32 & R/W & UART data\\\hline
\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 various I/O peripherals included as part of the SoC.
 
 
 
\subsection{Interrupt Controller}
The interrupt controller is identical to the one found with the ZipSystem.
The interrupt controller is identical to the one found with the ZipSystem.
Please read the ZipSystem documentation for how to control this.
The layout of the PIC bits is shown in Fig.~\ref{fig:picreg}.
 
\begin{figure}\begin{center}
 
\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31} \\
 
        \bitbox{1}{E}
 
        \bitbox{15}{Enabled}
 
        \bitbox{1}{A}
 
        \bitbox{15}{ACTIVE}
 
        \\
 
\end{bytefield}
 
\caption{Programmable Interrupt Control (PIC) Register}\label{fig:picreg}
 
\end{center}\end{figure}
 
This controller supports up to fifteen interrupts, however only twelve are
 
defined within the SoC.  If any interrupt line is active, the PIC controller
 
will have that bit set among it's active set.  Once set, the bit and hence the
 
interrupt can only be cleared by writing to the controller.  Interrupts can
 
also be enabled as well.  The enabled bit mask controls which interrupt lines
 
are permitted to interrupt the CPU. Hence, just because an interrupt is active
 
doesn't mean it will interrupt the CPU--the enabled line must be set as well.
 
Finally, then {\tt A} or {\tt ANY} bit will be high if any interrupts are both
 
enabled and active, whereas the {\tt E} or global interrupt enable bit can be
 
set to allow the PIC to interrupt the CPU or cleared to disable all interrupts.
 
 
 
To keep operations on this register atomic, most of the bits of this register
 
have special meanings upon write.  The one exception to this is the global
 
interrupt enable bit.  On any write, interrupts will be globally enabled or
 
disabled based upon the value of this bit.  Further, the {\tt ANY} bit is a
 
read only bit, so writes to it have no effect.
 
 
 
Enabling specific interrupts, via writes to the enable lines, are different.
 
To enable a specific interrupt, enable all interrupts and
 
set the wire high associated with the specific interrupt you wish to enable.
 
Hence writing a {\tt 0x80010000} will enable interrupt line zero, while also
 
enabling all previously enabled interrupts.
 
To disable a specific interrupt, disable all interrupts and write a one to the
 
enable line of the interrupt you wish to disable.  In this fashion, writing a
 
{\tt 0x00010000} will disable all interrupts and leave interrupt line zero
 
disabled when the interrupts are re--enabled later, whereas {\tt 0x07fff0000}
 
will disable all specific interrupts.
 
 
 
Interrupts are acknowledged in a fashion similar to enabling interrupts.  By
 
writing a `1' to the active bit mask, the interrupt will be acknowledged and
 
reset, whereas writing a `0' leaves the interrupt untouched.  In this fashion,
 
as individual interrupts are handled, a `1' may be written to this bottom mask
 
to clear the interrupt.  Be aware, however, that any interrupt acknowledgement
 
may also globally enable or disable interrupts.
 
 
 
\subsection{Last Bus Error Address}
The Bus Error peripheral simply records the address of the last bus error.
The Bus Error peripheral simply records the address of the last bus error.
This can be useful when debugging.  While the peripheral may only be read,
This can be useful when debugging.  While the peripheral may only be read,
setting it is really as easy as creating a bus error and trapping the result.
setting it is really as easy as creating a bus error and trapping the result.
 
Another use for this is upon any reboot, it is possible to read the address
 
of the last bus error and perhaps learn something of what caused the CPU to
 
restart.
 
 
 
\subsection{ZipTimer}
 
The S6 Soc contains two ZipTimers, available for the CPU to use.  These are
 
countdown timers.  Writing any non--zero value to them will cause them to
 
immediately start counting down from that value towards zero, and to interrupt
 
the CPU when they reach zero.  Writing a new value while the timer is running
 
will cause that new value to automatically load into the CPU and start counting
 
from there.  Writing a zero to the timer disables the timer, and causes it to
 
stop.
 
 
 
ZipTimer A can be set to auto reload.  When set, the timer will automatically
 
load it's last set value upon reaching zero and interrupting the CPU.  This
 
effectively turns it into an interrupt timer if desired.  To set this feature,
 
write to the timer the number of clock ticks before an interrupt, but also set
 
the high order bit.  In this fashion, writing a {\tt 0x80013880} will interrupt
 
the CPU every millisecond, starting one millisecond after the write takes place
 
(assuming an 80~MHz system clock).
 
 
 
ZipTimer B has been wired for a different purpose.  ZipTimer B does not support
 
auto reload, nor will it interrupt the CPU.  Instead, ZipTimer B has been wired
 
as a watchdog timer.  When this timer reaches zero, the CPU will be rebooted.
 
One way to use this timer would be in conjunction with the ZipTimer A, and to
 
write a number to it upon any entry to the interrupt service routine.  If given
 
enough time, this would cause the CPU to reboot if for any reason it locked up.
 
 
The two ZipTimer's are ZipSystem timer's, placed onto this peripheral bus.
\subsection{PWM Audio Controller}
They are available for the CPU to use.  Common uses might include I2C or SPI
The bit fields of the PWM Audio controller are shown in Fig.~\ref{fig:pwmreg}.
speed control, or multi--tasking task-swap control.  For further details, please
\begin{figure}\begin{center}
see the ZipSystem documentation.
\begin{bytefield}[endianness=big]{32}
 
\bitheader{0-31} \\
 
        \bitbox{10}{Unused}
 
        \bitbox{1}{S}
 
        \bitbox{1}{G}
 
        \bitbox{3}{}
 
        \bitbox{1}{E}
 
        \bitbox{16}{Sample}
 
        \\
 
\end{bytefield}
 
\caption{PWM Audio Controller Bitfields}\label{fig:pwmreg}
 
\end{center}\end{figure}
 
This controller has been designed for easy writing.  To send a sample to the
 
PWM audio controller, simply write the sample to the controller and clear the
 
PWM audio interrupt.  When the audio interrupts the CPU again, it is ready
 
for the next sample.
 
 
 
The audio sample rate has been fixed at 8~kHz.  While changing this rate is
 
easy to do within {\tt busmaster.v}, the rate itself takes some work to keep
 
up with, so I wouldn't recommend going much (any) faster.
 
 
 
The audio controller supports two additional functionalities, however.  The
 
first is that the {\tt E} bit will be set upon any read when or if the audio
 
controller is ready for another sample.  Equivalently, the audio interrupt
 
will be asserted.
 
 
 
The second functionality has to do with the two auxiliary control bits present
 
in the PModAMP2 audio device.  These are the gain and shutdown bits.  To set
 
these bits, write a sample to the controller while also setting the {\tt E}
 
bit.  When the {\tt E} bit is set upon any write, the shutdown and gain bits
 
will also be set.  (Be aware, the shutdown bit is negative logic.)  Hence, one
 
may start this interface by writing a {\tt 0x0310000} to the device, and later
 
shut it back off by writing a {\tt 0x010000}.
 
 
Audio Controller
\subsection{Special Purpose I/O}
 
 
Register {\tt KYPAD}, as shown in Fig.~\ref{fig:spioreg},
Register {\tt SPIO}, as shown in Fig.~\ref{fig:spioreg},
\begin{figure}\begin{center}
\begin{figure}\begin{center}
\begin{bytefield}[endianness=big]{32}
\begin{bytefield}[endianness=big]{32}
\bitheader{0-31} \\
\bitheader{0-31} \\
\begin{leftwordgroup}{Read}\bitbox[lrt]{16}{Zeros}
\begin{leftwordgroup}{Read}\bitbox[lrt]{16}{Zeros}
        \bitbox[lrt]{4}{Kpad}
        \bitbox[lrt]{4}{Kpad}
Line 245... Line 557...
Specifically, to change an LED, write the new value as well as a `1' to the
Specifically, to change an LED, write the new value as well as a `1' to the
corresponding LED change enable bit.  The same goes for the keypad column
corresponding LED change enable bit.  The same goes for the keypad column
output, a `1' needs to be written to the change enable bit in order for a
output, a `1' needs to be written to the change enable bit in order for a
new value to be accepted.
new value to be accepted.
 
 
 
As examples, writing a {\tt 0x0ff} to the {\tt SPIO} register will turn all
 
LED's on, {\tt 0x0f0} will turn all LED's off, and {\tt 0x011} and {\tt 0x010}
 
will turn LED0 on and then off again respectively.
 
 
The controller will generate a keypad interrupt whenever any row input is
The controller will generate a keypad interrupt whenever any row input is
zero, and a button interrupt whenever any button value is a one.
zero, and a button interrupt whenever any button value is a one.  This also
 
means that, once generated, the interrupt must be disabled until the key or
 
button is released.
 
 
 
\subsection{General Purpose I/O}
The General Purpose Input and Output (GPIO) control register, shown in
The General Purpose Input and Output (GPIO) control register, shown in
Fig.~\ref{fig:gpioreg},
Fig.~\ref{fig:gpioreg},
\begin{figure}\begin{center}
\begin{figure}\begin{center}
\begin{bytefield}[endianness=big]{32}
\begin{bytefield}[endianness=big]{32}
\bitheader{0-31} \\
\bitheader{0-31} \\
Line 261... Line 580...
\caption{GPIO Control Register}\label{fig:gpioreg}
\caption{GPIO Control Register}\label{fig:gpioreg}
\end{center}\end{figure}
\end{center}\end{figure}
is quite simple to use: when read, the top 16--bits indicate
is quite simple to use: when read, the top 16--bits indicate
the value of the 16--input GPIO pins, whereas the bottom 16--bits indicate
the value of the 16--input GPIO pins, whereas the bottom 16--bits indicate
the value being placed on the 16--output GPIO pins.  To change a GPIO pin,
the value being placed on the 16--output GPIO pins.  To change a GPIO pin,
write the new pins value to this register, together with setting the
write the new pin's value to this register, together with setting the
corresponding pin in the upper 16--bits.  For example, to set output pin 0,
corresponding pin in the upper 16--bits.  For example, to set output pin 0,
write a {\tt 0x010001} to the GPIO device.  To clear output pin 0, write a
write a {\tt 0x010001} to the GPIO device.  To clear output pin 0, write a
{\tt 0x010000}.  This makes it possible to adjust some output pins independent
{\tt 0x010000}.  This makes it possible to adjust some output pins independent
of the others.
of the others.
 
 
The GPIO controller, like the keypad or SPIO controller, will also generate
The GPIO controller, like the keypad or SPIO controller, will also generate
an interrupt.  The GPIO interrupt is generated whenever a GPIO input line
an interrupt.  The GPIO interrupt is generated whenever a GPIO input line
changes.
changes.  The interrupt is not selective: if any line changes, a GPIO interrupt
 
will be generated.  There are no do not care lines.
 
 
Of the 16 GPIO inputs and the 16 GPIO outputs, two lines have been taken for
Of the 16 GPIO inputs and the 16 GPIO outputs, two lines have been taken for
I2C support.  GPIO line zero, for both input and output, is an I2C data line,
I2C support.  GPIO line zero, for both input and output, is an I2C data line,
and GPIO line one is an I2C clock line.  If the output of either of these
{\tt io\_sda}, and GPIO line one is an I2C clock line, {\tt io\_scl}.  If the
 
output of either of these
lines is set to zero, the GPIO controller will drive the line.  Otherwise,
lines is set to zero, the GPIO controller will drive the line.  Otherwise,
the line is pulled up with a weak resistor so that other devices may
the line is pulled up with a weak resistor so that other devices may
pull it low.  If either line is low, when the output control bit is high,
pull it low.  If either line is low, when the output control bit is high,
it is an indicator that another device is sending data across these wires.
it is an indicator that another device is sending data across these wires.
 
 
 
\subsection{UART Data Register}
Moving on to the UART \ldots
Moving on to the UART \ldots
although the UART module within the S6~SoC is highly configurable, as built
although the UART module within the S6~SoC is highly configurable, as built
the UART can only handle 9600~Baud, 8--data bits, no parity, and one stop bit.
the UART can only handle 9600~Baud, 8--data bits, no parity, and one stop bit.
There is a single byte data buffer, so reading from the port has a real--time
Changing this involves changing the constant {\tt uart\_setup} within
requirement associated with it.
{\tt busmaster.v}.  Further,  the UART has only a single byte data buffer, so
 
reading from the port has a real--time requirement associated with it--the
 
data buffer must be emptied before the next value is read.
Attempts to read from this port will either return an 8--bit data value from
Attempts to read from this port will either return an 8--bit data value from
the port, or if no values are available it will return an {\tt 0x0100}
the port, or if no values are available it will return an {\tt 0x0100}
indicating that fact.  In a similar fashion, writes to this port will send
indicating that fact.  In general, reading from the UART port involves first
the lower 8--bits of the write out the serial port.  If the port is already
waiting for the interrupt to be ready, second reading from the port itself,
busy, a single byte will be buffered.
and then third immediately  clearing the interrupt.  (The interrupt cannot
 
be cleared while data is waiting.)  Writing to the UART port is done in a
 
similar fashion.  First, wait until the UART transmit interrupt is asserted,
 
second write to the UART port, and then third clear the interrupt.  As with
 
the read interrupt, clearing the interrupt prior to writing to the port will
 
have no effect.
 
 
 
\section{Debugging Scope}
 
The debugging scope consists of two registers, a control register and a data
 
register.  It needs to be internally wired to 32--wires, internal to the S6
 
SoC, that will be of interest later.  For further details on how to configure
 
and use this scope, please see the {\tt WBSCOPE} project on OpenCores.
 
 
 
\section{Internal Configuration Access Port}
 
The Internal Configuration Access Port (ICAP) provides access to the internal
 
configuration details of the FPGA.  This access was designed so as to provide
 
the CPU with the capability to command a different FPGA load.  In particular,
 
the code in Fig.~\ref{fig:reload} should reconfigure the FPGA from any given
 
Quad SPI {\tt address}.\footnote{According to Xilinx's technical support, this
 
will only work if the JTAG port is not busy.}
 
\begin{figure}\begin{center}\begin{tabbing}
 
{\tt warmboot(uint32 address) \{} \\
 
\hbox to 0.25in{}\={\tt uint32\_t *icape6 = (volatile uint32\_t *)0x{\em <ICAPE port address>};}\\
 
 \>{\tt icape6[13] = (address<<2)\&0x0ffff;}\\
 
 \>{\tt icape6[14] = ((address>>14)\&0x0ff)|((0x03)<<8);}\\
 
 \>{\tt icape6[4] = 14;}\\
 
 \>{\em // The CMod~S6 is now reconfiguring itself from the new address.}\\
 
 \>{\em // If all goes well, this routine will never return.}\\
 
{\tt \}}
 
\end{tabbing}
 
\caption{Spartan--6 ICAPE Usage}\label{fig:reload}
 
\end{center}\end{figure}
 
 
 
One subtle problem with this port is that it will not work if the CMod is
 
plugged in to the USB JTAG port.  It will only work if the CMod has been
 
provided with an independent power supply, leaving the USB JTAG unplugged.
 
 
 
For further details, please see either the {\tt WBICAPETWO} project on OpenCores
 
as well as Xilinx's ``Spartan-6 FPGA Configuration User Guide''.
 
 
 
\section{Real--Time Clock}
 
The Real Time Clock will be included if there is enough area to support it.
 
The four registers correspond to a clock, a timer, a stopwatch, and an alarm.
 
If space is tight, the timer and stopwatch, or indeed the entire clock, may be
 
removed from the design.  For further details regarding how to set and use this
 
clock, please see the {\tt RTCCLOCK} project on OpenCores.
 
 
 
There is currently not enough area on the chip to support the Real--Time Clock
 
together with all of the other peripherals listed here.  You can adjust whether
 
the clock is included or not by adjusting the {\tt `define} lines at the top
 
of {\tt busmaster.v}.  For example, it may be possible to get the RTC back by
 
disabling the ICAPE2 interface.
 
 
 
\section{On-Chip Block RAM}
 
 
 
The block RAM is the fastest memory available to the processor.  It is also
 
the {\em only} writeable memory available to the processor.  Hence all
 
non-constant program data {\em must} be placed into block RAM.  The ZipCPU
 
can also run instructions from the block RAM if extra speed is desired.  When
 
runnning from block RAM, the ZipCPU will nominally take 8~clocks per
 
instruction, for an effective rate of 8~MIPS.  Loads or stores to block RAM
 
will take one instruction longer.
 
 
 
\section{Flash Memory}
 
The flash memory has been arbitrarily sectioned into three sections, one for
 
a primary configuration, a second section for an alternate configuration file,
 
and the third section for any program and data.  These regions are shown in
 
Tbl.~\ref{tbl:flash-addresses}.
 
\begin{table}[htbp]
 
\begin{center}\begin{tabular}{|p{0.75in}|p{0.75in}|p{0.5in}|p{3.0in}|}\hline
 
\rowcolor[gray]{0.85} Start & End & & Purpose \\\hline\hline
 
\scalebox{0.9}{\tt 0x400000} & \scalebox{0.9}{\tt 0x43ffff} & R & Primary configuration space\\\hline
 
\scalebox{0.9}{\tt 0x440000} & \scalebox{0.9}{\tt 0x47ffff} & R & Alternate configuration space\\\hline
 
\scalebox{0.9}{\tt 0x480000} & \scalebox{0.9}{\tt 0x7fffff} & R & ZipCPU program memory\\\hline
 
\end{tabular}
 
\caption{Flash Address Regions}\label{tbl:flash-addresses}
 
\end{center}\end{table}
 
The host program {\tt zipload} can be used to load a ZipCPU program and
 
configuration files into this address space.  To use it, first load the
 
alternate configuration into the FPGA.  Then pass it, as arguments, the
 
primary, and alternate if desired, configuration files followed by the ZipCPU
 
program file.  Then, when the primary configuration is loaded again, perhaps
 
upon power up, the ZipCPU will automatically start running from it's
 
{\tt RESET\_ADDRESS}, {\tt 0x480000}.
 
 
 
When running from Flash memory, the ZipCPU will nominally take 52~clocks per
 
instruction, for an effective speed of about 1.5~MIPS.
 
 
\chapter{Clocks}
\chapter{Clocks}
 
 
The S6~SoC is designed to run off of one master clock.  This clock is derived
The S6~SoC is designed to run off of one master clock.  This clock is derived
from the 8~MHz input clock on the board, by multiplying it up to 80~MHz.
from the 8~MHz input clock on the board, by multiplying it up to 80~MHz.

powered by: WebSVN 2.1.0

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