\documentclass{gqtekspec}
|
\documentclass{gqtekspec}
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%
|
%%
|
%% Filename: spec.tex
|
%% Filename: spec.tex
|
%%
|
%%
|
%% Project: SD-Card controller, using a shared SPI interface
|
%% Project: SD-Card controller, using a shared SPI interface
|
%%
|
%%
|
%% Purpose: This LaTeX file contains all of the documentation/description
|
%% Purpose: This LaTeX file contains all of the documentation/description
|
%% currently provided with the SDSPI controller core. For those
|
%% currently provided with the SDSPI controller core. For those
|
%% looking into here, this document is not nearly as interesting as the
|
%% looking into here, this document is not nearly as interesting as the
|
%% spec.pdf file it creates, so I'd strongly recommend reading that before
|
%% spec.pdf file it creates, so I'd strongly recommend reading that before
|
%% diving into this document. However, if you are interested in producing
|
%% diving into this document. However, if you are interested in producing
|
%% documents looking like this one, or using LaTeX in a similar fashion,
|
%% documents looking like this one, or using LaTeX in a similar fashion,
|
%% you may find this document of use.
|
%% you may find this document of use.
|
%%
|
%%
|
%% You should be able to find the PDF this file produces in the SVN
|
%% You should be able to find the PDF this file produces in the SVN
|
%% distribution together with this LaTeX file and a copy of the GPL-3.0
|
%% distribution together with this LaTeX file and a copy of the GPL-3.0
|
%% license this file is distributed under. If not, just type 'make' in
|
%% license this file is distributed under. If not, just type 'make' in
|
%% the doc directory (one up from this one), and it (should) build both
|
%% the doc directory (one up from this one), and it (should) build both
|
%% pdf's without a problem.
|
%% pdf's without a problem.
|
%%
|
%%
|
%% Creator: Dan Gisselquist, Ph.D.
|
%% Creator: Dan Gisselquist, Ph.D.
|
%% Gisselquist Technology, LLC
|
%% Gisselquist Technology, LLC
|
%%
|
%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%
|
%%
|
%% Copyright (C) 2016, Gisselquist Technology, LLC
|
%% Copyright (C) 2016, Gisselquist Technology, LLC
|
%%
|
%%
|
%% This program is free software (firmware): you can redistribute it and/or
|
%% This program is free software (firmware): you can redistribute it and/or
|
%% modify it under the terms of the GNU General Public License as published
|
%% modify it under the terms of the GNU General Public License as published
|
%% by the Free Software Foundation, either version 3 of the License, or (at
|
%% by the Free Software Foundation, either version 3 of the License, or (at
|
%% your option) any later version.
|
%% your option) any later version.
|
%%
|
%%
|
%% This program is distributed in the hope that it will be useful, but WITHOUT
|
%% This program is distributed in the hope that it will be useful, but WITHOUT
|
%% ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
%% ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
%% FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
%% FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
%% for more details.
|
%% for more details.
|
%%
|
%%
|
%% You should have received a copy of the GNU General Public License along
|
%% You should have received a copy of the GNU General Public License along
|
%% with this program. (It's in the $(ROOT)/doc directory, run make with no
|
%% with this program. (It's in the $(ROOT)/doc directory, run make with no
|
%% target there if the PDF file isn't present.) If not, see
|
%% target there if the PDF file isn't present.) If not, see
|
%% <http://www.gnu.org/licenses/> for a copy.
|
%% <http://www.gnu.org/licenses/> for a copy.
|
%%
|
%%
|
%% License: GPL, v3, as defined and found on www.gnu.org,
|
%% License: GPL, v3, as defined and found on www.gnu.org,
|
%% http://www.gnu.org/licenses/gpl.html
|
%% http://www.gnu.org/licenses/gpl.html
|
%%
|
%%
|
%%
|
%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%
|
%%
|
%%
|
%%
|
\usepackage{import}
|
\usepackage{import}
|
\usepackage{bytefield}
|
\usepackage{bytefield}
|
\project{SDSPI Controller}
|
\project{SDSPI Controller}
|
\title{Specification}
|
\title{Specification}
|
\author{Dan Gisselquist, Ph.D.}
|
\author{Dan Gisselquist, Ph.D.}
|
\email{dgisselq (at) opencores.org}
|
\email{dgisselq (at) ieee.org}
|
\revision{Rev.~0.1}
|
\revision{Rev.~0.1}
|
\begin{document}
|
\begin{document}
|
\pagestyle{gqtekspecplain}
|
\pagestyle{gqtekspecplain}
|
\titlepage
|
\titlepage
|
\begin{license}
|
\begin{license}
|
Copyright (C) \theyear\today, Gisselquist Technology, LLC
|
Copyright (C) \theyear\today, Gisselquist Technology, LLC
|
|
|
This project is free software (firmware): you can redistribute it and/or
|
This project is free software (firmware): you can redistribute it and/or
|
modify it under the terms of the GNU General Public License as published
|
modify it under the terms of the GNU General Public License as published
|
by the Free Software Foundation, either version 3 of the License, or (at
|
by the Free Software Foundation, either version 3 of the License, or (at
|
your option) any later version.
|
your option) any later version.
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
for more details.
|
for more details.
|
|
|
You should have received a copy of the GNU General Public License along
|
You should have received a copy of the GNU General Public License along
|
with this program. If not, see \texttt{http://www.gnu.org/licenses/} for a copy.
|
with this program. If not, see \texttt{http://www.gnu.org/licenses/} for a copy.
|
\end{license}
|
\end{license}
|
\begin{revisionhistory}
|
\begin{revisionhistory}
|
0.1 & 6/18/2016 & Gisselquist & First Draft \\\hline
|
0.1 & 6/18/2016 & Gisselquist & First Draft \\\hline
|
\end{revisionhistory}
|
\end{revisionhistory}
|
% Revision History
|
% Revision History
|
% Table of Contents, named Contents
|
% Table of Contents, named Contents
|
\tableofcontents
|
\tableofcontents
|
\listoffigures
|
\listoffigures
|
\listoftables
|
\listoftables
|
\begin{preface}
|
\begin{preface}
|
When I started this project, I was informed that other projects similar to this
|
When I started this project, I was informed that other projects similar to this
|
one existed. The OpenRISC project has used an SD--Card controller, for example,
|
one existed. The OpenRISC project has used an SD--Card controller, for example,
|
as has the Google project vault. Of these two, the first uses the full SD--Card
|
as has the Google project vault. Of these two, the first uses the full SD--Card
|
interface which is unavailable on the XuLA2 board, and I could never find the
|
interface which is unavailable on the XuLA2 board, and I could never find the
|
code for the second.
|
code for the second.
|
|
|
Still, had I found such interfaces, I would've still had another reason for
|
Still, had I found such interfaces, I would've still had another reason for
|
building my own: controlling the license. By rolling my own interface, I can
|
building my own: controlling the license. By rolling my own interface, I can
|
offer it to anyone interested in it under the GPL license, such as you have
|
offer it to anyone interested in it under the GPL license, such as you have
|
here. Further, by not using code belonging to others, I am not restricted or
|
here. Further, by not using code belonging to others, I am not restricted or
|
encumbered by any of their licenses--whether it be the GPL or otherwise. This
|
encumbered by any of their licenses--whether it be the GPL or otherwise. This
|
code, and specification document, are therefore completely the product of
|
code, and specification document, are therefore completely the product of
|
Gisselquist Technology, LLC.
|
Gisselquist Technology, LLC.
|
|
|
That said, I am indebted to Mr.~Tambe for sharing his interface. While the
|
That said, I am indebted to Mr.~Tambe for sharing his interface. While the
|
current work does not use his approach and represents a complete rewrite, his
|
current work does not use his approach and represents a complete rewrite, his
|
approach was valuable in helping me understand what the SD--Card specification
|
approach was valuable in helping me understand what the SD--Card specification
|
meant at several points along the way.
|
meant at several points along the way.
|
\end{preface}
|
\end{preface}
|
|
|
\chapter{Introduction}
|
\chapter{Introduction}
|
\pagenumbering{arabic}
|
\pagenumbering{arabic}
|
\setcounter{page}{1}
|
\setcounter{page}{1}
|
|
|
% What is old
|
% What is old
|
This Verilog core exports an SD card controller interface from internal to an
|
This Verilog core exports an SD card controller interface from internal to an
|
FPGA to the rest of the FPGA core, while taking care of the lower level details
|
FPGA to the rest of the FPGA core, while taking care of the lower level details
|
internal to the interface.
|
internal to the interface.
|
% What does the old lack?
|
% What does the old lack?
|
Unlike the other OpenCores SD Card controller\footnote{See
|
Unlike the other OpenCores SD Card controller\footnote{See
|
\texttt{http://www.opencores.org/project,sdcard\_mass\_storage\_controller}.}
|
\texttt{http://www.opencores.org/project,sdcard\_mass\_storage\_controller}.}
|
which offers a full SD--interface, this controller focuses on the SPI interface
|
which offers a full SD--interface, this controller focuses on the SPI interface
|
of the SD Card. While this is a slower interface, the SPI interface is
|
of the SD Card. While this is a slower interface, the SPI interface is
|
necessary to access the card when using a XuLA2
|
necessary to access the card when using a XuLA2
|
board\footnote{See \texttt{http://www.xess.com/shop/product/xula2-lx25/}}, or
|
board\footnote{See \texttt{http://www.xess.com/shop/product/xula2-lx25/}}, or
|
in general any time the full 9--bit, bi--directional interface to the SD card
|
in general any time the full 9--bit, bi--directional interface to the SD card
|
has not been implemented.
|
has not been implemented.
|
Further, for those who are die--hard Verilog authors, this core is written in
|
Further, for those who are die--hard Verilog authors, this core is written in
|
Verilog as opposed to the XESS provided demonstration SD Card controller
|
Verilog as opposed to the XESS provided demonstration SD Card controller
|
found on GitHub\footnote{See
|
found on GitHub\footnote{See
|
\texttt{https://github.com/xesscorp/VHDL\_Lib/SDCard.vhd}}, which was written
|
\texttt{https://github.com/xesscorp/VHDL\_Lib/SDCard.vhd}}, which was written
|
in VHDL. For those who are not such die--hard Verilog authors, this controller
|
in VHDL. For those who are not such die--hard Verilog authors, this controller
|
provides a lower level interface to the card than these other controllers.
|
provides a lower level interface to the card than these other controllers.
|
Whereas the XESS controller will automatically start up the card and interact
|
Whereas the XESS controller will automatically start up the card and interact
|
with it, this controller requires external software to be used when interacting
|
with it, this controller requires external software to be used when interacting
|
with the card. This makes the SDSPI controller both more versatile, in the
|
with the card. This makes the SDSPI controller both more versatile, in the
|
face of potential changes to the card interface, but also less--turn key.
|
face of potential changes to the card interface, but also less--turn key.
|
% What is new
|
% What is new
|
% What does the new have that the old lacks
|
% What does the new have that the old lacks
|
% What performance gain can be expected?
|
% What performance gain can be expected?
|
|
|
While this core was written for the purpose of being used with the ZipCPU,
|
While this core was written for the purpose of being used with the ZipCPU,
|
as enhanced by the Wishbone DMA controller used by the ZipCPU, nothing in this
|
as enhanced by the Wishbone DMA controller used by the ZipCPU, nothing in this
|
core prevents it from being used with any other architecture that supports
|
core prevents it from being used with any other architecture that supports
|
the 32--bit Wishbone interface of this core.
|
the 32--bit Wishbone interface of this core.
|
|
|
This core has been written as a wishbone slave, not a master. Using the core
|
This core has been written as a wishbone slave, not a master. Using the core
|
together with a separate master, such as a CPU or a DMA controller, only makes
|
together with a separate master, such as a CPU or a DMA controller, only makes
|
sense. This design, however, also restricts the core from being able to use
|
sense. This design, however, also restricts the core from being able to use
|
the multiple block write or multiple block read commands, restricting us to
|
the multiple block write or multiple block read commands, restricting us to
|
single block read and write commands alone.
|
single block read and write commands alone.
|
|
|
\chapter{Architecture}\label{ch:arch}
|
\chapter{Architecture}\label{ch:arch}
|
|
|
This SD Card interface is designed to provide a means of commanding an SD Card,
|
This SD Card interface is designed to provide a means of commanding an SD Card,
|
via the SPI port, and returning its results.
|
via the SPI port, and returning its results.
|
|
|
The first thing to know about the SDSPI interface is that it is designed to work
|
The first thing to know about the SDSPI interface is that it is designed to work
|
over a shared SPI port. Hence, when the SDSPI controller lowers the CS line to
|
over a shared SPI port. Hence, when the SDSPI controller lowers the CS line to
|
select the SD--Card, the lowered line is only a request to an external
|
select the SD--Card, the lowered line is only a request to an external
|
controller. Once that external controller grants access to the SPI port to this
|
controller. Once that external controller grants access to the SPI port to this
|
device, it will tell this controller and processing can continue. If your
|
device, it will tell this controller and processing can continue. If your
|
application does not have any contention for the SPI interface, you may simply
|
application does not have any contention for the SPI interface, you may simply
|
wire this grant line high. The controller will still work, although it will
|
wire this grant line high. The controller will still work, although it will
|
wait one clock more than necessary in that case before starting any transaction.
|
wait one clock more than necessary in that case before starting any transaction.
|
|
|
Second, the SDSPI core is completely controlled via the wishbone bus. In
|
Second, the SDSPI core is completely controlled via the wishbone bus. In
|
particular a command register is used to initiate interaction across the bus.
|
particular a command register is used to initiate interaction across the bus.
|
A separate data register is used to provide an argument to the command, and
|
A separate data register is used to provide an argument to the command, and
|
two FIFO registers are used when transferring larger amounts of data to the
|
two FIFO registers are used when transferring larger amounts of data to the
|
card. We'll examine each of these interactions in turn.
|
card. We'll examine each of these interactions in turn.
|
|
|
Writes to the command register (CMD) will initiate actions across the port,
|
Writes to the command register (CMD) will initiate actions across the port,
|
whether they be reads from or writes to the card. These writes take the
|
whether they be reads from or writes to the card. These writes take the
|
form of sending a 48--bit command to the card. The command sent to the card
|
form of sending a 48--bit command to the card. The command sent to the card
|
is taken from the lower 8--bits of the command register, and the argument to the
|
is taken from the lower 8--bits of the command register, and the argument to the
|
command is taken from the DATA register. The last 8--bits of the command sent
|
command is taken from the DATA register. The last 8--bits of the command sent
|
to the card are formed from a command CRC byte which the core generates
|
to the card are formed from a command CRC byte which the core generates
|
internally. From the perspective of the Wishbone bus, writes to the register
|
internally. From the perspective of the Wishbone bus, writes to the register
|
will complete immediately, even though the action they initiate will may take
|
will complete immediately, even though the action they initiate will may take
|
much longer to complete. Further, writes made to the CMD register will be
|
much longer to complete. Further, writes made to the CMD register will be
|
silently ignored if the device is already busy.
|
silently ignored if the device is already busy.
|
|
|
Reads from the CMD register will always return immediately. In particular, the
|
Reads from the CMD register will always return immediately. In particular, the
|
{\tt busy} bit, as returned by the CMD register, can be used to determine if the
|
{\tt busy} bit, as returned by the CMD register, can be used to determine if the
|
interface is busy.
|
interface is busy.
|
|
|
There is one exception to the rule that writes take many clocks to complete,
|
There is one exception to the rule that writes take many clocks to complete,
|
and that is writes which configure the SDSPI port. Internal to the SDSPI
|
and that is writes which configure the SDSPI port. Internal to the SDSPI
|
port is a configuration register, which determines the speed of the port
|
port is a configuration register, which determines the speed of the port
|
clock as well as the length of the FIFO (up to 128~samples, or 512--bytes).
|
clock as well as the length of the FIFO (up to 128~samples, or 512--bytes).
|
To read the current speed and FIFO configuration, write an {\tt 0x00bf} value to
|
To read the current speed and FIFO configuration, write an {\tt 0x00bf} value to
|
the command register. This will cause the DATA register to be filled with
|
the command register. This will cause the DATA register to be filled with
|
the internal configuration register. Likewise writing a {\tt 0x0ff} to the
|
the internal configuration register. Likewise writing a {\tt 0x0ff} to the
|
CMD register will cause the current DATA value, or specifically those non-zero
|
CMD register will cause the current DATA value, or specifically those non-zero
|
parts, to be transferred to the internal configuration register possibly setting
|
parts, to be transferred to the internal configuration register possibly setting
|
the clock divider and/or the FIFO length.
|
the clock divider and/or the FIFO length.
|
|
|
As part of each write to the CMD register, the controller must also be told
|
As part of each write to the CMD register, the controller must also be told
|
which type of response to expect from the SDSPI card. Responses can be either
|
which type of response to expect from the SDSPI card. Responses can be either
|
R1 (single byte), R1b (single byte, followed by a variable delay), or R1
|
R1 (single byte), R1b (single byte, followed by a variable delay), or R1
|
followed by up to four bytes, such as the R2, R3, or R7 responses.
|
followed by up to four bytes, such as the R2, R3, or R7 responses.
|
(Expected responses for particular commands may be found in the SD
|
(Expected responses for particular commands may be found in the SD
|
Specifications documents.\footnote{This particular interface, and the examples
|
Specifications documents.\footnote{This particular interface, and the examples
|
using it, were built using the SD Specifications, Part 1: Physical Layer
|
using it, were built using the SD Specifications, Part 1: Physical Layer
|
Simplified Specification, Version 4.10, dated 22 January, 2013.}
|
Simplified Specification, Version 4.10, dated 22 January, 2013.}
|
|
|
Finally, individual commands may or may not use the FIFO. Commands that need
|
Finally, individual commands may or may not use the FIFO. Commands that need
|
use of the FIFO will be specified by the {\tt use\_fifo} bit of the CMD
|
use of the FIFO will be specified by the {\tt use\_fifo} bit of the CMD
|
register. Commands writing to the device will also set the {\tt fifo\_wr} bit
|
register. Commands writing to the device will also set the {\tt fifo\_wr} bit
|
of the CMD register, whereas commands simply reading from the fifo will set the
|
of the CMD register, whereas commands simply reading from the fifo will set the
|
{\tt use\_fifo} bit alone.
|
{\tt use\_fifo} bit alone.
|
|
|
The DATA register is used during these transactions to first provide the
|
The DATA register is used during these transactions to first provide the
|
argument to the CMD interaction, and second to provide a place to put the
|
argument to the CMD interaction, and second to provide a place to put the
|
R2, R3, or R7 response after the transaction has completed. The register will
|
R2, R3, or R7 response after the transaction has completed. The register will
|
be set to {\tt 0xffffffff} if not set by the response.
|
be set to {\tt 0xffffffff} if not set by the response.
|
|
|
Finally, this core supports two separate FIFO's. This allows a program to
|
Finally, this core supports two separate FIFO's. This allows a program to
|
fill (or read) one FIFO while the second FIFO can be read/written from the
|
fill (or read) one FIFO while the second FIFO can be read/written from the
|
SD card. The FIFO internal address will be cleared and reset to the beginning
|
SD card. The FIFO internal address will be cleared and reset to the beginning
|
upon any write to the CMD register. After clearing, the FIFO may be written
|
upon any write to the CMD register. After clearing, the FIFO may be written
|
(read) one value at a time. Reading both FIFO's in any interleaved fashion,
|
(read) one value at a time. Reading both FIFO's in any interleaved fashion,
|
however, is not allowed as they share a common internal address.
|
however, is not allowed as they share a common internal address.
|
|
|
Currently, the core will detect two types of errors in the interface. The
|
Currently, the core will detect two types of errors in the interface. The
|
first is a CRC error, and the second a timeout error. Either error will set
|
first is a CRC error, and the second a timeout error. Either error will set
|
an error bit in the CMD register. Once set, only writing the error bit back
|
an error bit in the CMD register. Once set, only writing the error bit back
|
to the CMD register will clear it.
|
to the CMD register will clear it.
|
|
|
Now, if this discussion isn't thoroughly confusing, let's move on to the
|
Now, if this discussion isn't thoroughly confusing, let's move on to the
|
Operation chapter to see some examples of how this might be used.
|
Operation chapter to see some examples of how this might be used.
|
|
|
\chapter{Operation}\label{ch:ops}
|
\chapter{Operation}\label{ch:ops}
|
This chapter will walk through some constants that can be used to simplify
|
This chapter will walk through some constants that can be used to simplify
|
interaction with the controller, the logic necessary to start up the card,
|
interaction with the controller, the logic necessary to start up the card,
|
to read its registers, and then examples of how to read and write sectors
|
to read its registers, and then examples of how to read and write sectors
|
from the SD Card using this interface.
|
from the SD Card using this interface.
|
|
|
\section{Constants}
|
\section{Constants}
|
Since so much of the interface is controlled by the CMD register, it helps to
|
Since so much of the interface is controlled by the CMD register, it helps to
|
define several constants which can be used when issuing commands to the SD
|
define several constants which can be used when issuing commands to the SD
|
Card. Lets discuss some of these constants.
|
Card. Lets discuss some of these constants.
|
|
|
First, as discussed in the last chapter, the SDSPI core maintains an auxiliary
|
First, as discussed in the last chapter, the SDSPI core maintains an auxiliary
|
register to handle FIFO length and clock speed. To set this register, we
|
register to handle FIFO length and clock speed. To set this register, we
|
define {\tt SD\_SETAUX} to {\tt 0x0ff}. Thus, when {\tt SD\_SETAUX} is written
|
define {\tt SD\_SETAUX} to {\tt 0x0ff}. Thus, when {\tt SD\_SETAUX} is written
|
to the CMD register, the value of the DATA register is transferred to the
|
to the CMD register, the value of the DATA register is transferred to the
|
internal configuration. Likewise, we also define {\tt SD\_READAUX} to
|
internal configuration. Likewise, we also define {\tt SD\_READAUX} to
|
{\tt 0x0bf}. When this value is written to the SD--Card, the internal
|
{\tt 0x0bf}. When this value is written to the SD--Card, the internal
|
configuration registers value will be copied to the DATA regiseter.
|
configuration registers value will be copied to the DATA regiseter.
|
\begin{tabular}{lll}
|
\begin{tabular}{lll}
|
{\tt \#define} & {\tt SD\_SETAUX} & {\tt 0x0ff} \\
|
{\tt \#define} & {\tt SD\_SETAUX} & {\tt 0x0ff} \\
|
{\tt \#define} & {\tt SD\_READAUX} & {\tt 0x0bf}
|
{\tt \#define} & {\tt SD\_READAUX} & {\tt 0x0bf}
|
\end{tabular}
|
\end{tabular}
|
|
|
Second, every command to the SD--Card starts with a single byte. Of that byte,
|
Second, every command to the SD--Card starts with a single byte. Of that byte,
|
bit-7 must be clear and bit 6 set. For this purpose, we define {\tt SD\_CMD}
|
bit-7 must be clear and bit 6 set. For this purpose, we define {\tt SD\_CMD}
|
to be {\tt 0x040}. Thus, {\tt SD\_CMD+0} can be used to send an SD command
|
to be {\tt 0x040}. Thus, {\tt SD\_CMD+0} can be used to send an SD command
|
{\tt CMD0}, and {\tt SD\_CMD+1} can be used to send an SD command {\tt CMD1}.
|
{\tt CMD0}, and {\tt SD\_CMD+1} can be used to send an SD command {\tt CMD1}.
|
\begin{tabular}{lll}
|
\begin{tabular}{lll}
|
{\tt \#define} & {\tt SD\_CMD} & {\tt 0x040}
|
{\tt \#define} & {\tt SD\_CMD} & {\tt 0x040}
|
\end{tabular}
|
\end{tabular}
|
|
|
Third, for those commands that will read an SD--Card register, such as those
|
Third, for those commands that will read an SD--Card register, such as those
|
expecting an R2, R3, or R7 response from the card, we define {\tt SD\_READREG}
|
expecting an R2, R3, or R7 response from the card, we define {\tt SD\_READREG}
|
to be {\tt 0x0200}. Thus, we can send a CMD8 by writing
|
to be {\tt 0x0200}. Thus, we can send a CMD8 by writing
|
\hbox{\tt SD\_CMD|SD\_READREG} to the port.
|
\hbox{\tt SD\_CMD|SD\_READREG} to the port.
|
\begin{tabular}{lll}
|
\begin{tabular}{lll}
|
{\tt \#define} & {\tt SD\_READREG} & {\tt 0x0200}
|
{\tt \#define} & {\tt SD\_READREG} & {\tt 0x0200}
|
\end{tabular}
|
\end{tabular}
|
|
|
The next thing we'll want to be able to do is use the FIFO. There are two
|
The next thing we'll want to be able to do is use the FIFO. There are two
|
types of commands that use the FIFO, those that read from the card and those
|
types of commands that use the FIFO, those that read from the card and those
|
that write to the card. Both need the FIFO bit set, so we'll set
|
that write to the card. Both need the FIFO bit set, so we'll set
|
{\tt SD\_FIFO\_OP} to {\tt 0x0800} to be a read operation from the card, and
|
{\tt SD\_FIFO\_OP} to {\tt 0x0800} to be a read operation from the card, and
|
the same but with the write bit set {\tt SD\_WRITEOP} will be set to
|
the same but with the write bit set {\tt SD\_WRITEOP} will be set to
|
{\tt 0x0c00} to write to the card.
|
{\tt 0x0c00} to write to the card.
|
|
|
\begin{tabular}{lll}
|
\begin{tabular}{lll}
|
{\tt \#define} & {\tt SD\_FIFO\_OP} & {\tt 0x800} \\
|
{\tt \#define} & {\tt SD\_FIFO\_OP} & {\tt 0x800} \\
|
{\tt \#define} & {\tt SD\_WRITEOP} & {\tt 0xc00}
|
{\tt \#define} & {\tt SD\_WRITEOP} & {\tt 0xc00}
|
\end{tabular}
|
\end{tabular}
|
|
|
Finally, we want to be able to choose which FIFO we are using. For this
|
Finally, we want to be able to choose which FIFO we are using. For this
|
purpose, we define {\tt SD\_ALTFIFO} to be {\tt 0x01000}. When this bitmask
|
purpose, we define {\tt SD\_ALTFIFO} to be {\tt 0x01000}. When this bitmask
|
is included in a command, FIFO number one will be used for the command data,
|
is included in a command, FIFO number one will be used for the command data,
|
otherwise FIFO zero. (Note that this is separate from the DATA register,
|
otherwise FIFO zero. (Note that this is separate from the DATA register,
|
which is still used for any command argument.)
|
which is still used for any command argument.)
|
|
|
\begin{tabular}{lll}
|
\begin{tabular}{lll}
|
{\tt \#define} & {\tt SD\_ALTFIFO} & {\tt 0x1000}
|
{\tt \#define} & {\tt SD\_ALTFIFO} & {\tt 0x1000}
|
\end{tabular}
|
\end{tabular}
|
|
|
Two other constants are necessary: {\tt SD\_BUSY}, set to {\tt 0x04000}, which
|
Two other constants are necessary: {\tt SD\_BUSY}, set to {\tt 0x04000}, which
|
can be used to test when the SD interface is still busy, and {\tt SD\_ERROR},
|
can be used to test when the SD interface is still busy, and {\tt SD\_ERROR},
|
set to {\tt 0x08000} which can be used to tell if an error has occurred.
|
set to {\tt 0x08000} which can be used to tell if an error has occurred.
|
Clearing an error may be done by writing {\tt SD\_ERROR} back to the card, but
|
Clearing an error may be done by writing {\tt SD\_ERROR} back to the card, but
|
to make things simpler we also create {\tt SD\_CLEARERR} for the same purpose.
|
to make things simpler we also create {\tt SD\_CLEARERR} for the same purpose.
|
|
|
\begin{tabular}{lll}
|
\begin{tabular}{lll}
|
{\tt \#define} & {\tt SD\_BUSY} & {\tt 0x4000} \\
|
{\tt \#define} & {\tt SD\_BUSY} & {\tt 0x4000} \\
|
{\tt \#define} & {\tt SD\_ERROR} & {\tt 0x8000} \\
|
{\tt \#define} & {\tt SD\_ERROR} & {\tt 0x8000} \\
|
{\tt \#define} & {\tt SD\_CLEARERR} & {\tt 0x8000}
|
{\tt \#define} & {\tt SD\_CLEARERR} & {\tt 0x8000}
|
\end{tabular}
|
\end{tabular}
|
|
|
The two most important commands, though, are probably going to be those that
|
The two most important commands, though, are probably going to be those that
|
read and write a sector. For these, we shall define {\tt SD\_READ\_SECTOR}
|
read and write a sector. For these, we shall define {\tt SD\_READ\_SECTOR}
|
and {\tt SD\_WRITE\_SECTOR}. As the first is a CMD17 to the card and the second
|
and {\tt SD\_WRITE\_SECTOR}. As the first is a CMD17 to the card and the second
|
a CMD24, these can be defined as:
|
a CMD24, these can be defined as:
|
|
|
\begin{tabular}{lll}
|
\begin{tabular}{lll}
|
{\tt \#define} & {\tt SD\_READ\_SECTOR} & {\tt ((SD\_CMD|SD\_CLEARERR|SD\_FIFO\_OP)+17)} \\
|
{\tt \#define} & {\tt SD\_READ\_SECTOR} & {\tt ((SD\_CMD|SD\_CLEARERR|SD\_FIFO\_OP)+17)} \\
|
{\tt \#define} & {\tt SD\_WRITE\_SECTOR} & {\tt ((SD\_CMD|SD\_CLEARERR|SD\_WRITEOP)+24)}
|
{\tt \#define} & {\tt SD\_WRITE\_SECTOR} & {\tt ((SD\_CMD|SD\_CLEARERR|SD\_WRITEOP)+24)}
|
\end{tabular}
|
\end{tabular}
|
|
|
`Or'ing the {\tt SD\_ALTFIFO} mask to either of these commands will cause the
|
`Or'ing the {\tt SD\_ALTFIFO} mask to either of these commands will cause the
|
interface to read from or write to the alternate FIFO.
|
interface to read from or write to the alternate FIFO.
|
|
|
As a very last \#define, we can define the macro {\tt SD\_WAIT\_WHILE\_BUSY}
|
As a very last \#define, we can define the macro {\tt SD\_WAIT\_WHILE\_BUSY}
|
to wait until the SD operation completes:
|
to wait until the SD operation completes:
|
|
|
\begin{tabular}{lll}
|
\begin{tabular}{lll}
|
{\tt \#define} & {\tt SD\_WAIT\_WHILE\_BUSY}&{\tt while(CMD \& SD\_BUSY)}
|
{\tt \#define} & {\tt SD\_WAIT\_WHILE\_BUSY}&{\tt while(CMD \& SD\_BUSY)}
|
\end{tabular}
|
\end{tabular}
|
|
|
Alternatively, we could wait for an interrupt instead since the SDSPI core
|
Alternatively, we could wait for an interrupt instead since the SDSPI core
|
will create an interrupt upon completion. For now, and for this example,
|
will create an interrupt upon completion. For now, and for this example,
|
we'll ignore interrupts.
|
we'll ignore interrupts.
|
|
|
\section{SD--Card Setup}
|
\section{SD--Card Setup}
|
Setting up an SD--Card takes a bit of work. There's a series of commands
|
Setting up an SD--Card takes a bit of work. There's a series of commands
|
and interactions that need to take place with the card before the card can
|
and interactions that need to take place with the card before the card can
|
be used. You can read about how to do this within the SD--Specification, so
|
be used. You can read about how to do this within the SD--Specification, so
|
we won't repeat the how's or why's here. Instead, let's focus for now on
|
we won't repeat the how's or why's here. Instead, let's focus for now on
|
how this interaction can be made to take place using this controller.
|
how this interaction can be made to take place using this controller.
|
|
|
The first step in any start up sequence is to clear the card from any
|
The first step in any start up sequence is to clear the card from any
|
prior condition. Hence we wait for the card to be no longer busy (it
|
prior condition. Hence we wait for the card to be no longer busy (it
|
shouldn't be busy anyway), and we then clear any errors:
|
shouldn't be busy anyway), and we then clear any errors:
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt CMD} \= {\tt SD\_CLEARERR};
|
{\tt CMD} \= {\tt = SD\_CLEARERR};
|
\end{tabbing}
|
\end{tabbing}
|
|
|
Now that the controller is idle (which it should've been from startup anyway),
|
Now that the controller is idle (which it should've been from startup anyway),
|
we can now set up our interface. For this, we'll set our clock rate to 400~KHz.
|
we can now set up our interface. For this, we'll set our clock rate to 400~KHz.
|
The clock division register, sometimes erroneously called the speed, is found
|
The clock division register, sometimes erroneously called the speed, is found
|
in the lower eight bits of the soft-core configuration register. The actual
|
in the lower eight bits of the soft-core configuration register. The actual
|
SPI clock frequency, given this value, will be:
|
SPI clock frequency, given this value, will be:
|
\begin{eqnarray}
|
\begin{eqnarray}
|
f_{\mbox{\tiny SDSPI}} &=& \frac{f_{\mbox{\tiny CLK}}}{2\left(\mbox{\tt CLKDIV}+1\right)}
|
f_{\mbox{\tiny SDSPI}} &=& \frac{f_{\mbox{\tiny CLK}}}{2\left(\mbox{\tt CLKDIV}+1\right)}
|
\end{eqnarray}
|
\end{eqnarray}
|
Hence, since the XuLA2-LX25 SoC runs at an 80~MHz clock, setting this value to
|
Hence, since the XuLA2-LX25 SoC runs at an 80~MHz clock, setting this value to
|
{\tt 0x63} sets the SPI clock to 400~kHz.
|
{\tt 0x63} sets the SPI clock to 400~kHz.
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt DATA} \= {\tt = 0x063}; \\
|
{\tt DATA} \= {\tt = 0x063}; \\
|
{\tt CMD} \> {\tt = SD\_SETAUX};
|
{\tt CMD} \> {\tt = SD\_SETAUX};
|
\end{tabbing}
|
\end{tabbing}
|
Note that we could have also set the higher order configuration bits to set
|
Note that we could have also set the higher order configuration bits to set
|
the size of the FIFO. In particular, the next four bits, bits 8--11, set
|
the size of the FIFO. In particular, the next four bits, bits 8--11, set
|
the FIFO length. Setting these to zero will cause the controller to ignore
|
the FIFO length. Setting these to zero will cause the controller to ignore
|
the change, whereas setting the value to three will set the FIFO length to
|
the change, whereas setting the value to three will set the FIFO length to
|
$4\cdot2^3$ bytes, and setting it to seven will set the FIFO length to the
|
$4\cdot2^3$ bytes, and setting it to seven will set the FIFO length to the
|
nominal $4\cdot 2^7$ or $512$~bytes.
|
nominal $4\cdot 2^7$ or $512$~bytes.
|
|
|
The controller is now ready to send commands to the SD card. The first command
|
The controller is now ready to send commands to the SD card. The first command
|
to the card is always a command zero, with zero data. This is sometimes
|
to the card is always a command zero, with zero data. This is sometimes
|
called the \hbox{\tt GO\_IDLE\_STATE} command. We then wait for the
|
called the \hbox{\tt GO\_IDLE\_STATE} command. We then wait for the
|
command to complete:
|
command to complete:
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt CMD} \> {\tt = SD\_CMD+0;} \\
|
{\tt CMD} \> {\tt = SD\_CMD+0;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;}
|
{\tt SD\_WAIT\_WHILE\_BUSY;}
|
\end{tabbing}
|
\end{tabbing}
|
The card should now be in its idle state.
|
The card should now be in its idle state.
|
|
|
The next part of the negotiation tells the card whether or not we are able to
|
The next part of the negotiation tells the card whether or not we are able to
|
handle high capacity cards. For this, we send a command one,
|
handle high capacity cards. For this, we send a command one,
|
\hbox{\tt SEND\_OP\_COND}, with an argument of {\tt 0x40000000} to tell it
|
\hbox{\tt SEND\_OP\_COND}, with an argument of {\tt 0x40000000} to tell it
|
that we are able to support high capacity cards. (An argument of zero would
|
that we are able to support high capacity cards. (An argument of zero would
|
mean that we could not.)
|
mean that we could not.)
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt DATA} \= {\tt = 0x40000000;} \\
|
{\tt DATA} \= {\tt = 0x40000000;} \\
|
{\tt CMD} \> {\tt = SD\_CMD+1;} \\
|
{\tt CMD} \> {\tt = SD\_CMD+1;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;}
|
{\tt SD\_WAIT\_WHILE\_BUSY;}
|
\end{tabbing}
|
\end{tabbing}
|
|
|
Then the card needs to know what voltage it will be run at. We communicate this
|
Then the card needs to know what voltage it will be run at. We communicate this
|
via a \hbox{\tt SEND\_IF\_COND} command, or CMD8. Since the XuLA2
|
via a \hbox{\tt SEND\_IF\_COND} command, or CMD8. Since the XuLA2
|
only operates the card at 3.3V, we tell the card we wish to run at 3.3V in the
|
only operates the card at 3.3V, we tell the card we wish to run at 3.3V in the
|
argument. The last eight bits of the argument, however, are simply to determine
|
argument. The last eight bits of the argument, however, are simply to determine
|
whether communication has taken place. We set these bits to {\tt 0x0a5},
|
whether communication has taken place. We set these bits to {\tt 0x0a5},
|
although they could be anything. The card will echo this value back in the
|
although they could be anything. The card will echo this value back in the
|
response:
|
response:
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt DATA} \= {\tt = 0x1a5;} \\
|
{\tt DATA} \= {\tt = 0x1a5;} \\
|
{\tt CMD} \> {\tt = SD\_CMD+8;} \\
|
{\tt CMD} \> {\tt = SD\_CMD+8;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\em // assert((DATA\&0x0ff)==0x01a5);}
|
{\em // assert((DATA\&0x0ff)==0x01a5);}
|
\end{tabbing}
|
\end{tabbing}
|
The card will also echo back the voltage range, if it accepts it. Thus,
|
The card will also echo back the voltage range, if it accepts it. Thus,
|
we should receive {\tt 0x01a5} as a response.
|
we should receive {\tt 0x01a5} as a response.
|
|
|
The card will now try to start up its own internal state machines. This could
|
The card will now try to start up its own internal state machines. This could
|
take a while. We therefore poll the device, and wait for its startup sequence
|
take a while. We therefore poll the device, and wait for its startup sequence
|
to complete:
|
to complete:
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt bool dev\_busy = false;} \\
|
{\tt bool dev\_busy = false;} \\
|
{\tt do \{}\=\\
|
{\tt do \{}\=\\
|
\> {\em // CMD55 gives us access to SD specific commands}\\
|
\> {\em // CMD55 gives us access to SD specific commands}\\
|
\> {\tt DATA = 0;}\\
|
\> {\tt DATA = 0;}\\
|
\> {\tt CMD = SD\_CMD+55;}\\
|
\> {\tt CMD = SD\_CMD+55;}\\
|
\> {\tt SD\_WAIT\_WHILE\_BUSY;}\\
|
\> {\tt SD\_WAIT\_WHILE\_BUSY;}\\
|
\\
|
\\
|
\> {\em // Now we can issue the ACMD41, to get the idle}\\
|
\> {\em // Now we can issue the ACMD41, to get the idle}\\
|
\> {\em // status}\\
|
\> {\em // status}\\
|
\> {\tt DATA = 0x40000000;} \\
|
\> {\tt DATA = 0x40000000;} \\
|
\> {\tt CMD = SD\_CMD+41;} \\
|
\> {\tt CMD = SD\_CMD+41;} \\
|
\> {\tt DATA} \= {\tt = 0x1a5;} \\
|
\> {\tt DATA} \= {\tt = 0x1a5;} \\
|
\> {\tt CMD} \> {\tt = SD\_CMD+8;} \\
|
\> {\tt CMD} \> {\tt = SD\_CMD+8;} \\
|
\> {\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
\> {\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
\\
|
\\
|
\> {\em // The R1 response can be found in the lower 8 bits}\\
|
\> {\em // The R1 response can be found in the lower 8 bits}\\
|
\> {\em // of the CMD register after the command is complete.}\\
|
\> {\em // of the CMD register after the command is complete.}\\
|
\> {\em // Bit 1 of R1 indicates the card hasn't finished its}\\
|
\> {\em // Bit 1 of R1 indicates the card hasn't finished its}\\
|
\> {\em // startup}\\
|
\> {\em // startup}\\
|
\> {\tt dev\_busy = CMD\&1;}\\
|
\> {\tt dev\_busy = CMD\&1;}\\
|
{\tt \} while(dev\_busy);}
|
{\tt \} while(dev\_busy);}
|
\end{tabbing}
|
\end{tabbing}
|
|
|
\section{Reading Card Registers}
|
\section{Reading Card Registers}
|
|
|
Once the card has started, we can request its operating conditions register,
|
Once the card has started, we can request its operating conditions register,
|
or OCR register as it is called. For this, we issue a {\tt READ\_OCR} command,
|
or OCR register as it is called. For this, we issue a {\tt READ\_OCR} command,
|
or CMD58 by number. Since this command returns a 32--bit value, we use the
|
or CMD58 by number. Since this command returns a 32--bit value, we use the
|
{\tt SD\_READREG} macro as well:
|
{\tt SD\_READREG} macro as well:
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt int OCR;}\\
|
{\tt int OCR;}\\
|
\\
|
\\
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt CMD} \> {\tt = (SD\_READREG|SD\_CMD)+58;} \\
|
{\tt CMD} \> {\tt = (SD\_READREG|SD\_CMD)+58;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt OCR} \= {\tt = DATA;}\\
|
{\tt OCR} \= {\tt = DATA;}\\
|
\end{tabbing}
|
\end{tabbing}
|
When I issue this command on my card, I get a {\tt 0xc0ff8000} response telling
|
When I issue this command on my card, I get a {\tt 0xc0ff8000} response telling
|
me that my card can handle between 2.7 and 3.6~Volts, that it is a higher
|
me that my card can handle between 2.7 and 3.6~Volts, that it is a higher
|
capacity card, and that it has completed its startup sequence.
|
capacity card, and that it has completed its startup sequence.
|
|
|
Now let's switch up to a higher speed, and read the 16--byte Card Specific
|
Now let's switch up to a higher speed, and read the 16--byte Card Specific
|
Data (CSD) register field from the card. First, the switch to a 20~MHz clock
|
Data (CSD) register field from the card. First, the switch to a 20~MHz clock
|
and a 16--byte fifo,
|
and a 16--byte fifo,
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt DATA} \= {\tt = 0x0201}; \\
|
{\tt DATA} \= {\tt = 0x0201}; \\
|
{\tt CMD} \> {\tt = SD\_SETAUX};
|
{\tt CMD} \> {\tt = SD\_SETAUX};
|
\end{tabbing}
|
\end{tabbing}
|
Remember that the {\tt 0x0200} switches to a FIFO of length~$2^2$ words, or
|
Remember that the {\tt 0x0200} switches to a FIFO of length~$2^2$ words, or
|
equivalently $4\cdot 2^2=16$ bytes. Likewise the {\tt 0x01} component switches
|
equivalently $4\cdot 2^2=16$ bytes. Likewise the {\tt 0x01} component switches
|
our frequency to 20~MHz. Now we can issue the {\tt SEND\_CSD\_COND}, or
|
our frequency to 20~MHz. Now we can issue the {\tt SEND\_CSD\_COND}, or
|
CMD9, command itself. Note that we didn't need to wait for the {\tt SD\_SETAUX}
|
CMD9, command itself. Note that we didn't need to wait for the {\tt SD\_SETAUX}
|
command to complete. Further, since this command is going to read from our
|
command to complete. Further, since this command is going to read from our
|
FIFO, we need to include the {\tt SD\_FIFO\_OP} part of the command:
|
FIFO, we need to include the {\tt SD\_FIFO\_OP} part of the command:
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt int CSD[4];}\\
|
{\tt int CSD[4];}\\
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt CMD} \> {\tt = (SD\_FIFO\_OP|SD\_CMD)+9;}
|
{\tt CMD} \> {\tt = (SD\_FIFO\_OP|SD\_CMD)+9;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt for(int i=0; i<4; i++) } \\
|
{\tt for(int i=0; i<4; i++) } \\
|
\> {\tt CSD[i] = FIFO[0];}
|
\> {\tt CSD[i] = FIFO[0];}
|
\end{tabbing}
|
\end{tabbing}
|
Once the command is complete, we can read the four 32--bit words of the CSD
|
Once the command is complete, we can read the four 32--bit words of the CSD
|
register from the FIFO, as shown above. Alternatively, we could have issued
|
register from the FIFO, as shown above. Alternatively, we could have issued
|
another command first, before reading that FIFO result.
|
another command first, before reading that FIFO result.
|
|
|
We could read the Card Identification (CID) register as well, but this would've
|
We could read the Card Identification (CID) register as well, but this would've
|
been the same sequence as above, save only that we would've written a
|
been the same sequence as above, save only that we would've written a
|
{\tt (SD\_READREG|SD\_CMD)+10)} to CMD.
|
{\tt (SD\_READREG|SD\_CMD)+10)} to CMD.
|
|
|
Reading the STATUS is similar, only the response to the {\tt SEND\_STATUS}
|
Reading the STATUS is similar, only the response to the {\tt SEND\_STATUS}
|
command is an 8--bit value from an R2 response, not the 32--bit values of
|
command is an 8--bit value from an R2 response, not the 32--bit values of
|
the R3 (OCR) or R7 responses. Still, the R2 response is provided in the
|
the R3 (OCR) or R7 responses. Still, the R2 response is provided in the
|
DATA register, so we only need to send {\tt (SD\_READREG|SD\_CMD)+13} to
|
DATA register, so we only need to send {\tt (SD\_READREG|SD\_CMD)+13} to
|
the CMD register in order to read its result from the DATA register. The status
|
the CMD register in order to read its result from the DATA register. The status
|
register will be returned in the top eight bits of the DATA register (the
|
register will be returned in the top eight bits of the DATA register (the
|
interface still reads 32--bits, even though the other 24 can be ignored), so:
|
interface still reads 32--bits, even though the other 24 can be ignored), so:
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt int card\_status;}\\
|
{\tt int card\_status;}\\
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt CMD} \> {\tt = (SD\_READREG|SD\_CMD)+13;}
|
{\tt CMD} \> {\tt = (SD\_READREG|SD\_CMD)+13;}
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt card\_status = DATA>>24;}
|
{\tt card\_status = DATA>>24;}
|
\end{tabbing}
|
\end{tabbing}
|
|
|
As a final register example, let's read the SD Card Configuration Register
|
As a final register example, let's read the SD Card Configuration Register
|
(SCR). This register is read in a fashion very similar to the CSD register,
|
(SCR). This register is read in a fashion very similar to the CSD register,
|
except that because of its width the FIFO needs to be set for a shorter
|
except that because of its width the FIFO needs to be set for a shorter
|
register width:
|
register width:
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt int SCR[2];}\\
|
{\tt int SCR[2];}\\
|
{\em // Set the FIFO length to two words, $2^1$.}\\
|
{\em // Set the FIFO length to two words, $2^1$.}\\
|
{\tt DATA} \= {\tt = 0x0100}; \\
|
{\tt DATA} \= {\tt = 0x0100}; \\
|
{\tt CMD} \> {\tt = SD\_SETAUX};\\
|
{\tt CMD} \> {\tt = SD\_SETAUX};\\
|
{\em // Issue an ALT command, to get the other command set.}\\
|
{\em // Issue an ALT command, to get the other command set.}\\
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt CMD} \> {\tt = (SD\_CMD)+55;}\\
|
{\tt CMD} \> {\tt = (SD\_CMD)+55;}\\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\em // Now get the SCR register.}\\
|
{\em // Now get the SCR register.}\\
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt DATA} \= {\tt = 0;} \\
|
{\tt CMD} \> {\tt = (SD\_FIFO\_OP|SD\_CMD)+51;}\\
|
{\tt CMD} \> {\tt = (SD\_FIFO\_OP|SD\_CMD)+51;}\\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt for(int i=0; i<2; i++) } \\
|
{\tt for(int i=0; i<2; i++) } \\
|
\> {\tt SCR[i] = FIFO[0];}\\
|
\> {\tt SCR[i] = FIFO[0];}\\
|
\end{tabbing}
|
\end{tabbing}
|
|
|
|
|
\section{Reading and Writing}
|
\section{Reading and Writing}
|
|
|
For our first example, let's read the boot sector from our card. For this,
|
For our first example, let's read the boot sector from our card. For this,
|
we set our FIFO back to 128~words (512~bytes), and then issue a read sector
|
we set our FIFO back to 128~words (512~bytes), and then issue a read sector
|
command:
|
command:
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt void} \= {\tt read(int sector\_num, int *buf) \{}\\
|
{\tt void} \= {\tt read(int sector\_num, int *buf) \{}\\
|
\> {\em // Set the FIFO length to 128 words, $2^7$.}\\
|
\> {\em // Set the FIFO length to 128 words, $2^7$.}\\
|
\> {\tt DATA} \= {\tt = 0x0700}; \\
|
\> {\tt DATA} \= {\tt = 0x0700}; \\
|
\> {\tt CMD} \> {\tt = SD\_SETAUX};\\
|
\> {\tt CMD} \> {\tt = SD\_SETAUX};\\
|
\> {\em // Read from the requested sector}\\
|
\> {\em // Read from the requested sector}\\
|
\> {\tt DATA} \= {\tt = sector\_num;} \\
|
\> {\tt DATA} \= {\tt = sector\_num;} \\
|
\> {\tt CMD} \> {\tt = SD\_READ\_SECTOR;}\\
|
\> {\tt CMD} \> {\tt = SD\_READ\_SECTOR;}\\
|
\> {\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
\> {\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
\> {\tt for(int i=0; i<128; i++) } \\
|
\> {\tt for(int i=0; i<128; i++) } \\
|
\> \> {\tt buf[i] = FIFO[0];}\\
|
\> \> {\tt buf[i] = FIFO[0];}\\
|
{\tt \}}
|
{\tt \}}
|
\end{tabbing}
|
\end{tabbing}
|
|
|
We could also write to any sector on the card in a very similar fashion:
|
We could also write to any sector on the card in a very similar fashion:
|
\begin{tabbing}
|
\begin{tabbing}
|
{\tt void} \= {\tt write(int sector\_num, int *buf) \{}\\
|
{\tt void} \= {\tt write(int sector\_num, int *buf) \{}\\
|
\> {\em // Set the FIFO length to 128 words, $2^7$.}\\
|
\> {\em // Set the FIFO length to 128 words, $2^7$.}\\
|
\> {\tt DATA} \= {\tt = 0x0700}; \\
|
\> {\tt DATA} \= {\tt = 0x0700}; \\
|
\> {\tt CMD} \> {\tt = SD\_SETAUX};\\
|
\> {\tt CMD} \> {\tt = SD\_SETAUX};\\
|
\> {\em // Fill the FIFO with our data}\\
|
\> {\em // Fill the FIFO with our data}\\
|
\> {\tt for(int i=0; i<128; i++) } \\
|
\> {\tt for(int i=0; i<128; i++) } \\
|
\> \> {\tt FIFO[0] = buf[i];}\\
|
\> \> {\tt FIFO[0] = buf[i];}\\
|
\> {\em // Issue the write command}\\
|
\> {\em // Issue the write command}\\
|
\> {\tt DATA} \= {\tt = sector\_num;} \\
|
\> {\tt DATA} \= {\tt = sector\_num;} \\
|
\> {\tt CMD} \> {\tt = SD\_WRITE\_SECTOR;}\\
|
\> {\tt CMD} \> {\tt = SD\_WRITE\_SECTOR;}\\
|
\> {\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
\> {\tt SD\_WAIT\_WHILE\_BUSY;} \\
|
{\tt \}}
|
{\tt \}}
|
\end{tabbing}
|
\end{tabbing}
|
|
|
As mentioned in the introductory chapter, this interface does not support
|
As mentioned in the introductory chapter, this interface does not support
|
reading or writing multiple blocks at once. Hence, I expect all interaction
|
reading or writing multiple blocks at once. Hence, I expect all interaction
|
using this card controller to be accomplished through these two commands:
|
using this card controller to be accomplished through these two commands:
|
reading a single sector, and writing to a single sector.
|
reading a single sector, and writing to a single sector.
|
|
|
\chapter{Registers}\label{ch:regs}
|
\chapter{Registers}\label{ch:regs}
|
|
|
As mentioned in the last two chapters, the SDSPI core has only four registers,
|
As mentioned in the last two chapters, the SDSPI core has only four registers,
|
and one internal register. These are shown in Tbl.~\ref{tbl:ioregs}.
|
and one internal register. These are shown in Tbl.~\ref{tbl:ioregs}.
|
\begin{table}[htbp]
|
\begin{table}[htbp]
|
\begin{center}\begin{reglist}
|
\begin{center}\begin{reglist}
|
CMD &{\tt 0x00} & 32 & R/W & SDSPI Command register\\\hline
|
CMD &{\tt 0x00} & 32 & R/W & SDSPI Command register\\\hline
|
DAT &{\tt 0x01} & 32 & R/W & SDSPI return data/argument register\\\hline
|
DAT &{\tt 0x01} & 32 & R/W & SDSPI return data/argument register\\\hline
|
FIFO[0] &{\tt 0x02} & 32 & R/W & FIFO[0] data\\\hline
|
FIFO[0] &{\tt 0x02} & 32 & R/W & FIFO[0] data\\\hline
|
FIFO[1] &{\tt 0x03} & 32 & R/W & FIFO[1] data\\\hline
|
FIFO[1] &{\tt 0x03} & 32 & R/W & FIFO[1] data\\\hline
|
CONFIG & & 12 & R/W & Internal configuration register\\\hline
|
CONFIG & & 12 & R/W & Internal configuration register\\\hline
|
\end{reglist}
|
\end{reglist}
|
\caption{I/O Peripheral Registers}\label{tbl:ioregs}
|
\caption{I/O Peripheral Registers}\label{tbl:ioregs}
|
\end{center}\end{table}
|
\end{center}\end{table}
|
The most powerful of these is the command register, CMD, so we'll spend most of
|
The most powerful of these is the command register, CMD, so we'll spend most of
|
our time discussing that one.
|
our time discussing that one.
|
|
|
\section{CMD Register}
|
\section{CMD Register}
|
Writes to the CMD register will cause the device to act, or if the device is
|
Writes to the CMD register will cause the device to act, or if the device is
|
already busy then any writes will be ignored. The CMD register itself is
|
already busy then any writes will be ignored. The CMD register itself is
|
composed of several packed bit fields, as shown in Fig.~\ref{fig:CMD}.
|
composed of several packed bit fields, as shown in Fig.~\ref{fig:CMD}.
|
\begin{figure}\begin{center}
|
\begin{figure}\begin{center}
|
\begin{bytefield}[endianness=big]{32}
|
\begin{bytefield}[endianness=big]{32}
|
\bitheader{0-31}\\
|
\bitheader{0-31}\\
|
\bitbox{15}{Unused}
|
\bitbox{15}{Unused}
|
\bitbox{1}{C}
|
\bitbox{1}{C}
|
\bitbox{1}{E}
|
\bitbox{1}{E}
|
\bitbox{1}{B}
|
\bitbox{1}{B}
|
\bitbox{1}{0}
|
\bitbox{1}{0}
|
\bitbox{1}{I}
|
\bitbox{1}{I}
|
\bitbox{1}{F}
|
\bitbox{1}{F}
|
\bitbox{1}{W}
|
\bitbox{1}{W}
|
\bitbox{2}{R}
|
\bitbox{2}{R}
|
\bitbox{8}{R1/CMD}
|
\bitbox{8}{R1/CMD}
|
\end{bytefield}
|
\end{bytefield}
|
\caption{CMD Register fields}\label{fig:CMD}
|
\caption{CMD Register fields}\label{fig:CMD}
|
\end{center}\end{figure}
|
\end{center}\end{figure}
|
Perhaps the most important of these is the R1/CMD field. If bits 7--6 are
|
Perhaps the most important of these is the R1/CMD field. If bits 7--6 are
|
the two bits 2'b01, then the write is a command and the bottom six bits
|
the two bits 2'b01, then the write is a command and the bottom six bits
|
specify the rest of the 8--bit command identifier. Once the command is
|
specify the rest of the 8--bit command identifier. Once the command is
|
complete, these 8--bits represent the R1 response from the device. R1
|
complete, these 8--bits represent the R1 response from the device. R1
|
should be one while the device is still starting, or zero in the case of no
|
should be one while the device is still starting, or zero in the case of no
|
error. Further interpretation of this value may be found in the SD--Card
|
error. Further interpretation of this value may be found in the SD--Card
|
Specification.
|
Specification.
|
|
|
Of next importance is the $R$ field. This specifies the response the
|
Of next importance is the $R$ field. This specifies the response the
|
controller should expect from the card given the command that was issued
|
controller should expect from the card given the command that was issued
|
to the card. There are three possible values for this field: $2'b00$, meaning
|
to the card. There are three possible values for this field: $2'b00$, meaning
|
the controller should expect an R1 response, $2'b01$, meaning the controller
|
the controller should expect an R1 response, $2'b01$, meaning the controller
|
should expect an R1b response, and $2'b10$ meaning the controller should
|
should expect an R1b response, and $2'b10$ meaning the controller should
|
expect an R2/R3/R7 32--bit response.
|
expect an R2/R3/R7 32--bit response.
|
|
|
The $F$, or FIFO, field should be set if the command being given requires the
|
The $F$, or FIFO, field should be set if the command being given requires the
|
use of the FIFO. $W$ should be set at the same time if the controller will be
|
use of the FIFO. $W$ should be set at the same time if the controller will be
|
writing to the card from the FIFO, and cleared if the controller will be
|
writing to the card from the FIFO, and cleared if the controller will be
|
reading from the card into the FIFO. Finally, $I$ specifies which FIFO will
|
reading from the card into the FIFO. Finally, $I$ specifies which FIFO will
|
be used: 0 for the primary, or 1 for the alternate.
|
be used: 0 for the primary, or 1 for the alternate.
|
|
|
While the command is running, the BUSY or $B$ bit will be set.
|
While the command is running, the BUSY or $B$ bit will be set.
|
|
|
Once the command has completed, the $E$ bit may be set if either the command
|
Once the command has completed, the $E$ bit may be set if either the command
|
timed out, or a CRC error was noted while reading from the card. (To detect
|
timed out, or a CRC error was noted while reading from the card. (To detect
|
a CRC error when writing to the card, check the R1 response according to the
|
a CRC error when writing to the card, check the R1 response according to the
|
SD Card specification.) Errors may be cleared by writing a 1 to this bit.
|
SD Card specification.) Errors may be cleared by writing a 1 to this bit.
|
Until such time as an error is cleared, the error condition will simply
|
Until such time as an error is cleared, the error condition will simply
|
persist.
|
persist.
|
|
|
\section{DATA Register}
|
\section{DATA Register}
|
Compared to the CMD register, the DATA register is quite simple. Like the
|
Compared to the CMD register, the DATA register is quite simple. Like the
|
CMD register, the DATA register may only be written when the interface is
|
CMD register, the DATA register may only be written when the interface is
|
idle. When issuing a command to the device, the 32--bit argument for the
|
idle. When issuing a command to the device, the 32--bit argument for the
|
command is taken from the DATA register. When reading the results of a device
|
command is taken from the DATA register. When reading the results of a device
|
command, the DATA register will contain the R2 response in the upper 8--bits,
|
command, the DATA register will contain the R2 response in the upper 8--bits,
|
or an R3 or R7 response in the full 32--bits.
|
or an R3 or R7 response in the full 32--bits.
|
|
|
\section{FIFO Registers}
|
\section{FIFO Registers}
|
The SDSPI controller maintains two 128~word (512~byte) FIFOs. Reads from the
|
The SDSPI controller maintains two 128~word (512~byte) FIFOs. Reads from the
|
card will read data into one of the two FIFO's, whereas writes to the card will
|
card will read data into one of the two FIFO's, whereas writes to the card will
|
write data out from one of the FIFO's. Which FIFO the card uses is determined
|
write data out from one of the FIFO's. Which FIFO the card uses is determined
|
by the $I$ bit in the CMD register (above).
|
by the $I$ bit in the CMD register (above).
|
|
|
Further, upon any write to the CMD register, the FIFO address will be set
|
Further, upon any write to the CMD register, the FIFO address will be set
|
to point to the beginning of the FIFO.
|
to point to the beginning of the FIFO.
|
|
|
The purpose of the FIFO's is to allow one to issue a command to read into one
|
The purpose of the FIFO's is to allow one to issue a command to read into one
|
FIFO, then when that command is complete to read into a second FIFO. While
|
FIFO, then when that command is complete to read into a second FIFO. While
|
the second command is ongoing, a CPU or DMA may read the data out of the first
|
the second command is ongoing, a CPU or DMA may read the data out of the first
|
FIFO and place it wherever into memory. Then, when the second read is complete,
|
FIFO and place it wherever into memory. Then, when the second read is complete,
|
a third read may be issued into the first buffer while the data is read out of
|
a third read may be issued into the first buffer while the data is read out of
|
the second and so forth.
|
the second and so forth.
|
|
|
This interleaving approach, sometimes called ping-pong buffering, can also be
|
This interleaving approach, sometimes called ping-pong buffering, can also be
|
used for writing: Write into one FIFO, issue a write command, write into the
|
used for writing: Write into one FIFO, issue a write command, write into the
|
second FIFO, wait for the first write command to complete, issue a second
|
second FIFO, wait for the first write command to complete, issue a second
|
write command, and so forth.
|
write command, and so forth.
|
|
|
One item to note before closing: there is only one internal address register
|
One item to note before closing: there is only one internal address register
|
when accessing the FIFO from the wishbone bus. Attempts to read from or write
|
when accessing the FIFO from the wishbone bus. Attempts to read from or write
|
to either FIFO from the wishbone bus will increment this address register.
|
to either FIFO from the wishbone bus will increment this address register.
|
Interleaved read, or write attempts, such as reading one item from
|
Interleaved read, or write attempts, such as reading one item from
|
FIFO[0] and writing another item to FIFO[1], will each increment the internal
|
FIFO[0] and writing another item to FIFO[1], will each increment the internal
|
address pointer so that the result is likely to be undesirable. For this
|
address pointer so that the result is likely to be undesirable. For this
|
reason, it is recommended that only one FIFO be read from or written by the
|
reason, it is recommended that only one FIFO be read from or written by the
|
wishbone bus at a time.
|
wishbone bus at a time.
|
|
|
\section{CONFIG Register}
|
\section{CONFIG Register}
|
The CONFIG register controls the SPI clock rate and the FIFO size.
|
The CONFIG register controls the SPI clock rate and the FIFO size.
|
Specifically, with regards to the FIFO size, it controls how many bytes will
|
Specifically, with regards to the FIFO size, it controls how many bytes will
|
be written into the FIFO (which is really of a fixed size) before the expecting
|
be written into the FIFO (which is really of a fixed size) before the expecting
|
a CRC, or equivalently how many bytes to read out of the FIFO before adding a
|
a CRC, or equivalently how many bytes to read out of the FIFO before adding a
|
CRC. The fields of this register are shown in Fig.~\ref{fig:CONFIG}.
|
CRC. The fields of this register are shown in Fig.~\ref{fig:CONFIG}.
|
\begin{figure}\begin{center}
|
\begin{figure}\begin{center}
|
\begin{bytefield}[endianness=big]{32}
|
\begin{bytefield}[endianness=big]{32}
|
\bitheader{0-31}\\
|
\bitheader{0-31}\\
|
\bitbox{8}{Unused}
|
\bitbox{8}{Unused}
|
\bitbox{8}{Max LgFIFO}
|
\bitbox{8}{Max LgFIFO}
|
\bitbox{8}{LgFIFO}
|
\bitbox{8}{LgFIFO}
|
\bitbox{2}{0}
|
\bitbox{2}{0}
|
\bitbox{6}{CLKDIV}
|
\bitbox{6}{CLKDIV}
|
\end{bytefield}
|
\end{bytefield}
|
\caption{CONFIG Register fields}\label{fig:CONFIG}
|
\caption{CONFIG Register fields}\label{fig:CONFIG}
|
\end{center}\end{figure}
|
\end{center}\end{figure}
|
|
|
The CLKDIV field sets a divisor from the current clock to create a SPI clock.
|
The CLKDIV field sets a divisor from the current clock to create a SPI clock.
|
The minimum value of this field is `1', corresponding to dividing the input
|
The minimum value of this field is `1', corresponding to dividing the input
|
clock by `4'. As discussed earlier, the input clock will be divided by
|
clock by `4'. As discussed earlier, the input clock will be divided by
|
twice this field plus one. Hence, setting this field to one will cause the
|
twice this field plus one. Hence, setting this field to one will cause the
|
original clock to be divided by $2(1+{\tt CLKDIV})$ or $4$. Thus an 80~MHz
|
original clock to be divided by $2(1+{\tt CLKDIV})$ or $4$. Thus an 80~MHz
|
input clock will become a 20~MHz SPI clock. Setting this value to zero will
|
input clock will become a 20~MHz SPI clock. Setting this value to zero will
|
cause the set to be ignored.
|
cause the set to be ignored.
|
|
|
The LgFIFO field sets the log, base two, of the FIFO size. The actual FIFO
|
The LgFIFO field sets the log, base two, of the FIFO size. The actual FIFO
|
size used will be $2^{\mbox{\tiny LGFIFO}}$ words. The maximum size the
|
size used will be $2^{\mbox{\tiny LGFIFO}}$ words. The maximum size the
|
device will support is returned by the {\tt Max LgFIFO} field, which is
|
device will support is returned by the {\tt Max LgFIFO} field, which is
|
currently set to $7$ for a 128~word (512~byte) FIFO.
|
currently set to $7$ for a 128~word (512~byte) FIFO.
|
|
|
To set the CONFIG register, first set the DATA register to the new config
|
To set the CONFIG register, first set the DATA register to the new config
|
value (or zero for the fields that will not change), and then write
|
value (or zero for the fields that will not change), and then write
|
{\tt 0x0ff} to the CMD register. Likewise, to read the CONFIG register
|
{\tt 0x0ff} to the CMD register. Likewise, to read the CONFIG register
|
write a {\tt 0x0bf} to the CMD register and read the CONFIG register from the
|
write a {\tt 0x0bf} to the CMD register and read the CONFIG register from the
|
DATA register.
|
DATA register.
|
|
|
\chapter{Wishbone Datasheet}\label{ch:wb}
|
\chapter{Wishbone Datasheet}\label{ch:wb}
|
Tbl.~\ref{tbl:wishbone}
|
Tbl.~\ref{tbl:wishbone}
|
\begin{table}[htbp]
|
\begin{table}[htbp]
|
\begin{center}
|
\begin{center}
|
\begin{wishboneds}
|
\begin{wishboneds}
|
Revision level of wishbone & WB B4 spec \\\hline
|
Revision level of wishbone & WB B4 spec \\\hline
|
Type of interface & Slave, (Block/pipelined) Read/Write \\\hline
|
Type of interface & Slave, (Block/pipelined) Read/Write \\\hline
|
Port size & 32--bit \\\hline
|
Port size & 32--bit \\\hline
|
Port granularity & 32--bit \\\hline
|
Port granularity & 32--bit \\\hline
|
Maximum Operand Size & 32--bit \\\hline
|
Maximum Operand Size & 32--bit \\\hline
|
Data transfer ordering & Big Endian \\\hline
|
Data transfer ordering & Big Endian \\\hline
|
Clock constraints & (See below)\\\hline
|
Clock constraints & (See below)\\\hline
|
Signal Names & \begin{tabular}{ll}
|
Signal Names & \begin{tabular}{ll}
|
Signal Name & Wishbone Equivalent \\\hline
|
Signal Name & Wishbone Equivalent \\\hline
|
{\tt i\_clk} & {\tt CLK\_I} \\
|
{\tt i\_clk} & {\tt CLK\_I} \\
|
{\tt i\_wb\_cyc} & {\tt CYC\_I} \\
|
{\tt i\_wb\_cyc} & {\tt CYC\_I} \\
|
{\tt i\_wb\_stb} & {\tt STB\_I} \\
|
{\tt i\_wb\_stb} & {\tt STB\_I} \\
|
{\tt i\_wb\_we} & {\tt WE\_I} \\
|
{\tt i\_wb\_we} & {\tt WE\_I} \\
|
{\tt i\_wb\_addr} & {\tt ADR\_I} \\
|
{\tt i\_wb\_addr} & {\tt ADR\_I} \\
|
{\tt i\_wb\_data} & {\tt DAT\_I} \\
|
{\tt i\_wb\_data} & {\tt DAT\_I} \\
|
{\tt o\_wb\_ack} & {\tt ACK\_O} \\
|
{\tt o\_wb\_ack} & {\tt ACK\_O} \\
|
{\tt o\_wb\_stall} & {\tt STALL\_O} \\
|
{\tt o\_wb\_stall} & {\tt STALL\_O} \\
|
{\tt o\_wb\_data} & {\tt DAT\_O}
|
{\tt o\_wb\_data} & {\tt DAT\_O}
|
\end{tabular}\\\hline
|
\end{tabular}\\\hline
|
\end{wishboneds}
|
\end{wishboneds}
|
\caption{Wishbone Slave Datasheet}\label{tbl:wishbone}
|
\caption{Wishbone Slave Datasheet}\label{tbl:wishbone}
|
\end{center}\end{table}
|
\end{center}\end{table}
|
is required by the wishbone specification, and so it is included here. Note
|
is required by the wishbone specification, and so it is included here. Note
|
that all wishbone operations may be pipelined, to include FIFO operations,
|
that all wishbone operations may be pipelined, to include FIFO operations,
|
for speed.
|
for speed.
|
|
|
The particular constraint on the clock is not really a wishbone constraint, but
|
The particular constraint on the clock is not really a wishbone constraint, but
|
rather an SD--Card constraint. Not all cards can handle clocks faster than
|
rather an SD--Card constraint. Not all cards can handle clocks faster than
|
25~MHz. For this reason, the wishbone clock, which forms the master clock for
|
25~MHz. For this reason, the wishbone clock, which forms the master clock for
|
this entire controller, must be divided down so that the SPI clock is within
|
this entire controller, must be divided down so that the SPI clock is within
|
the limits the card can handle.
|
the limits the card can handle.
|
|
|
\chapter{Clocks}\label{ch:clk}
|
\chapter{Clocks}\label{ch:clk}
|
|
|
This core is based upon the XuLA2-LX25 SoC design. The XuLA2 development board
|
This core is based upon the XuLA2-LX25 SoC design. The XuLA2 development board
|
contains one external 12~MHz clock, which is internally boosted within the SoC
|
contains one external 12~MHz clock, which is internally boosted within the SoC
|
to 80~MHz. This clock is divided by a programmable divider, often set to
|
to 80~MHz. This clock is divided by a programmable divider, often set to
|
four, to create the 20~MHz clock used to drive the device. (Maximum device
|
four, to create the 20~MHz clock used to drive the device. (Maximum device
|
speed is usually 25MHz, although some devices can run at 50~MHz.) This
|
speed is usually 25MHz, although some devices can run at 50~MHz.) This
|
controller does not support setting the SPI clock frequency any faster than
|
controller does not support setting the SPI clock frequency any faster than
|
one quarter of the input clock rate.
|
one quarter of the input clock rate.
|
|
|
\chapter{I/O Ports}\label{ch:io}
|
\chapter{I/O Ports}\label{ch:io}
|
|
|
Table.~\ref{tbl:ioports}
|
Table.~\ref{tbl:ioports}
|
\begin{table}[htbp]
|
\begin{table}[htbp]
|
\begin{center}
|
\begin{center}
|
\begin{portlist}
|
\begin{portlist}
|
i\_clk & 1 & Input & Clock\\\hline\hline
|
i\_clk & 1 & Input & Clock\\\hline\hline
|
i\_wb\_cyc & 1 & Output & Wishbone bus cycle active\\\hline
|
i\_wb\_cyc & 1 & Output & Wishbone bus cycle active\\\hline
|
i\_wb\_stb & 1 & Output & Wishbone Strobe, true one clock only for each interaction\\\hline
|
i\_wb\_stb & 1 & Output & Wishbone Strobe, true one clock only for each interaction\\\hline
|
i\_wb\_we & 1 & Output & Wishbone Write-Enable line\\\hline
|
i\_wb\_we & 1 & Output & Wishbone Write-Enable line\\\hline
|
i\_wb\_addr & 2 & Output & Selects our I/O register\\\hline
|
i\_wb\_addr & 2 & Output & Selects our I/O register\\\hline
|
i\_wb\_data & 32 & Output & Incoming wishbone bus data\\\hline
|
i\_wb\_data & 32 & Output & Incoming wishbone bus data\\\hline
|
o\_wb\_ack & 1 & Output & Acknowledge a WB request, always true one clock after the request\\\hline
|
o\_wb\_ack & 1 & Output & Acknowledge a WB request, always true one clock after the request\\\hline
|
o\_wb\_stall & 1 & Output & Always zero\\\hline
|
o\_wb\_stall & 1 & Output & Always zero\\\hline
|
o\_wb\_data & 32 & Output & 32--bit wishbone data response\\\hline\hline
|
o\_wb\_data & 32 & Output & 32--bit wishbone data response\\\hline\hline
|
o\_cs\_n & 1 & Output & Chip--select and SPI request line\\\hline
|
o\_cs\_n & 1 & Output & Chip--select and SPI request line\\\hline
|
o\_sck & 1 & Output & SD Card clock\\\hline
|
o\_sck & 1 & Output & SD Card clock\\\hline
|
o\_mosi & 1 & Output & Output data wire to the SD Card\\\hline
|
o\_mosi & 1 & Output & Output data wire to the SD Card\\\hline
|
i\_miso & 1 & Input & Input data wire from the SD Card\\\hline\hline
|
i\_miso & 1 & Input & Input data wire from the SD Card\\\hline\hline
|
o\_int & 1 & Output & An interrupt line to the CPU controller\\\hline
|
o\_int & 1 & Output & An interrupt line to the CPU controller\\\hline
|
i\_bus\_grant & 1 & Input & True if the SDSPI controller is controlling the bus\\\hline
|
i\_bus\_grant & 1 & Input & True if the SDSPI controller is controlling the bus\\\hline
|
o\_debug & 32 & Output & See Verilog for details\\\hline
|
o\_debug & 32 & Output & See Verilog for details\\\hline
|
\end{portlist}
|
\end{portlist}
|
\caption{List of IO ports}\label{tbl:ioports}
|
\caption{List of IO ports}\label{tbl:ioports}
|
\end{center}\end{table}
|
\end{center}\end{table}
|
lists all of the input and output ports to this core. You may notice these
|
lists all of the input and output ports to this core. You may notice these
|
inputs and outputs are divided into sections: the master clock, the wishbone
|
inputs and outputs are divided into sections: the master clock, the wishbone
|
bus, the SPI interface to the card, and three other wires. Of these, the
|
bus, the SPI interface to the card, and three other wires. Of these, the
|
last two chapters discussed the wishbone bus interface and the clock. The
|
last two chapters discussed the wishbone bus interface and the clock. The
|
SPI interface should be fairly straightforward, so we'll move on and discuss
|
SPI interface should be fairly straightforward, so we'll move on and discuss
|
the other three wires.
|
the other three wires.
|
|
|
This controller supports an interrupt line, {\tt o\_int}. Upon completion of
|
This controller supports an interrupt line, {\tt o\_int}. Upon completion of
|
any operation, when the SPI chip select line is deactivated (raised high),
|
any operation, when the SPI chip select line is deactivated (raised high),
|
{\tt o\_int} will be strobed for one cycle. It is up to the logic using this
|
{\tt o\_int} will be strobed for one cycle. It is up to the logic using this
|
chip to catch and use that interrupt line or ignore it. In particular, it is
|
chip to catch and use that interrupt line or ignore it. In particular, it is
|
possible to use that interrupt line to trigger a DMA service to move data
|
possible to use that interrupt line to trigger a DMA service to move data
|
in or out of the FIFO, although the details of that are beyond this discussion
|
in or out of the FIFO, although the details of that are beyond this discussion
|
here.
|
here.
|
|
|
The second wire, {\tt i\_bus\_grant}, exists because this controller is
|
The second wire, {\tt i\_bus\_grant}, exists because this controller is
|
expected to operate together with other SPI controllers that may also wish
|
expected to operate together with other SPI controllers that may also wish
|
to drive the same three wires ({\tt o\_sck} and {\tt o\_mosi} to the device,
|
to drive the same three wires ({\tt o\_sck} and {\tt o\_mosi} to the device,
|
and {\tt i\_miso} from the device). When the controller therefore lowers the
|
and {\tt i\_miso} from the device). When the controller therefore lowers the
|
{\tt o\_cs\_n} line to make it active, it then waits for {\tt i\_bus\_grant}
|
{\tt o\_cs\_n} line to make it active, it then waits for {\tt i\_bus\_grant}
|
to go high. This is its signal, from the outside world, that its chip has been
|
to go high. This is its signal, from the outside world, that its chip has been
|
selected and that it is now driving the {\tt o\_sck} and {\tt o\_mosi} pins.
|
selected and that it is now driving the {\tt o\_sck} and {\tt o\_mosi} pins.
|
Should you not need this in your environment, you can simply leave this line
|
Should you not need this in your environment, you can simply leave this line
|
wired high.
|
wired high.
|
|
|
The final bus of 32--wires, {\tt o\_debug}, is defined internally and used
|
The final bus of 32--wires, {\tt o\_debug}, is defined internally and used
|
when/if necessary to debug the core and watch what is going on within it.
|
when/if necessary to debug the core and watch what is going on within it.
|
These wires may be left unconnected in most implementations, as they are not
|
These wires may be left unconnected in most implementations, as they are not
|
necessary for using the actually controller.
|
necessary for using the actually controller.
|
|
|
% Appendices
|
% Appendices
|
% Index
|
% Index
|
\end{document}
|
\end{document}
|
|
|
|
|
|
|