1 |
7 |
dgisselq |
\documentclass{gqtekspec}
|
2 |
|
|
\usepackage{import}
|
3 |
|
|
\usepackage{bytefield}
|
4 |
|
|
\project{CMod S6 SoC}
|
5 |
|
|
\title{Specification}
|
6 |
|
|
\author{Dan Gisselquist, Ph.D.}
|
7 |
|
|
\email{dgisselq (at) opencores.org}
|
8 |
41 |
dgisselq |
\revision{Rev.~0.3}
|
9 |
7 |
dgisselq |
\begin{document}
|
10 |
|
|
\pagestyle{gqtekspecplain}
|
11 |
|
|
\titlepage
|
12 |
|
|
\begin{license}
|
13 |
|
|
Copyright (C) \theyear\today, Gisselquist Technology, LLC
|
14 |
|
|
|
15 |
|
|
This project is free software (firmware): you can redistribute it and/or
|
16 |
|
|
modify it under the terms of the GNU General Public License as published
|
17 |
|
|
by the Free Software Foundation, either version 3 of the License, or (at
|
18 |
|
|
your option) any later version.
|
19 |
|
|
|
20 |
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
21 |
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
22 |
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
23 |
|
|
for more details.
|
24 |
|
|
|
25 |
|
|
You should have received a copy of the GNU General Public License along
|
26 |
|
|
with this program. If not, see \texttt{http://www.gnu.org/licenses/} for a copy.
|
27 |
|
|
\end{license}
|
28 |
|
|
\begin{revisionhistory}
|
29 |
41 |
dgisselq |
0.3 & 5/23/2016 & Gisselquist & Draft for comment, includes ZipOS and PMod
|
30 |
|
|
pin mapping\\\hline
|
31 |
36 |
dgisselq |
0.2 & 5/14/2016 & Gisselquist & Updated Draft, still not complete \\\hline
|
32 |
7 |
dgisselq |
0.1 & 4/22/2016 & Gisselquist & First Draft \\\hline
|
33 |
|
|
\end{revisionhistory}
|
34 |
|
|
% Revision History
|
35 |
|
|
% Table of Contents, named Contents
|
36 |
|
|
\tableofcontents
|
37 |
|
|
\listoffigures
|
38 |
|
|
\listoftables
|
39 |
|
|
\begin{preface}
|
40 |
|
|
The Zip CPU was built with the express purpose of being an area optimized,
|
41 |
|
|
32--bit FPGA soft processor.
|
42 |
|
|
|
43 |
41 |
dgisselq |
The S6~SoC is designed to prove that the Zip~CPU has met this goal.
|
44 |
|
|
|
45 |
|
|
There are two side--effects to this. First, the project proves how capable a
|
46 |
|
|
CMod--S6 is, and second, this project provides demonstration implementations
|
47 |
|
|
of how to interact with a variety of PMod devices: the audio amplifier,
|
48 |
|
|
the serial 2--line LCD display, the USBUART, and the 16--character numeric
|
49 |
|
|
keypad.
|
50 |
7 |
dgisselq |
\end{preface}
|
51 |
|
|
|
52 |
|
|
\chapter{Introduction}
|
53 |
|
|
\pagenumbering{arabic}
|
54 |
|
|
\setcounter{page}{1}
|
55 |
|
|
|
56 |
41 |
dgisselq |
% What is old
|
57 |
|
|
The Zip~CPU is a soft core CPU designed to fit within an FPGA, to use a minimum
|
58 |
|
|
amount of the FPGA's resources, and yet to provide the services of a fully
|
59 |
|
|
capable 32--bit computer. It is based upon a Von~Neumann architecure and so a
|
60 |
|
|
single 32--bit wishbone bus provides it with access to both peripherals and
|
61 |
|
|
memory.
|
62 |
7 |
dgisselq |
|
63 |
41 |
dgisselq |
% What does the old lack?
|
64 |
|
|
Previous demonstrations of the Zip~CPU have focused on larger FPGAs, such as
|
65 |
|
|
the Spartan--6 LX9 and LX25 and the Artix--7 35T. On these FPGA's,
|
66 |
|
|
the Zip~CPU runs in a pipelined configuration where it is tightly integrated
|
67 |
|
|
with a prefetch/instruction cache. While these demonstrations have shown that
|
68 |
|
|
the Zip~CPU can act as a very simple CPU in these environments, they really
|
69 |
|
|
haven't demonstrated the ability of the Zip~CPU to use only a minimum amount
|
70 |
|
|
of the FPGA's resources.
|
71 |
|
|
|
72 |
|
|
% What is new
|
73 |
|
|
The CMod~S6 board provides the opportunity for that demonstration rather nicely.
|
74 |
|
|
% What does the new have that the old lacks
|
75 |
7 |
dgisselq |
\begin{enumerate}
|
76 |
36 |
dgisselq |
\item The Spartan--6 LX4 FPGA is very limited in its resources:
|
77 |
7 |
dgisselq |
It only has 2,400 look--up tables (LUTs), and can only support
|
78 |
|
|
a 4,096~Word RAM memory (16 kB).
|
79 |
|
|
\item With only 4kW RAM, the majority of any program will need to be placed into
|
80 |
41 |
dgisselq |
and run from flash.
|
81 |
7 |
dgisselq |
\item While the chip has enough area for the CPU, it doesn't have enough area
|
82 |
|
|
to include the CPU and \ldots write access to the flash, debug access,
|
83 |
41 |
dgisselq |
wishbone command access from the UART, pipelined CPU operations,
|
84 |
|
|
a prefetch cache and more. Other solutions will need to be found.
|
85 |
7 |
dgisselq |
\end{enumerate}
|
86 |
|
|
|
87 |
|
|
Of course, if someone just wants the functionality of a small, cheap, CPU,
|
88 |
|
|
this project does not fit that role very well. While the S6 is not very
|
89 |
41 |
dgisselq |
expensive at nearly \$70, it is still an order of magnitude greater than it's
|
90 |
|
|
CPU competitors in price. This includes such CPU's as the Raspberry Pi Zero
|
91 |
|
|
(\$5), or even the TeensyLC (\$12).
|
92 |
7 |
dgisselq |
|
93 |
41 |
dgisselq |
% What performance gain can be expected?
|
94 |
7 |
dgisselq |
|
95 |
41 |
dgisselq |
If, on the other hand, what you want is a small, cheap, CPU that can be
|
96 |
|
|
embedded within an FPGA without using too much of the FPGA's resources, this
|
97 |
|
|
project will demonstrate that possibility as well as some utility.
|
98 |
|
|
Alternatively, if you wish to study how to get a CPU to work in a small,
|
99 |
|
|
constrained environment, this project may be what you are looking for.
|
100 |
|
|
|
101 |
|
|
Finally, because the Zip~CPU and the included ZipOS are as small and simple as
|
102 |
|
|
they are, the code base found here will be simpler to understand than the
|
103 |
|
|
code bases for some of these other projects. For example, the Zip~CPU
|
104 |
|
|
instruction set is very simple. With less than 40 instructions, it is much
|
105 |
|
|
easier to understand and learn than the ARM instruction set. Further, unlike
|
106 |
|
|
the ARM, the entire specification for and description of the Zip~CPU is
|
107 |
|
|
publicly available. Likewise, an operating system such as the ZipOS that has
|
108 |
|
|
less than \hbox{3,000} lines of code will be much easier to understand than any
|
109 |
|
|
Linux operating system--even if it has much less functionality.
|
110 |
|
|
|
111 |
7 |
dgisselq |
\chapter{Architecture}
|
112 |
|
|
Fig.~\ref{fig:architecture}
|
113 |
|
|
\begin{figure}\begin{center}
|
114 |
|
|
\includegraphics[width=5in]{../gfx/s6bones.eps}
|
115 |
41 |
dgisselq |
\caption{CMod S6 SoC Architecture: Zip~CPU and
|
116 |
7 |
dgisselq |
Peripherals}\label{fig:architecture}
|
117 |
|
|
\end{center}\end{figure}
|
118 |
41 |
dgisselq |
shows the basic internal architecture of the S6~SoC. In summary, it consists
|
119 |
|
|
of a CPU
|
120 |
7 |
dgisselq |
coupled with a variety of peripherals for the purpose of controlling the
|
121 |
41 |
dgisselq |
external peripherals of the S6~SoC: flash, LEDs, buttons, and GPIO. External
|
122 |
|
|
devices may also be added on, and have been added on as part of this project,
|
123 |
|
|
such as an audio device, an external serial port, an external keypad, and an
|
124 |
|
|
external display. All of these devices are then available for the CPU to
|
125 |
|
|
interact with.
|
126 |
7 |
dgisselq |
|
127 |
|
|
If you are familiar with the Zip CPU, you'll notice this architecture provides
|
128 |
|
|
no access to the Zip CPU debug port. There simply wasn't enough room on the
|
129 |
41 |
dgisselq |
device. Debugging the Zip~CPU will instead need to take place via other means,
|
130 |
7 |
dgisselq |
such as dumping all registers and/or memory to the serial port on any reboot.
|
131 |
|
|
|
132 |
41 |
dgisselq |
Further, the Zip~CPU has no ability to write to flash memory. For this reason,
|
133 |
|
|
there exists an alternate CMod S6~SoC architecture, shown in
|
134 |
7 |
dgisselq |
Fig.~\ref{fig:altarchitecture}.
|
135 |
|
|
\begin{figure}\begin{center}
|
136 |
|
|
\includegraphics[width=5in]{../gfx/altbones.eps}
|
137 |
|
|
\caption{Alternate CMod S6 SoC Architecture: Peripherals, with no
|
138 |
|
|
CPU}\label{fig:altarchitecture}
|
139 |
|
|
\end{center}\end{figure}
|
140 |
|
|
Using this alternate architecture, it should be possible to test the peripherals
|
141 |
|
|
and program the flash memory. Both architectures may be loaded into the flash,
|
142 |
|
|
together with the programming code for the Zip CPU.
|
143 |
|
|
|
144 |
36 |
dgisselq |
The basic approach to loading the board is actually quite simple. Using the
|
145 |
|
|
Digilent ADEPT JTAG configuration program, {\tt djtgcfg}, the alternate
|
146 |
|
|
configuration may be written directly to the device. Once this alternate
|
147 |
41 |
dgisselq |
configuration has been loaded, the flash may be examined and programmed using
|
148 |
|
|
the {\tt zipload} utility. This utility uses Digilent's Asynchronous Parallel
|
149 |
|
|
Port interface (DEPP) to communicate with the device, and in particular to
|
150 |
|
|
tell the device what to write to the flash. When writing to the flash,
|
151 |
|
|
the {\tt zipload} utility will program both a primary and an alternate
|
152 |
|
|
FPGA configuration into the configuration section of the flash, as well as
|
153 |
|
|
computer code into the rest of the flash. Once complete, the system may then be
|
154 |
36 |
dgisselq |
reloaded with the primary configuration file which will contain an image of
|
155 |
|
|
the CPU. The CPU will then begin following the instructions found in flash
|
156 |
|
|
memory.
|
157 |
7 |
dgisselq |
|
158 |
|
|
|
159 |
36 |
dgisselq |
\chapter{Software}
|
160 |
41 |
dgisselq |
This chapter provides an overview of the software that is available to support
|
161 |
|
|
the S6~SoC. This includes not only the RTL, the Makefiles, and the software
|
162 |
|
|
that will run on the Zip~CPU within the S6~SoC, but also the support software
|
163 |
|
|
necessary for communicating with the S6~SoC in its alternate configuration.
|
164 |
|
|
|
165 |
36 |
dgisselq |
\section{Directory Structure}
|
166 |
|
|
\begin{itemize}
|
167 |
|
|
\item[{\tt trunk/bench}] Contains software for emulating the S6 without the S6
|
168 |
|
|
present.
|
169 |
|
|
\begin{itemize}
|
170 |
|
|
\item[{\tt trunk/bench/cpp}] All of the bench testing software is
|
171 |
|
|
written in C++, so it is found in this directory. Primary
|
172 |
|
|
among these programs is the {\tt zip\_sim} program which will
|
173 |
41 |
dgisselq |
simulate the Zip~CPU within the S6~SoC. Specifically, it
|
174 |
36 |
dgisselq |
simulates everything at or below the {\tt busmaster.v} level.
|
175 |
7 |
dgisselq |
|
176 |
36 |
dgisselq |
Some, although not all, of the peripherals have been simulated
|
177 |
|
|
and made a part of this simulation. These include the
|
178 |
|
|
Quad--SPI flash, the UART, and the LED's.
|
179 |
|
|
|
180 |
|
|
\end{itemize}
|
181 |
41 |
dgisselq |
\item[{\tt trunk/doc}] All of the documentation for the S6~SoC project may be
|
182 |
36 |
dgisselq |
found in this documentation directory. Specifically, I would commend
|
183 |
|
|
your attention to anything with a {\tt .pdf} extension, as these
|
184 |
|
|
are the completed documents. Among these you should find a copy of the
|
185 |
|
|
GPL copyright under which this software is released, as well as a
|
186 |
|
|
pre--built copy of this document.
|
187 |
|
|
\begin{itemize}
|
188 |
|
|
\item[{\tt trunk/doc/gfx}] Here is where the graphics are located in
|
189 |
|
|
support of this specification document.
|
190 |
|
|
\item[{\tt trunk/doc/src}] And here is where the \LaTeX files are
|
191 |
|
|
kept that were used in building both this document as well as
|
192 |
|
|
the GPL copyright.
|
193 |
|
|
\end{itemize}
|
194 |
41 |
dgisselq |
\item[{\tt trunk/rtl}] Verilog files. The two top--level files are
|
195 |
|
|
{\tt toplevel.v} for the primary top level module, and
|
196 |
|
|
{\tt alttop.v} for the alternate load.
|
197 |
36 |
dgisselq |
\begin{itemize}
|
198 |
41 |
dgisselq |
\item[{\tt trunk/rtl/cpu}] Verilog files containing the Zip~CPU
|
199 |
36 |
dgisselq |
core and peripherals. The toplevel file here is the
|
200 |
|
|
{\tt zipbones.v} file, although some of the peripherals, such
|
201 |
|
|
as the {\tt ziptimer.v} are referenced independently.
|
202 |
|
|
\end{itemize}
|
203 |
|
|
\item[{\tt trunk/sw}] The main software directory, primarily a repository
|
204 |
|
|
for software subdirectories beneath it.
|
205 |
|
|
\begin{itemize}
|
206 |
|
|
\item[{\tt trunk/sw/dev}] This directory holds a variety of
|
207 |
41 |
dgisselq |
simple programs for the Zip~CPU, such as {\tt helloworld},
|
208 |
36 |
dgisselq |
{\tt doorbell} and {\tt doorbell2}, as well as software drivers
|
209 |
|
|
for various peripherals, such as the real--time clock simulator,
|
210 |
|
|
and the keypad and display device drivers.
|
211 |
|
|
\item[{\tt trunk/sw/host}] This directory holds support software which
|
212 |
|
|
can be built on and run on the host machine. Building this
|
213 |
|
|
software will involve adjusting the Makefile so that it knows
|
214 |
|
|
where your local ADEPT installation directory is.\footnote{Many
|
215 |
|
|
of the programs also depend upon the serial number of my CMod
|
216 |
|
|
S6 device. This will need to be adjusted in any new install.}
|
217 |
|
|
Once built, you will find a variety of very useful programs
|
218 |
|
|
within here.
|
219 |
|
|
\item[{\tt trunk/sw/zipos}] This directory contains the source code for
|
220 |
|
|
a rudimentary, very basic, operating system that I
|
221 |
|
|
call the ZipOS.
|
222 |
|
|
\end{itemize}
|
223 |
|
|
\end{itemize}
|
224 |
|
|
|
225 |
41 |
dgisselq |
\section{Zip CPU Tool Chain}
|
226 |
|
|
To build programs for the Zip~CPU, you will need the Zip~CPU toolchain. You
|
227 |
|
|
can find this as part of the Zip~CPU project, available at OpenCores. Building
|
228 |
|
|
the Zip~CPU project should result in a set of binaries in the
|
229 |
|
|
\hbox{\tt zipcpu/trunk/sw/install/cross-tools/bin} directory. Make this
|
230 |
|
|
directory a part of your path, and you should be able to build the CMod S6
|
231 |
|
|
Zip~CPU software. Specifically, you will need to use {\tt zip-gcc},
|
232 |
|
|
{\tt zip-as}, {\tt zip-ld}, and {\tt zip-cpp}. Other tools, such as
|
233 |
|
|
{\tt zip-objdump} and {\tt zip-readelf}, may also prove to be very useful when
|
234 |
|
|
trying to figure out what is going on within the SoC.
|
235 |
36 |
dgisselq |
|
236 |
|
|
\section{Bench Test Software}
|
237 |
|
|
|
238 |
|
|
Bench testing software currently consists of the {\tt zip\_sim} program found
|
239 |
|
|
within {\tt trunk/bench/cpp}. This program requires Verilator to run, and
|
240 |
41 |
dgisselq |
simulates in a cycle accurate fashion, the entire S6~SoC from {\tt busmaster.v}
|
241 |
36 |
dgisselq |
on down. Further, the external Quad--SPI flash memory, UART, and LED's are
|
242 |
|
|
also simulated, although the 2--line display, audio, and keypad are not.
|
243 |
|
|
|
244 |
|
|
\section{Host Software}
|
245 |
41 |
dgisselq |
Several software programs have been built to support the S6~SoC from a nearby
|
246 |
|
|
host. These programs include:
|
247 |
36 |
dgisselq |
\begin{itemize}
|
248 |
|
|
\item {\tt dumpuart}: My current approach to debugging involves
|
249 |
|
|
dumping the state of the registers and memory to the
|
250 |
|
|
UART upon reboot. The dumpuart command found here is
|
251 |
|
|
designed to make certain that the UART is first set
|
252 |
41 |
dgisselq |
up correctly at 9600~Baud, and second that everything
|
253 |
36 |
dgisselq |
read from the UART is directly sent to both a file and
|
254 |
|
|
to the screen. In this fashion, it is similar to the
|
255 |
|
|
UNIX {\tt tee} program, save for its serial port
|
256 |
|
|
attachment.
|
257 |
|
|
\item {\tt readflash}: As I am loathe to remove anything from
|
258 |
|
|
a device that came factory installed, the
|
259 |
|
|
{\tt readflash} program reads the original installed
|
260 |
|
|
configuration from the flash and dumps it to a file.
|
261 |
|
|
|
262 |
41 |
dgisselq |
This program is only useful when the alternate configuration is loaded.
|
263 |
|
|
|
264 |
|
|
\item {\tt wbregs}: This program offers a capability very similar to the
|
265 |
|
|
PEEK and POKE capability Apple user's may remember from before the
|
266 |
|
|
days of Macintosh. {\tt wbregs <address>} will read from the
|
267 |
|
|
Wishbone bus the value at the given address. Likewise
|
268 |
|
|
{\tt wbregs <address> <value>} will write the given value into the
|
269 |
|
|
given address. While both address and value have the semantics of
|
270 |
|
|
numbers acceptable to {\tt strtoul()}, the address can also be a named
|
271 |
|
|
address. Supported names can be found in {\tt regdefs.cpp}, and their
|
272 |
|
|
register mapping in {\tt regdefs.h}.
|
273 |
|
|
|
274 |
|
|
As examples, {\tt wbregs version}, will return the build date, or
|
275 |
|
|
version of the RTL. {\tt wbregs spio} reads the special purpose
|
276 |
|
|
I/O register, and {\tt wbregs gpio 0xffffffff} will set all output
|
277 |
|
|
GPIO ports high while {\tt wbregs gpio 0xffff0000} will set all
|
278 |
|
|
output GPIO ports to ground.
|
279 |
|
|
|
280 |
|
|
This program is only useful when the alternate configuration is loaded.
|
281 |
|
|
|
282 |
|
|
\item {\tt zipload}: This is the primary program you will need to get your
|
283 |
|
|
software loaded on the CMod. It takes three arguments. The first is
|
284 |
|
|
the name of the primary Xilinx configuration file, the second is the
|
285 |
|
|
name of an alternate Xilinx configuration file, and the third is the
|
286 |
|
|
name of the Zip~CPU program you wish to write to Flash memory.
|
287 |
|
|
|
288 |
|
|
Each of these arguments is optional. For example, if only one
|
289 |
|
|
configuration file is given, the loader will load the primary
|
290 |
|
|
configuration. If only one Zip~CPU program is given, the program will
|
291 |
|
|
be loaded into the program memory area and the configuration file areas
|
292 |
36 |
dgisselq |
will be left untouched.
|
293 |
41 |
dgisselq |
|
294 |
|
|
This program is only useful when the alternate configuration is loaded.
|
295 |
36 |
dgisselq |
\end{itemize}
|
296 |
41 |
dgisselq |
\section{Zip CPU Programs}
|
297 |
|
|
The following are a list of simple, independent, single-task example programs
|
298 |
|
|
that will run on the S6~SoC:
|
299 |
36 |
dgisselq |
\begin{itemize}
|
300 |
|
|
\item {\tt helloworld}: The first program any programmer should build,
|
301 |
|
|
``Hello, world!'' This program sends the string, ``Hello, world!''
|
302 |
|
|
over the UART connection once per second. It is a very valuable
|
303 |
|
|
program because, if you can get this program running, you know you have
|
304 |
|
|
a lot of things working and working correctly. For example, running
|
305 |
|
|
this program means you can run the {\tt zip-gcc} compiler, load
|
306 |
|
|
the auxiliar configuration, load the program info flash memory, load
|
307 |
|
|
the primary configuration, and read from the UART port. It also means
|
308 |
|
|
that you must have the UART port properly configured and wired to your
|
309 |
|
|
CMod board.
|
310 |
|
|
\item {\tt doorbell}: This annoying program verifies the functionality of the
|
311 |
|
|
audio device by playing a doorbell sound to the audio port. It will
|
312 |
|
|
then wait ten seconds, and play the doorbell sound again (and again,
|
313 |
|
|
and again). (It gets old after a while ...)
|
314 |
|
|
\item {\tt doorbell2}: This adds to the functionality of the {\tt doorbell}
|
315 |
|
|
program a wait for keypress, and a display of the current time on the
|
316 |
|
|
2--line display. While almost our fully functional program, this
|
317 |
|
|
does not include any menus to configure the device or set time, since
|
318 |
|
|
it doesn't include any keypad functionality.
|
319 |
|
|
\item {\tt kptest}: A test of whether or not they keypad driver works. When
|
320 |
41 |
dgisselq |
run, anytime a key is pressed, the key's associated printable character
|
321 |
|
|
will be sent to the UART. Further, pressing an `F' on the keypad will
|
322 |
|
|
also send a newline over the UART, in case you wish to keep your lines
|
323 |
|
|
from getting too long.
|
324 |
36 |
dgisselq |
\end{itemize}
|
325 |
|
|
\section{ZipOS}
|
326 |
41 |
dgisselq |
The ZipOS is a brand new operating system, specifically designed to run on the
|
327 |
|
|
ZipCPU. It is both pre--emptive and multitasking, although with many
|
328 |
|
|
limitations. Those familiar with the internals of other operating systems, such
|
329 |
|
|
as Linux, may laugh that I call this an Operating System at all: it has no
|
330 |
|
|
memory management unit, no paging, no virtual memory, no file I/O access, no
|
331 |
|
|
network stack, no ability to dynamically add or remove tasks, indeed it hardly
|
332 |
|
|
has any of the things most often associated with an Operating System. It does,
|
333 |
|
|
however, handle interrupts, support multiple pre--emptive tasks in a
|
334 |
|
|
multitasking, timesharing fashion, and it supports some very basic and
|
335 |
|
|
rudimentary system calls. In a similar fashion, it does contain just about all
|
336 |
|
|
of the functionality necessary for a multi--tasking microcontroller built
|
337 |
|
|
around a do--forever loop. For its size, I consider it an impressive
|
338 |
|
|
achievement. You are welcome to disagree with me, however.
|
339 |
36 |
dgisselq |
|
340 |
41 |
dgisselq |
This version of the ZipOS starts in the {\tt resetdump.s} code, so that upon
|
341 |
36 |
dgisselq |
any startup the ZipOS will dump register contents, the BusError register, and
|
342 |
|
|
any scope contents to the UART. This can take some time, so you may wish to
|
343 |
41 |
dgisselq |
configure what you really wish to send--if anything. If desired,
|
344 |
|
|
{\tt resetdump} can also be configured to also dump the entire memory as well
|
345 |
|
|
while only using 9~memory locations. All of this is quite useful in case the
|
346 |
|
|
Zip~CPU encounters a bus error or other sort of error that causes it to hang,
|
347 |
|
|
stall, or reboot, as the CPU registers are very carefully not touched prior to
|
348 |
|
|
being sent to the UART output port. This extends to all registers save the
|
349 |
|
|
supervisor PC and CC registers, which would've been reset by a reboot anyway.
|
350 |
36 |
dgisselq |
|
351 |
41 |
dgisselq |
{\tt resetdump.s} then calls a rudimentary bootloader, to load the parts of
|
352 |
36 |
dgisselq |
the ZipOS that need to run faster into Block RAM. The choice of what parts
|
353 |
|
|
to load into Block RAM is made on a file by file basis, and found within
|
354 |
|
|
the linker script, {\tt cmodram.ld}.
|
355 |
|
|
|
356 |
|
|
Upon completion, {\tt resetdump.s} calls the entry routine for the O/S,
|
357 |
|
|
{\tt kernel\_entry()} found in {\tt kernel.c}. This is the main task loop for
|
358 |
|
|
the entire O/S, and worth studying if you are interested in understanding how
|
359 |
|
|
the O/S works.
|
360 |
|
|
|
361 |
|
|
The user tasks are found (mostly) within {\tt doorbell.c}, also found in the
|
362 |
|
|
ZipOS directory. This file contains two kernel entry points, {\tt kntasks()},
|
363 |
41 |
dgisselq |
which returns the number of user tasks the kernel needs to know about, and
|
364 |
36 |
dgisselq |
{\tt kinit()}, which builds each of the tasks and connects their file
|
365 |
|
|
descriptors to the various devices they will be referencing.
|
366 |
41 |
dgisselq |
\subsection{System Calls}
|
367 |
|
|
The ZipOS supports a variety of system calls, listed here:
|
368 |
36 |
dgisselq |
\begin{itemize}
|
369 |
41 |
dgisselq |
\item {\tt int wait(unsigned event\_mask, int timeout)}
|
370 |
|
|
|
371 |
|
|
Halts the execution of a process until an event matching the
|
372 |
|
|
{\tt event\_mask} takes place, or a {\tt timeout} (in milliseconds)
|
373 |
|
|
has been reached. The events that can take place are a
|
374 |
36 |
dgisselq |
bitmask of the various interrupts the CPU supports, together with a
|
375 |
41 |
dgisselq |
bitmask of the software interrupt values found in {\tt swint.h}.
|
376 |
36 |
dgisselq |
|
377 |
41 |
dgisselq |
The {\tt timeout} value can either be zero, to return immediately with
|
378 |
|
|
the list of events that have taken place, negative, to wait
|
379 |
|
|
indefinitely, or a positive number of milliseconds in order to wait at
|
380 |
|
|
least that time for the event of interest to take place.
|
381 |
36 |
dgisselq |
|
382 |
41 |
dgisselq |
Waiting on a zero event mask allows a process to sleep for any number
|
383 |
|
|
of requested milliseconds.
|
384 |
36 |
dgisselq |
|
385 |
|
|
When wait returns, any events returned by the wait have been cleared.
|
386 |
|
|
|
387 |
|
|
The other thing to be aware of is that events may accumulate before the
|
388 |
41 |
dgisselq |
wait system call. Nothing within the wait system call clears prior
|
389 |
|
|
events. These prior events be returned and cleared, though, if
|
390 |
|
|
the wait call indicates an interest in those events.
|
391 |
|
|
|
392 |
|
|
Upon return, the a bitmask of events that have taken place will be
|
393 |
|
|
returned to the process.
|
394 |
|
|
|
395 |
|
|
\item {\tt int clear(unsigned event\_mask, int timeout)}
|
396 |
|
|
|
397 |
|
|
This system call works closely with the wait system call. Indeed,
|
398 |
|
|
when the timeout given is zero, the two function nearly identically.
|
399 |
|
|
It clears any of the requested events which may be pending, and returns
|
400 |
|
|
a bit mask of the events that were pending and cleared.
|
401 |
|
|
|
402 |
|
|
However, if the timeout is given (and is positive), then {\tt clear()}
|
403 |
|
|
starts a timer. Once the timer has completed, a timeout event,
|
404 |
|
|
{\tt SWINT\_TIMEOUT}, will be generated and made available to the task
|
405 |
|
|
to wait upon it.
|
406 |
|
|
|
407 |
|
|
In a similar fashion, if the timeout is negative, then any pending
|
408 |
|
|
timeout is cleared.
|
409 |
|
|
|
410 |
|
|
\item {\tt void post(unsigned event\_mask)}
|
411 |
|
|
|
412 |
|
|
Certain devices, such as the real--time clock and the doorbell
|
413 |
36 |
dgisselq |
reader, need the ability of being able to post events to any listener
|
414 |
|
|
within the O/S. The POST system call allows them to POST events in
|
415 |
|
|
this manner.
|
416 |
41 |
dgisselq |
|
417 |
|
|
Were the ZipOS to be closer to a secure O/S, it might restrict what
|
418 |
|
|
events each process could post. Right now, however, any process can
|
419 |
|
|
post any event--whether it be a hardware or a software generated event.
|
420 |
|
|
|
421 |
|
|
\item {\tt void yield(void) }
|
422 |
|
|
|
423 |
|
|
This is simply a way of being nice to other processes. This system
|
424 |
36 |
dgisselq |
call takes no arguments and simply asks the scheduler to schedule the
|
425 |
|
|
next process. It does not take this process off of the ready to run
|
426 |
|
|
list, so the next process may be this one. However, since the scheduler
|
427 |
41 |
dgisselq |
is a round--robin scheduler, it will only return to this process once
|
428 |
|
|
it has gone through all other available processes checking whether or
|
429 |
|
|
not they are available to be run.
|
430 |
|
|
|
431 |
|
|
\item {\tt int read(int fid, void *buf, int len)}
|
432 |
|
|
|
433 |
|
|
This is roughly the same system call as the POSIX read() system
|
434 |
|
|
call. It reads some number of words (not octets) from the file
|
435 |
|
|
descriptor (device) specified by {\tt fid} into the memory address
|
436 |
|
|
range starting at {\tt buf} and {\tt len} words long. If the memory
|
437 |
|
|
requested is unavailable,
|
438 |
36 |
dgisselq |
the read will wait until it is available, possibly indefinitely.
|
439 |
41 |
dgisselq |
|
440 |
|
|
Upon return, the {\tt read()} function call returns the number of
|
441 |
|
|
words actually read, or a negative value on error.
|
442 |
|
|
|
443 |
|
|
As a future feature, a {\tt read()} system call should be able to be
|
444 |
|
|
interrupted by a timeout. This feature has not (yet) been implemented,
|
445 |
|
|
but will likely be implemented via a combination of the {\tt clear()}
|
446 |
|
|
system calls ability to set timeouts together with the {\tt read()}
|
447 |
|
|
functions ability to wait for available data.
|
448 |
|
|
|
449 |
|
|
\item {\tt int write(int fid, void *buf, int len)}
|
450 |
|
|
|
451 |
|
|
This is roughly the same system call as the POSIX {\tt write()} system
|
452 |
36 |
dgisselq |
call. It writes some number of memory addresses (words, not octets),
|
453 |
41 |
dgisselq |
to the given file descriptor. If there is no reader task or device
|
454 |
|
|
associated with the file descriptor, then the {\tt write()} system
|
455 |
|
|
call will block forever once the internal pipe fills up. Otherwise,
|
456 |
|
|
if something is reading from the file descriptor's pipe, the writing
|
457 |
|
|
task will only stall until the data is either written to the receiving
|
458 |
|
|
task, or copied into a memory buffer.
|
459 |
|
|
|
460 |
|
|
Upon return, the {\tt write()} system call returns the number of words
|
461 |
|
|
actually written to the system pipe (not necessarily the number that
|
462 |
|
|
have been read), or a negative value on error.
|
463 |
|
|
|
464 |
|
|
\item {\tt unsigned time(void) }
|
465 |
|
|
|
466 |
|
|
Returns the number of seconds since startup. Eventually, this will
|
467 |
36 |
dgisselq |
return the number of seconds since January 1, 1970, and be identical
|
468 |
|
|
to the UNIX system time() command, but that may not happen on this
|
469 |
|
|
project.
|
470 |
41 |
dgisselq |
|
471 |
36 |
dgisselq |
% \item SEMGET
|
472 |
|
|
% \item SEMPUT
|
473 |
41 |
dgisselq |
|
474 |
|
|
\item {\tt void *malloc(void)}
|
475 |
|
|
|
476 |
|
|
Allocates memory from the system/kernel heap. This is a very low
|
477 |
|
|
overhead memory allocator that, while it does allocate memory, cannot
|
478 |
|
|
free it later. It is nearly 100\% efficient since only one memory
|
479 |
|
|
address, the top of the heap, is used to determine what memory has
|
480 |
|
|
been allocated.
|
481 |
|
|
|
482 |
|
|
\item {\tt void free(void *buf)}
|
483 |
|
|
|
484 |
|
|
This function is a do--nothing stub.
|
485 |
|
|
|
486 |
36 |
dgisselq |
\end{itemize}
|
487 |
|
|
\subsection{Scheduler}
|
488 |
41 |
dgisselq |
The ZipOS currently supports only a round--robin scheduler. Tasks are executed
|
489 |
36 |
dgisselq |
in the order they were created, as long as they are available to be executed.
|
490 |
|
|
If no tasks are available to be run, the Scheduler will run the idle task which
|
491 |
|
|
puts the CPU to sleep while waiting for an interrupt.
|
492 |
|
|
|
493 |
7 |
dgisselq |
\chapter{Operation}
|
494 |
41 |
dgisselq |
The {\tt doorbell} program has been built to illustrate the operation of both
|
495 |
|
|
the Zip~CPU, the ZipOS, as well as showing off how all of the various
|
496 |
|
|
peripherals work. It was envisioned after my family and I experienced an
|
497 |
|
|
unexpected visitor during the wee hours of the morning. The {\tt doorbell}
|
498 |
|
|
program is designed to couple the doorbell and the exterior lights to a
|
499 |
|
|
single button. Hence, when the doorbell to the house is pressed, the exterior
|
500 |
|
|
light is turned on for a half an hour. This, then, would make it difficult
|
501 |
|
|
for someone to see inside during this time.
|
502 |
7 |
dgisselq |
|
503 |
41 |
dgisselq |
This chapter will present an example of how the {\tt doorbell} program works.
|
504 |
|
|
|
505 |
|
|
To run the {\tt doorbell} program, you will first need to build the various
|
506 |
|
|
RTL and software support programs just to get the {\tt doorbell} program on
|
507 |
|
|
the device:
|
508 |
|
|
\begin{enumerate}
|
509 |
|
|
\item First build the primary and alternate .bit files by building
|
510 |
|
|
with {\tt toplevel.v} and then {\tt alttop.v} as your top--level
|
511 |
|
|
RTL files. I like to place my Xilinx work directoy into
|
512 |
|
|
{\tt trunk/xilinx}, and if you do the same the load scripts that
|
513 |
|
|
are referenced next will work.
|
514 |
|
|
|
515 |
|
|
Before going on, double check that both configuration .bit files were
|
516 |
|
|
created, that they each fit within the device (there would be errors
|
517 |
|
|
if they did not), and that they met their respective timing
|
518 |
|
|
requirements.
|
519 |
|
|
|
520 |
|
|
\item Then, load the alternate bit file into the S6~SoC. You will need
|
521 |
|
|
the Digilent tools installed in order to do this. Having done so,
|
522 |
|
|
you may run {\tt make axload} from the {\tt trunk/} directory.
|
523 |
|
|
If you didn't run the Xilinx ISE from within {\tt tunk/xilinx},
|
524 |
|
|
you may need to find your .bit files and adjust where they load
|
525 |
|
|
from, but this should be fairly straight--forward from the instructions
|
526 |
|
|
within the Makefile.
|
527 |
|
|
\item Build the software found in the host directory. This sotware depends
|
528 |
|
|
upon Digilent's ADEPT toolsuite, so you will need to adjust the
|
529 |
|
|
Makefile so that it references the toolsuite.
|
530 |
|
|
|
531 |
|
|
{\em Note:} Currently, the host software is serial--number locked to
|
532 |
|
|
my own CMod--S6. Until I fix this and make it more user friendly,
|
533 |
|
|
you'll want to switch your software to reference your own CMod.
|
534 |
|
|
To do this, look for the {\tt "SN:\ldots"} lines within the `*.cpp'
|
535 |
|
|
files. Currently, there is one such line within wbregs, another
|
536 |
|
|
within readflash, and the last within zipload. To find our your own
|
537 |
|
|
device's serial number, type {\tt djtgcfg enum}. It should find one
|
538 |
|
|
(or more) CMod devices connected to your system, and list each of
|
539 |
|
|
their serial numbers.
|
540 |
|
|
|
541 |
|
|
Once you've done this, you should have a working set of host support
|
542 |
|
|
programs: readflash, wbregs, and zipload.
|
543 |
|
|
|
544 |
|
|
\item Using {\tt wbregs}, you may now test your configuration. {\tt wbregs}
|
545 |
|
|
works like the peek and poke programs from a generation ago.
|
546 |
|
|
{\tt wbregs <address>} will return the value of the memory (or
|
547 |
|
|
peripheral) found at the {\tt <address>}. Some addresses have names,
|
548 |
|
|
such as {\tt UART}, {\tt SPIO}, {\tt GPIO}, {\tt PIC}, and so forth.
|
549 |
|
|
These names are found in {\tt trunk/sw/host/regdefs.cpp}, and their
|
550 |
|
|
mappings in {\tt trunk/sw/host/regdefs.h}.
|
551 |
|
|
|
552 |
|
|
As examples, if you type {\tt wbregs version} you should be able
|
553 |
|
|
to read the version (a.k.a. build date) from the currently installed
|
554 |
|
|
.bit file. Likewise if you type {\tt wbregs uart 65}, you should see
|
555 |
|
|
an `A' (i.e. a 65) sent from the S6~SoC over the serial port.
|
556 |
|
|
{\tt wbregs uart} by itself will read a single character from the
|
557 |
|
|
serial port and so on.
|
558 |
|
|
|
559 |
|
|
You should be able to test all of your peripherals by hand using
|
560 |
|
|
{\tt wbregs}: GPIO, Flash, UART, keypad, buttons, LEDs, Interrupt
|
561 |
|
|
controller, timer, etc.\footnote{The display and audio devices may be
|
562 |
|
|
more difficult since these require multiple interactions over the
|
563 |
|
|
course of a short period of time to work.} This should give you some
|
564 |
|
|
confidence in how these peripherals work, should you need it. You
|
565 |
|
|
may also use this time to verify that your wiring is properly set up.
|
566 |
|
|
|
567 |
|
|
\item If you wish to make certain you keep track of the original Flash bitfile
|
568 |
|
|
that came with your device, you may read it out using {\tt readflash}.
|
569 |
|
|
This will dump the contents of you flash onto {\tt qspiflash.bin}.
|
570 |
|
|
You may then wish to change the name of this file, lest you overwrite
|
571 |
|
|
it by running {\tt readflash} again later.
|
572 |
|
|
|
573 |
|
|
\item At this point, it's time to build the programs for the Zip~CPU. To do
|
574 |
|
|
this, you will first need to download the Zip~CPU project. When
|
575 |
|
|
building that project, it will create a directory of programs
|
576 |
|
|
(including its compiler) in
|
577 |
|
|
{\tt zipcpu/trunk/sw/install/cross-tools/bin}.
|
578 |
|
|
Include this directory into your path.
|
579 |
|
|
|
580 |
|
|
\item Change into {\tt trunk/sw/dev} to build some device testing files.
|
581 |
|
|
{\tt make} by itself should build some of these.
|
582 |
|
|
|
583 |
|
|
You should now be ready to run some basic tests on the S6~SoC.
|
584 |
|
|
|
585 |
|
|
\item Let's test the UART first: back out to the main directory {\tt trunk/},
|
586 |
|
|
and run\break
|
587 |
|
|
{\tt sw/host/zipload sw/dev/helloworld} and then {\tt make xload}.
|
588 |
|
|
Now, examine your UART port. (You do have the PModUSBUART installed
|
589 |
|
|
and connected, right?) You should see ``Hello, world!'' printed
|
590 |
|
|
over and over again once each second.
|
591 |
|
|
|
592 |
|
|
\item You may try other test files in a similar manner, such as
|
593 |
|
|
{\tt trunk/sw/dev/doorbell} and\break
|
594 |
|
|
{\tt trunk/sw/dev/doorbell2}. The first of these will just play the
|
595 |
|
|
doorbell over and over again, whereas the second one will wait for a
|
596 |
|
|
button press before playing the doorbell sound.
|
597 |
|
|
|
598 |
|
|
\item Now let's go and build the ZipOS together with it's user files. To do
|
599 |
|
|
this, enter into the {\tt trunk/sw/zipos} directory and type
|
600 |
|
|
{\tt make}. If all goes well, you should now have a program named
|
601 |
|
|
{\tt trunk/sw/zipos/doorbell} which you can load into your S6~SoC as
|
602 |
|
|
well.
|
603 |
|
|
|
604 |
|
|
\item A final load, and we'll be done. To do this, make {\tt axload} again,
|
605 |
|
|
and this time {\tt sw/host/zipload xilinx/toplevel.bit sw/zipos/doorbell}.
|
606 |
|
|
When you power on your device the next time, or after you
|
607 |
|
|
{\tt make xload}, you'll find the ZipOS running on the Zip~CPU.
|
608 |
|
|
|
609 |
|
|
\item To test the doorbell, press one of the buttons. You should hear a
|
610 |
|
|
doorbell coming out of the PModAMP2 audio port.
|
611 |
|
|
|
612 |
|
|
\item You should also be able to read the time on the LCD display. It will be
|
613 |
|
|
the wrong time (the number of seconds since power on \ldots). To set
|
614 |
|
|
the correct time, press `A' on the keypad and then type in the 6--digit
|
615 |
|
|
time: HHMMSS.
|
616 |
|
|
|
617 |
|
|
If you make a mistake, the `C' key can be used for a backspace.
|
618 |
|
|
|
619 |
|
|
\item You can also set the time of ``dawn'' by pressing a `B' on the keypad
|
620 |
|
|
and then typing in the time ``dawn'' should be at. The same is
|
621 |
|
|
true for dusk, only you'll need to start that by pressing a `C' on the
|
622 |
|
|
keypad.
|
623 |
|
|
|
624 |
|
|
\item Now, when the doorbell rings, the LCD will show the time the doorbell
|
625 |
|
|
was pressed. If the time is at night, the ourdoor light (oops, I
|
626 |
|
|
mean LED\#3) will turn on for a half an hour (currently set to
|
627 |
|
|
30~seconds, since I don't have the patience to wait a half hour while
|
628 |
|
|
testing).
|
629 |
|
|
\end{enumerate}
|
630 |
|
|
|
631 |
|
|
Now that you've made it this far, you can go back and examine what was done
|
632 |
|
|
along the way, and perhaps even modify it for your own personal application.
|
633 |
|
|
|
634 |
7 |
dgisselq |
\chapter{Registers}
|
635 |
|
|
There are several address regions on the S6~SoC, as shown in
|
636 |
|
|
Tbl.~\ref{tbl:memregions}.
|
637 |
|
|
\begin{table}[htbp]
|
638 |
|
|
\begin{center}\begin{tabular}{|p{0.75in}|p{0.75in}|p{0.5in}|p{3.0in}|}\hline
|
639 |
|
|
\rowcolor[gray]{0.85} Start & End & & Purpose \\\hline\hline
|
640 |
|
|
\scalebox{0.9}{\tt 0x000100} & \scalebox{0.9}{\tt 0x000107} & R/W & Peripheral I/O Control \\\hline
|
641 |
|
|
\scalebox{0.9}{\tt 0x000200} & \scalebox{0.9}{\tt 0x000201} & R/(W) & Debugging scope\\\hline
|
642 |
|
|
\scalebox{0.9}{\tt 0x000400} & \scalebox{0.9}{\tt 0x00043f} & R/W & Internal Configuration Access Port\\\hline
|
643 |
|
|
\scalebox{0.9}{\tt 0x000800} & \scalebox{0.9}{\tt 0x000803} & R/W & RTC Clock (if present)\\\hline
|
644 |
|
|
\scalebox{0.9}{\tt 0x002000} & \scalebox{0.9}{\tt 0x002fff} & R/W & 16kB On-Chip Block RAM \\\hline
|
645 |
|
|
\scalebox{0.9}{\tt 0x400000} & \scalebox{0.9}{\tt 0x7fffff} & R & 16~MB SPI Flash memory\\\hline
|
646 |
|
|
\end{tabular}
|
647 |
|
|
\caption{Address Regions}\label{tbl:memregions}
|
648 |
|
|
\end{center}\end{table}
|
649 |
|
|
In general, the address regions that are made up of RAM or flash act like
|
650 |
|
|
memory. The RAM can be read and written, and the flash acts like read only
|
651 |
41 |
dgisselq |
memory.\footnote{The Flash can be written, but only by an external command
|
652 |
|
|
while in the alternate configuration.}
|
653 |
7 |
dgisselq |
|
654 |
41 |
dgisselq |
This isn't quite true with the other address regions. Accessing the I/O
|
655 |
|
|
region, while it will act like a memory, it may also have side-effects. For
|
656 |
|
|
example, reading from the debugging scope device's data port will read a word
|
657 |
|
|
from the scope's buffer and advance the buffer pointer. (More on that later.)
|
658 |
7 |
dgisselq |
|
659 |
41 |
dgisselq |
Finally, to keep the address decoder simple, many of these addresses are
|
660 |
|
|
multiply mapped. Hence you may find the I/O peripherals mapped throughout the
|
661 |
|
|
{\tt 0x0100}--{\tt 0x01ff} address region. Other memory addresses are similarly
|
662 |
|
|
overmapped. This overmapping was a resource minimization feature, to get the
|
663 |
|
|
bus to fit within a minimum number of FPGA resources.
|
664 |
|
|
|
665 |
36 |
dgisselq |
\section{Peripheral I/O Control}
|
666 |
7 |
dgisselq |
Tbl.~\ref{tbl:ioregs}
|
667 |
|
|
\begin{table}[htbp]
|
668 |
|
|
\begin{center}\begin{reglist}
|
669 |
|
|
PIC &\scalebox{0.8}{\tt 0x0100} & 32 & R/W & Interrupt Controller \\\hline
|
670 |
|
|
BUSERR &\scalebox{0.8}{\tt 0x0101} & 32 & R & Last Bus Error Address\\\hline
|
671 |
|
|
TIMA &\scalebox{0.8}{\tt 0x0102} & 32 & R/W & ZipTimer A\\\hline
|
672 |
|
|
TIMB &\scalebox{0.8}{\tt 0x0103} & 32 & R/W & ZipTimer B\\\hline
|
673 |
|
|
PWM &\scalebox{0.8}{\tt 0x0104} & 32 & R/W & PWM Audio Controller\\\hline
|
674 |
36 |
dgisselq |
SPIO &\scalebox{0.8}{\tt 0x0105} & 32 & R/W & Special Purpose I/O, Keypad, LED Controller \\\hline
|
675 |
7 |
dgisselq |
GPIO &\scalebox{0.8}{\tt 0x0106} & 32 & R/W & GPIO Controller \\\hline
|
676 |
|
|
UART &\scalebox{0.8}{\tt 0x0107} & 32 & R/W & UART data\\\hline
|
677 |
41 |
dgisselq |
VERSION &\scalebox{0.8}{\tt 0x0108} & 32 & R & Build date\\\hline
|
678 |
7 |
dgisselq |
\end{reglist}
|
679 |
|
|
\caption{I/O Peripheral Registers}\label{tbl:ioregs}
|
680 |
|
|
\end{center}\end{table}
|
681 |
|
|
shows the addresses of various I/O peripherals included as part of the SoC.
|
682 |
41 |
dgisselq |
We'll walk through each of these peripherals in turn, describing how they work.
|
683 |
7 |
dgisselq |
|
684 |
36 |
dgisselq |
\subsection{Interrupt Controller}
|
685 |
41 |
dgisselq |
The programmable interrupt controller (PIC) is identical to the one found with
|
686 |
|
|
the ZipSystem. The layout of the PIC bits is shown in Fig.~\ref{fig:picreg}.
|
687 |
36 |
dgisselq |
\begin{figure}\begin{center}
|
688 |
|
|
\begin{bytefield}[endianness=big]{32}
|
689 |
|
|
\bitheader{0-31} \\
|
690 |
|
|
\bitbox{1}{E}
|
691 |
41 |
dgisselq |
\bitbox{15}{Enabled Ints}
|
692 |
36 |
dgisselq |
\bitbox{1}{A}
|
693 |
41 |
dgisselq |
\bitbox{15}{Currently Active Ints}
|
694 |
36 |
dgisselq |
\\
|
695 |
|
|
\end{bytefield}
|
696 |
|
|
\caption{Programmable Interrupt Control (PIC) Register}\label{fig:picreg}
|
697 |
|
|
\end{center}\end{figure}
|
698 |
|
|
This controller supports up to fifteen interrupts, however only twelve are
|
699 |
41 |
dgisselq |
defined within the SoC. These are listed in Tbl.~\ref{tbl:hw-ints}.
|
700 |
|
|
\begin{table}[htbp]
|
701 |
|
|
\begin{center}\begin{tabular}{|p{0.9in}|p{0.75in}|p{3.75in}|}\hline
|
702 |
|
|
\rowcolor[gray]{0.85} Name & Bit Mask & Description \\\hline\hline
|
703 |
|
|
INT\_BUTTON & 0x001 & A Button has been pressed. \\\hline
|
704 |
|
|
INT\_BUSERR & 0x002 & A Wishbone bus error has taken place\\\hline
|
705 |
|
|
INT\_SCOPE & 0x004 & The Scope has completed its collection\\\hline
|
706 |
|
|
INT\_RTC & 0x008 & An alarm or timer has taken place (assuming the RTC
|
707 |
|
|
is installed, and includes both alarm or timer)\\\hline
|
708 |
|
|
INT\_TIMA & 0x010 & Timer-A has reached zero\\\hline
|
709 |
|
|
INT\_TIMB & 0x020 & Timer-B has reached zero\\\hline
|
710 |
|
|
INT\_UARTRX & 0x040 & A character has been received via the UART\\\hline
|
711 |
|
|
INT\_UARTTX & 0x080 & The transmit UART is idle, and ready for its next
|
712 |
|
|
character.\\\hline
|
713 |
|
|
INT\_KEYPAD & 0x100 & One of the keypad wires has been pulled low. \\\hline
|
714 |
|
|
INT\_AUDIO & 0x200 & The audio device is ready for its next sample\\\hline
|
715 |
|
|
INT\_GPIO & 0x400 & The GPIO input lines have changed values.\\\hline
|
716 |
|
|
INT\_FLASH & 0x800 & The flash device has finished either its erase or
|
717 |
|
|
write cycle, and is ready for its next command. (Alternate
|
718 |
|
|
config only.)\\\hline
|
719 |
|
|
\end{tabular}
|
720 |
|
|
\caption{Hardware Interrupts}\label{tbl:hw-ints}
|
721 |
|
|
\end{center}\end{table}
|
722 |
|
|
If any interrupt line is active, the PIC controller
|
723 |
|
|
will have that bit set among its active set. Once set, the bit and hence the
|
724 |
36 |
dgisselq |
interrupt can only be cleared by writing to the controller. Interrupts can
|
725 |
|
|
also be enabled as well. The enabled bit mask controls which interrupt lines
|
726 |
|
|
are permitted to interrupt the CPU. Hence, just because an interrupt is active
|
727 |
41 |
dgisselq |
doesn't mean it will interrupt the CPU--the corresponding bit in the enable
|
728 |
|
|
mask must be set as well.
|
729 |
36 |
dgisselq |
Finally, then {\tt A} or {\tt ANY} bit will be high if any interrupts are both
|
730 |
|
|
enabled and active, whereas the {\tt E} or global interrupt enable bit can be
|
731 |
|
|
set to allow the PIC to interrupt the CPU or cleared to disable all interrupts.
|
732 |
7 |
dgisselq |
|
733 |
36 |
dgisselq |
To keep operations on this register atomic, most of the bits of this register
|
734 |
|
|
have special meanings upon write. The one exception to this is the global
|
735 |
|
|
interrupt enable bit. On any write, interrupts will be globally enabled or
|
736 |
|
|
disabled based upon the value of this bit. Further, the {\tt ANY} bit is a
|
737 |
|
|
read only bit, so writes to it have no effect.
|
738 |
|
|
|
739 |
|
|
Enabling specific interrupts, via writes to the enable lines, are different.
|
740 |
|
|
To enable a specific interrupt, enable all interrupts and
|
741 |
41 |
dgisselq |
set the mask bit associated with the specific interrupt you wish to enable.
|
742 |
|
|
Hence writing a {\tt 0x80010000} will enable interrupt line zero
|
743 |
|
|
({\tt INT\_BUTTON}), while also enabling all previously enabled interrupts.
|
744 |
36 |
dgisselq |
To disable a specific interrupt, disable all interrupts and write a one to the
|
745 |
|
|
enable line of the interrupt you wish to disable. In this fashion, writing a
|
746 |
|
|
{\tt 0x00010000} will disable all interrupts and leave interrupt line zero
|
747 |
|
|
disabled when the interrupts are re--enabled later, whereas {\tt 0x07fff0000}
|
748 |
|
|
will disable all specific interrupts.
|
749 |
|
|
|
750 |
|
|
Interrupts are acknowledged in a fashion similar to enabling interrupts. By
|
751 |
|
|
writing a `1' to the active bit mask, the interrupt will be acknowledged and
|
752 |
|
|
reset, whereas writing a `0' leaves the interrupt untouched. In this fashion,
|
753 |
|
|
as individual interrupts are handled, a `1' may be written to this bottom mask
|
754 |
|
|
to clear the interrupt. Be aware, however, that any interrupt acknowledgement
|
755 |
|
|
may also globally enable or disable interrupts.
|
756 |
|
|
|
757 |
|
|
\subsection{Last Bus Error Address}
|
758 |
41 |
dgisselq |
The Bus Error peripheral simply records the address of the last bus error,
|
759 |
|
|
and sets an interrupt upon receiving a bus error. (The interrupt itself
|
760 |
|
|
is kind of useless ...) The address can be useful when debugging. While the
|
761 |
|
|
peripheral may only be read,
|
762 |
7 |
dgisselq |
setting it is really as easy as creating a bus error and trapping the result.
|
763 |
36 |
dgisselq |
Another use for this is upon any reboot, it is possible to read the address
|
764 |
|
|
of the last bus error and perhaps learn something of what caused the CPU to
|
765 |
|
|
restart.
|
766 |
7 |
dgisselq |
|
767 |
36 |
dgisselq |
\subsection{ZipTimer}
|
768 |
41 |
dgisselq |
The S6~SoC contains two ZipTimers, available for the CPU to use. These are
|
769 |
36 |
dgisselq |
countdown timers. Writing any non--zero value to them will cause them to
|
770 |
|
|
immediately start counting down from that value towards zero, and to interrupt
|
771 |
41 |
dgisselq |
the CPU upon the transition to zero. Writing a new value while the timer is
|
772 |
|
|
running will cause that new value to automatically load into the timer and
|
773 |
|
|
start counting from there. Writing a zero to the timer disables the timer, and
|
774 |
|
|
causes it to stop.
|
775 |
7 |
dgisselq |
|
776 |
41 |
dgisselq |
ZipTimer A can be set to auto reload by setting the top bit as well as the
|
777 |
|
|
interval. When so set, the timer will automatically
|
778 |
36 |
dgisselq |
load it's last set value upon reaching zero and interrupting the CPU. This
|
779 |
|
|
effectively turns it into an interrupt timer if desired. To set this feature,
|
780 |
|
|
write to the timer the number of clock ticks before an interrupt, but also set
|
781 |
41 |
dgisselq |
the high order bit. In this fashion, writing a {\tt 0x8001387f} will interrupt
|
782 |
36 |
dgisselq |
the CPU every millisecond, starting one millisecond after the write takes place
|
783 |
41 |
dgisselq |
(assuming an 80~MHz system clock).\footnote{Note that, since the timer spends
|
784 |
|
|
a cycle at zero, setting it for a 80,000 cycle period requires setting the
|
785 |
|
|
timer value to one less than 80,000.}
|
786 |
7 |
dgisselq |
|
787 |
36 |
dgisselq |
ZipTimer B has been wired for a different purpose. ZipTimer B does not support
|
788 |
|
|
auto reload, nor will it interrupt the CPU. Instead, ZipTimer B has been wired
|
789 |
41 |
dgisselq |
as a watchdog timer. When this timer transitions to zero, the CPU will be
|
790 |
|
|
rebooted. One way to use this timer would be in conjunction with the ZipTimer
|
791 |
|
|
A, and to write a number to it upon any entry to the interrupt service routine.
|
792 |
|
|
If given enough time, this would cause the CPU to reboot if for any reason it
|
793 |
|
|
locked up.
|
794 |
36 |
dgisselq |
|
795 |
41 |
dgisselq |
The ZipOS uses ZipTimer~A for task swapping. By setting the timer for
|
796 |
|
|
1~ms, the ZipOS examines every task for a potential task swap every millisecond.
|
797 |
|
|
Of course, if the various tasks are running from Flash at 52~clocks per
|
798 |
|
|
instruction, this means that as few as 1,538~instructions may be executed
|
799 |
|
|
between timer interrupts, but this can be tuned if necessary for better
|
800 |
|
|
performance.
|
801 |
|
|
|
802 |
36 |
dgisselq |
\subsection{PWM Audio Controller}
|
803 |
|
|
The bit fields of the PWM Audio controller are shown in Fig.~\ref{fig:pwmreg}.
|
804 |
7 |
dgisselq |
\begin{figure}\begin{center}
|
805 |
|
|
\begin{bytefield}[endianness=big]{32}
|
806 |
|
|
\bitheader{0-31} \\
|
807 |
36 |
dgisselq |
\bitbox{10}{Unused}
|
808 |
|
|
\bitbox{1}{S}
|
809 |
|
|
\bitbox{1}{G}
|
810 |
|
|
\bitbox{3}{}
|
811 |
|
|
\bitbox{1}{E}
|
812 |
|
|
\bitbox{16}{Sample}
|
813 |
|
|
\\
|
814 |
|
|
\end{bytefield}
|
815 |
|
|
\caption{PWM Audio Controller Bitfields}\label{fig:pwmreg}
|
816 |
|
|
\end{center}\end{figure}
|
817 |
|
|
This controller has been designed for easy writing. To send a sample to the
|
818 |
|
|
PWM audio controller, simply write the sample to the controller and clear the
|
819 |
41 |
dgisselq |
PWM audio interrupt---{\em in that order}. When the audio interrupts the CPU
|
820 |
|
|
again, it is ready for the next sample. Do note, however, that the audio
|
821 |
|
|
interrupt can only be cleared once a new sample has been written to it.
|
822 |
|
|
Attempts to clear it prior to that will have no effect. (This is why the
|
823 |
|
|
order matters.)
|
824 |
36 |
dgisselq |
|
825 |
|
|
The audio sample rate has been fixed at 8~kHz. While changing this rate is
|
826 |
|
|
easy to do within {\tt busmaster.v}, the rate itself takes some work to keep
|
827 |
41 |
dgisselq |
up with, so I wouldn't recommend going faster.
|
828 |
36 |
dgisselq |
|
829 |
|
|
The audio controller supports two additional functionalities, however. The
|
830 |
|
|
first is that the {\tt E} bit will be set upon any read when or if the audio
|
831 |
41 |
dgisselq |
controller is ready for another sample and the Audio interrupt has been
|
832 |
|
|
asserted. By polling this bit, for example, the audio driver can be run without
|
833 |
|
|
using the interrupt functionality.
|
834 |
36 |
dgisselq |
|
835 |
|
|
The second functionality has to do with the two auxiliary control bits present
|
836 |
|
|
in the PModAMP2 audio device. These are the gain and shutdown bits. To set
|
837 |
|
|
these bits, write a sample to the controller while also setting the {\tt E}
|
838 |
|
|
bit. When the {\tt E} bit is set upon any write, the shutdown and gain bits
|
839 |
|
|
will also be set. (Be aware, the shutdown bit is negative logic.) Hence, one
|
840 |
|
|
may start this interface by writing a {\tt 0x0310000} to the device, and later
|
841 |
|
|
shut it back off by writing a {\tt 0x010000}.
|
842 |
|
|
|
843 |
|
|
\subsection{Special Purpose I/O}
|
844 |
|
|
|
845 |
|
|
Register {\tt SPIO}, as shown in Fig.~\ref{fig:spioreg},
|
846 |
|
|
\begin{figure}\begin{center}
|
847 |
|
|
\begin{bytefield}[endianness=big]{32}
|
848 |
|
|
\bitheader{0-31} \\
|
849 |
7 |
dgisselq |
\begin{leftwordgroup}{Read}\bitbox[lrt]{16}{Zeros}
|
850 |
|
|
\bitbox[lrt]{4}{Kpad}
|
851 |
|
|
\bitbox[lrt]{4}{Kpad}
|
852 |
|
|
\bitbox[lrt]{2}{00}
|
853 |
|
|
\bitbox[lrt]{2}{Btn}
|
854 |
|
|
\bitbox[lrt]{4}{LED} \\
|
855 |
|
|
\bitbox[lrb]{16}{}
|
856 |
|
|
\bitbox[lrb]{4}{Col Out}
|
857 |
|
|
\bitbox[lrb]{4}{Row In}
|
858 |
|
|
\bitbox[lrb]{2}{}
|
859 |
|
|
\bitbox[lrb]{2}{}
|
860 |
|
|
\bitbox[lrb]{4}{}\end{leftwordgroup} \\
|
861 |
|
|
\begin{leftwordgroup}{Write}\bitbox[lrt]{16}{Ignored}
|
862 |
|
|
\bitbox[lrt]{4}{Col}
|
863 |
|
|
\bitbox[lrt]{4}{Col}
|
864 |
|
|
\bitbox[lrt]{4}{LED}
|
865 |
|
|
\bitbox[lrt]{4}{LED} \\
|
866 |
|
|
\bitbox[lrb]{16}{}
|
867 |
|
|
\bitbox[lrb]{4}{Out}
|
868 |
|
|
\bitbox[lrb]{4}{Enable}
|
869 |
|
|
\bitbox[lrb]{4}{Enable}
|
870 |
|
|
\bitbox[lrb]{4}{}\end{leftwordgroup} \\
|
871 |
|
|
\end{bytefield}
|
872 |
|
|
\caption{SPIO Control Register}\label{fig:spioreg}
|
873 |
|
|
\end{center}\end{figure}
|
874 |
|
|
is a Special Purpose Input/Output (SPIO) register. It is
|
875 |
|
|
designed to control the on-board LED's, buttons, and keypad. Upon any read,
|
876 |
|
|
the register reads the current state of the keypad column output, the keypad
|
877 |
|
|
row input, the buttons and the LED's. Writing is more difficult, in order to
|
878 |
|
|
make certain that parts of these registers can be modified atomically.
|
879 |
|
|
Specifically, to change an LED, write the new value as well as a `1' to the
|
880 |
|
|
corresponding LED change enable bit. The same goes for the keypad column
|
881 |
41 |
dgisselq |
output, a `1' needs to be written to the corresponding change enable bit in
|
882 |
|
|
order for a new value to be accepted.
|
883 |
7 |
dgisselq |
|
884 |
36 |
dgisselq |
As examples, writing a {\tt 0x0ff} to the {\tt SPIO} register will turn all
|
885 |
|
|
LED's on, {\tt 0x0f0} will turn all LED's off, and {\tt 0x011} and {\tt 0x010}
|
886 |
|
|
will turn LED0 on and then off again respectively.
|
887 |
|
|
|
888 |
41 |
dgisselq |
The keypad is a little bit tricker. To wait for a keypad interrupt, one needs
|
889 |
|
|
to set the column outputs to zero. To do this, write a {\tt 0x0f00} to the
|
890 |
|
|
{\tt SPIO} register. When a user then presses a key, one of the row inputs
|
891 |
|
|
will go low and an interrupt will be asserted. The key must then be debounced,
|
892 |
|
|
and the ZipOS debounces keys for 5~ms. Once debounced, the key may be read.
|
893 |
|
|
To do this, set half of the columns to zero, such as by writing a {\tt 0x0cf00}
|
894 |
|
|
to the {\tt SPIO} register. If one of the row values is still zero, then
|
895 |
|
|
one of the two columns tested corresponded with the key. This can then be
|
896 |
|
|
repeated until the correct column has been determined, at which point the
|
897 |
|
|
row can be read and the key known.
|
898 |
|
|
|
899 |
7 |
dgisselq |
The controller will generate a keypad interrupt whenever any row input is
|
900 |
41 |
dgisselq |
zero, and a button interrupt whenever any button value is a one. This is a
|
901 |
|
|
level triggered interrupt, not edge triggered. What that means is that,
|
902 |
|
|
once generated, the interrupt will need to be disabled until the key or button
|
903 |
|
|
is released---there will be no interrupt for the release, that part will need
|
904 |
|
|
to be done in software.
|
905 |
7 |
dgisselq |
|
906 |
36 |
dgisselq |
\subsection{General Purpose I/O}
|
907 |
7 |
dgisselq |
The General Purpose Input and Output (GPIO) control register, shown in
|
908 |
|
|
Fig.~\ref{fig:gpioreg},
|
909 |
|
|
\begin{figure}\begin{center}
|
910 |
|
|
\begin{bytefield}[endianness=big]{32}
|
911 |
|
|
\bitheader{0-31} \\
|
912 |
|
|
\bitbox[lrtb]{16}{Current Input Vals (x16)}\bitbox[lrt]{16}{Current Output} \\
|
913 |
|
|
\bitbox[lrtb]{16}{Output Change Enable}\bitbox[lrb]{16}{Values (16-outs)}
|
914 |
|
|
\end{bytefield}
|
915 |
|
|
\caption{GPIO Control Register}\label{fig:gpioreg}
|
916 |
|
|
\end{center}\end{figure}
|
917 |
|
|
is quite simple to use: when read, the top 16--bits indicate
|
918 |
|
|
the value of the 16--input GPIO pins, whereas the bottom 16--bits indicate
|
919 |
|
|
the value being placed on the 16--output GPIO pins. To change a GPIO pin,
|
920 |
36 |
dgisselq |
write the new pin's value to this register, together with setting the
|
921 |
41 |
dgisselq |
corresponding pin in the bit-mask represented by the upper 16--bits. For
|
922 |
|
|
example, to set output pin 0, write a {\tt 0x010001} to the GPIO device. To
|
923 |
|
|
clear output pin 0, write a {\tt 0x010000}. Likewise pin two may be set by
|
924 |
|
|
writing a {\tt 0x020002}, and both pins may be set by writing {\tt 0x030003},
|
925 |
|
|
etc. This makes it possible to adjust some output pins independent of the
|
926 |
|
|
others.
|
927 |
7 |
dgisselq |
|
928 |
|
|
The GPIO controller, like the keypad or SPIO controller, will also generate
|
929 |
|
|
an interrupt. The GPIO interrupt is generated whenever a GPIO input line
|
930 |
36 |
dgisselq |
changes. The interrupt is not selective: if any line changes, a GPIO interrupt
|
931 |
41 |
dgisselq |
will be generated. There are no ``do not care'' lines (although the GPIO
|
932 |
|
|
controller could be easily adjusted to make such ``do-not-care'' lines if
|
933 |
|
|
necessary \ldots).
|
934 |
7 |
dgisselq |
|
935 |
|
|
Of the 16 GPIO inputs and the 16 GPIO outputs, two lines have been taken for
|
936 |
41 |
dgisselq |
I2C support, and a third has been stolen to make the PMod's fit on the
|
937 |
|
|
board. GPIO line zero, for both input and output, is an I2C data line,
|
938 |
36 |
dgisselq |
{\tt io\_sda}, and GPIO line one is an I2C clock line, {\tt io\_scl}. If the
|
939 |
41 |
dgisselq |
output of either of these lines is set to zero, the GPIO controller will pull
|
940 |
|
|
the line low. Otherwise, the line is pulled up so that other devices may pull
|
941 |
|
|
it low. If either line is low, when the output control bit is high,
|
942 |
7 |
dgisselq |
it is an indicator that another device is sending data across these wires.
|
943 |
41 |
dgisselq |
Likewise GPIO input line 15 has been fixed to ground in order to support
|
944 |
|
|
placing the keypad next to the S6~SoC.
|
945 |
7 |
dgisselq |
|
946 |
36 |
dgisselq |
\subsection{UART Data Register}
|
947 |
41 |
dgisselq |
Moving on to the UART \ldots although the UART module itself
|
948 |
|
|
within the S6~SoC is highly configurable, as built
|
949 |
7 |
dgisselq |
the UART can only handle 9600~Baud, 8--data bits, no parity, and one stop bit.
|
950 |
36 |
dgisselq |
Changing this involves changing the constant {\tt uart\_setup} within
|
951 |
|
|
{\tt busmaster.v}. Further, the UART has only a single byte data buffer, so
|
952 |
41 |
dgisselq |
reading from the port has a real--time requirement associated with it: the
|
953 |
36 |
dgisselq |
data buffer must be emptied before the next value is read.
|
954 |
7 |
dgisselq |
Attempts to read from this port will either return an 8--bit data value from
|
955 |
|
|
the port, or if no values are available it will return an {\tt 0x0100}
|
956 |
36 |
dgisselq |
indicating that fact. In general, reading from the UART port involves first
|
957 |
|
|
waiting for the interrupt to be ready, second reading from the port itself,
|
958 |
|
|
and then third immediately clearing the interrupt. (The interrupt cannot
|
959 |
|
|
be cleared while data is waiting.) Writing to the UART port is done in a
|
960 |
41 |
dgisselq |
similar fashion. First, wait until the UART transmit interrupt is asserted
|
961 |
|
|
(this will likely be most of the time), second write to the UART port, and
|
962 |
|
|
then third clear the interrupt. As with the read interrupt, clearing the
|
963 |
|
|
transmit interrupt prior to writing to the port will have no effect. Likewise,
|
964 |
|
|
clearing the transmit interrupt after the byte has been written will have no
|
965 |
|
|
affect either.
|
966 |
7 |
dgisselq |
|
967 |
36 |
dgisselq |
\section{Debugging Scope}
|
968 |
|
|
The debugging scope consists of two registers, a control register and a data
|
969 |
41 |
dgisselq |
register. It needs to be internally wired to 32--wires, internal to the
|
970 |
|
|
S6~SoC, that will be of interest when debugging. For further details on how
|
971 |
|
|
to configure and use this scope, please see the {\tt WBSCOPE} project on
|
972 |
|
|
OpenCores.
|
973 |
36 |
dgisselq |
|
974 |
|
|
\section{Internal Configuration Access Port}
|
975 |
|
|
The Internal Configuration Access Port (ICAP) provides access to the internal
|
976 |
|
|
configuration details of the FPGA. This access was designed so as to provide
|
977 |
|
|
the CPU with the capability to command a different FPGA load. In particular,
|
978 |
|
|
the code in Fig.~\ref{fig:reload} should reconfigure the FPGA from any given
|
979 |
|
|
Quad SPI {\tt address}.\footnote{According to Xilinx's technical support, this
|
980 |
41 |
dgisselq |
will only work if the JTAG port is not busy--such as when the USB port is
|
981 |
|
|
disconnected.}
|
982 |
36 |
dgisselq |
\begin{figure}\begin{center}\begin{tabbing}
|
983 |
|
|
{\tt warmboot(uint32 address) \{} \\
|
984 |
|
|
\hbox to 0.25in{}\={\tt uint32\_t *icape6 = (volatile uint32\_t *)0x{\em <ICAPE port address>};}\\
|
985 |
|
|
\>{\tt icape6[13] = (address<<2)\&0x0ffff;}\\
|
986 |
|
|
\>{\tt icape6[14] = ((address>>14)\&0x0ff)|((0x03)<<8);}\\
|
987 |
|
|
\>{\tt icape6[4] = 14;}\\
|
988 |
|
|
\>{\em // The CMod~S6 is now reconfiguring itself from the new address.}\\
|
989 |
|
|
\>{\em // If all goes well, this routine will never return.}\\
|
990 |
|
|
{\tt \}}
|
991 |
|
|
\end{tabbing}
|
992 |
|
|
\caption{Spartan--6 ICAPE Usage}\label{fig:reload}
|
993 |
|
|
\end{center}\end{figure}
|
994 |
|
|
|
995 |
|
|
One subtle problem with this port is that it will not work if the CMod is
|
996 |
|
|
plugged in to the USB JTAG port. It will only work if the CMod has been
|
997 |
|
|
provided with an independent power supply, leaving the USB JTAG unplugged.
|
998 |
|
|
|
999 |
41 |
dgisselq |
For further details, please see either the {\tt WBICAPETWO} project on
|
1000 |
|
|
OpenCores as well as Xilinx's ``Spartan-6 FPGA Configuration User Guide''.
|
1001 |
36 |
dgisselq |
|
1002 |
|
|
\section{Real--Time Clock}
|
1003 |
41 |
dgisselq |
|
1004 |
36 |
dgisselq |
The Real Time Clock will be included if there is enough area to support it.
|
1005 |
41 |
dgisselq |
(There isn't currently \ldots)
|
1006 |
|
|
The four registers of this port correspond to a clock, a timer, a stopwatch,
|
1007 |
|
|
and an alarm. If space is tight, the timer and stopwatch, or indeed the entire
|
1008 |
|
|
clock, may be removed from the design. For further details regarding how to
|
1009 |
|
|
set and use this clock, please see the {\tt RTCCLOCK} project on OpenCores.
|
1010 |
36 |
dgisselq |
|
1011 |
|
|
There is currently not enough area on the chip to support the Real--Time Clock
|
1012 |
|
|
together with all of the other peripherals listed here. You can adjust whether
|
1013 |
|
|
the clock is included or not by adjusting the {\tt `define} lines at the top
|
1014 |
|
|
of {\tt busmaster.v}. For example, it may be possible to get the RTC back by
|
1015 |
|
|
disabling the ICAPE2 interface.
|
1016 |
|
|
|
1017 |
41 |
dgisselq |
In place of the RTC capability, the ZipOS offers a software based RTC capability
|
1018 |
|
|
to simulate the clock register of this port.
|
1019 |
|
|
|
1020 |
36 |
dgisselq |
\section{On-Chip Block RAM}
|
1021 |
|
|
|
1022 |
|
|
The block RAM is the fastest memory available to the processor. It is also
|
1023 |
|
|
the {\em only} writeable memory available to the processor. Hence all
|
1024 |
41 |
dgisselq |
non-constant program data {\em must} be placed into block RAM. The Zip~CPU
|
1025 |
36 |
dgisselq |
can also run instructions from the block RAM if extra speed is desired. When
|
1026 |
41 |
dgisselq |
runnning from block RAM, the Zip~CPU will nominally take 8~clocks per
|
1027 |
|
|
instruction, for an effective rate of 10~MIPS. Loads or stores to block RAM
|
1028 |
|
|
will take one clock longer.
|
1029 |
36 |
dgisselq |
|
1030 |
|
|
\section{Flash Memory}
|
1031 |
|
|
The flash memory has been arbitrarily sectioned into three sections, one for
|
1032 |
|
|
a primary configuration, a second section for an alternate configuration file,
|
1033 |
|
|
and the third section for any program and data. These regions are shown in
|
1034 |
|
|
Tbl.~\ref{tbl:flash-addresses}.
|
1035 |
|
|
\begin{table}[htbp]
|
1036 |
|
|
\begin{center}\begin{tabular}{|p{0.75in}|p{0.75in}|p{0.5in}|p{3.0in}|}\hline
|
1037 |
|
|
\rowcolor[gray]{0.85} Start & End & & Purpose \\\hline\hline
|
1038 |
|
|
\scalebox{0.9}{\tt 0x400000} & \scalebox{0.9}{\tt 0x43ffff} & R & Primary configuration space\\\hline
|
1039 |
|
|
\scalebox{0.9}{\tt 0x440000} & \scalebox{0.9}{\tt 0x47ffff} & R & Alternate configuration space\\\hline
|
1040 |
41 |
dgisselq |
\scalebox{0.9}{\tt 0x480000} & \scalebox{0.9}{\tt 0x7fffff} & R & Zip~CPU program memory\\\hline
|
1041 |
36 |
dgisselq |
\end{tabular}
|
1042 |
|
|
\caption{Flash Address Regions}\label{tbl:flash-addresses}
|
1043 |
|
|
\end{center}\end{table}
|
1044 |
41 |
dgisselq |
The host program {\tt zipload} can be used to load a Zip~CPU program and
|
1045 |
36 |
dgisselq |
configuration files into this address space. To use it, first load the
|
1046 |
|
|
alternate configuration into the FPGA. Then pass it, as arguments, the
|
1047 |
41 |
dgisselq |
primary, and alternate (if desired), configuration files followed by the
|
1048 |
|
|
Zip~CPU program file. Then, when the primary configuration is loaded again,
|
1049 |
|
|
perhaps upon power up, the Zip~CPU will automatically start running from it's
|
1050 |
36 |
dgisselq |
{\tt RESET\_ADDRESS}, {\tt 0x480000}.
|
1051 |
|
|
|
1052 |
41 |
dgisselq |
When running from Flash memory, the Zip~CPU will nominally take 52~clocks per
|
1053 |
36 |
dgisselq |
instruction, for an effective speed of about 1.5~MIPS.
|
1054 |
|
|
|
1055 |
41 |
dgisselq |
When using {\tt zipload}, the first bit file argument will load the first
|
1056 |
|
|
configuration space, the second bit file argument will load the second
|
1057 |
|
|
configuration space, and the third argument will load the Zip~CPU program
|
1058 |
|
|
into its space.
|
1059 |
|
|
|
1060 |
7 |
dgisselq |
\chapter{Clocks}
|
1061 |
|
|
|
1062 |
|
|
The S6~SoC is designed to run off of one master clock. This clock is derived
|
1063 |
41 |
dgisselq |
from the 8~MHz input clock on the board, by multiplying it up to 80~MHz. The
|
1064 |
|
|
code for doing this can be found in both {\tt toplevel.v} and {\tt alttop.v}.
|
1065 |
7 |
dgisselq |
|
1066 |
41 |
dgisselq |
\chapter{I/O Ports}
|
1067 |
7 |
dgisselq |
|
1068 |
41 |
dgisselq |
Table.~\ref{tbl:ioports}
|
1069 |
7 |
dgisselq |
\begin{table}[htbp]
|
1070 |
|
|
\begin{center}
|
1071 |
|
|
\begin{portlist}
|
1072 |
|
|
i\_clk\_8mhz & 1 & Input & Clock\\\hline
|
1073 |
|
|
o\_qspi\_cs\_n & 1 & Output & Quad SPI Flash chip select\\\hline
|
1074 |
|
|
o\_qspi\_sck & 1 & Output & Quad SPI Flash clock\\\hline
|
1075 |
|
|
io\_qspi\_dat & 4 & Input/Output & Four-wire SPI flash data bus\\\hline
|
1076 |
|
|
i\_btn & 2 & Input & Inputs from the two on-board push-buttons\\\hline
|
1077 |
|
|
o\_led & 4 & Output & Outputs controlling the four on-board LED's\\\hline
|
1078 |
|
|
o\_pwm & 1 & Output & Audio output, via pulse width modulator\\\hline
|
1079 |
|
|
\multicolumn{2}{|l|}{o\_pwm\_shutdown\_n, 1}& Output & Audio output shutdown control\\\hline
|
1080 |
|
|
o\_pwm\_gain & 1 & Output & Audio output 20~dB gain enable\\\hline
|
1081 |
|
|
i\_uart & 1 & Input & UART receive input\\\hline
|
1082 |
|
|
o\_uart & 1 & Output & UART transmit output\\\hline
|
1083 |
41 |
dgisselq |
o\_uart\_cts & 1 & Output & H/W flow control response, true if the internal
|
1084 |
|
|
single-byte receive buffer is empty.\\\hline
|
1085 |
|
|
i\_uart\_rts & 1 & Input & H/W flow control, true if the PModUSBUART wishes
|
1086 |
|
|
to send a byte\\\hline
|
1087 |
7 |
dgisselq |
i\_kp\_row & 4 & Output & Four wires to activate the four rows of the keypad\\\hline
|
1088 |
|
|
o\_kp\_col & 4 & Output & Return four wires, from the keypads columns \\\hline
|
1089 |
|
|
i\_gpio & 14 & Output & General purpose logic input lines\\\hline
|
1090 |
|
|
o\_gpio & 14 & Output & General purpose logic output lines\\\hline
|
1091 |
|
|
io\_scl & 1 & Input/Output & I2C clock port\\\hline
|
1092 |
|
|
io\_sda & 1 & Input/Output & I2C data port\\\hline
|
1093 |
|
|
\end{portlist}
|
1094 |
|
|
\caption{List of IO ports}\label{tbl:ioports}
|
1095 |
|
|
\end{center}\end{table}
|
1096 |
41 |
dgisselq |
lists the various I/O ports associated with the S6~SoC. These ports are named
|
1097 |
|
|
in roughly the same manner they are used. The four UART pins,
|
1098 |
|
|
{\tt i\_uart}, {\tt o\_uart}, {\tt i\_uart\_rts} and {\tt o\_uart\_cts},
|
1099 |
|
|
connect to the PModUSBUART. The three PWM pins, {\tt o\_pwm},
|
1100 |
|
|
{\tt o\_pwm\_gain}, and {\tt o\_pwm\_shutdown\_n}, control the PModAMP2 audio
|
1101 |
|
|
device. The eight pins, {\tt i\_kp\_row[3:0]} and {\tt o\_kp\_col[3:0]},
|
1102 |
|
|
control the PModKYPD keypad. The final PMod, PModCLS, is controlled via the
|
1103 |
|
|
SPI lines formed from {\tt o\_gpio[4:2]} and {\tt i\_gpio[2]}. This display
|
1104 |
|
|
could also be controlled via I2C, {\tt io\_sda} and {\tt io\_scl}, although that
|
1105 |
|
|
is not part of the current demonstration software.
|
1106 |
18 |
dgisselq |
|
1107 |
41 |
dgisselq |
The assignment of these pins to external output I/O pins is shown in
|
1108 |
|
|
Fig.~\ref{fig:physicalio}.
|
1109 |
|
|
\begin{figure}
|
1110 |
18 |
dgisselq |
\begin{center}
|
1111 |
|
|
\includegraphics[height=7in]{../gfx/pinout.eps}
|
1112 |
41 |
dgisselq |
\caption{Physical Locations of Device I/O Ports}\label{fig:physicalio}
|
1113 |
|
|
\end{center}\end{figure}
|
1114 |
|
|
Although pin assignment to the actual S6~board has been rather arbitrary, there
|
1115 |
|
|
is a touch of method to the madness. In particular, the S6~SoC pin placement
|
1116 |
|
|
supports placing the PMods in the configuration shown in
|
1117 |
|
|
Fig.~\ref{fig:pmodplaces}.
|
1118 |
|
|
\begin{figure}
|
1119 |
|
|
\begin{center}
|
1120 |
|
|
\includegraphics[height=7in]{../gfx/pmodmap.eps}
|
1121 |
|
|
\caption{Suggested mapping of I/O ports to PMod Locations}\label{fig:pmodplaces}
|
1122 |
|
|
\end{center}\end{figure}
|
1123 |
|
|
From this figure you can see that I have tried to minimize the amount of
|
1124 |
|
|
movement necessary to install any particular PMods, while also making the
|
1125 |
|
|
greatest use of pins on board. What may not be obvious from this picture
|
1126 |
|
|
is that the PMod power and ground lines are all connected to power and ground
|
1127 |
|
|
rails separate from the CMod itself.
|
1128 |
|
|
|
1129 |
|
|
As with any piece of open source firmware, these pin assignments are fairly
|
1130 |
|
|
arbitrary and easy to adjust by making changes to the {\tt cmod.ucf} and
|
1131 |
|
|
{\tt cmodtop.ucf} files. The main difference between those two files being
|
1132 |
|
|
the DEPP interface supported by alternate configuration, which uses
|
1133 |
|
|
{\tt cmod.ucf}.
|
1134 |
|
|
|
1135 |
7 |
dgisselq |
% Appendices
|
1136 |
|
|
% Index
|
1137 |
|
|
\end{document}
|
1138 |
|
|
|
1139 |
|
|
|