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